summaryrefslogtreecommitdiffstats
path: root/contrib/tools
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-08-28 14:27:58 +0300
committerrobot-piglet <[email protected]>2025-08-28 14:57:06 +0300
commit81d828c32c8d5477cb2f0ce5da06a1a8d9392ca3 (patch)
tree3081d566f0d5158d76e9093261344f6406fd09f7 /contrib/tools
parent77ea11423f959e51795cc3ef36a48d808b4ffb98 (diff)
Intermediate changes
commit_hash:d5b1af16dbe9030537a04c27eb410c88c2f496cd
Diffstat (limited to 'contrib/tools')
-rw-r--r--contrib/tools/swig/.yandex_meta/__init__.py64
-rw-r--r--contrib/tools/swig/.yandex_meta/devtools.copyrights.report145
-rw-r--r--contrib/tools/swig/.yandex_meta/devtools.licenses.report369
-rw-r--r--contrib/tools/swig/.yandex_meta/licenses.list.txt935
-rw-r--r--contrib/tools/swig/.yandex_meta/override.nix24
-rw-r--r--contrib/tools/swig/ANNOUNCE38
-rw-r--r--contrib/tools/swig/CHANGES29923
-rw-r--r--contrib/tools/swig/CHANGES.current34
-rw-r--r--contrib/tools/swig/COPYRIGHT115
-rw-r--r--contrib/tools/swig/INSTALL226
-rw-r--r--contrib/tools/swig/LICENSE22
-rw-r--r--contrib/tools/swig/LICENSE-GPL674
-rw-r--r--contrib/tools/swig/LICENSE-UNIVERSITIES95
-rw-r--r--contrib/tools/swig/Lib/allkw.swg34
-rw-r--r--contrib/tools/swig/Lib/attribute.i21
-rw-r--r--contrib/tools/swig/Lib/carrays.i122
-rw-r--r--contrib/tools/swig/Lib/cdata.i50
-rw-r--r--contrib/tools/swig/Lib/cmalloc.i110
-rw-r--r--contrib/tools/swig/Lib/constraints.i217
-rw-r--r--contrib/tools/swig/Lib/cpointer.i186
-rw-r--r--contrib/tools/swig/Lib/cstring.i12
-rw-r--r--contrib/tools/swig/Lib/cwstring.i11
-rw-r--r--contrib/tools/swig/Lib/director_common.swg15
-rw-r--r--contrib/tools/swig/Lib/director_guard.swg105
-rw-r--r--contrib/tools/swig/Lib/exception.i341
-rw-r--r--contrib/tools/swig/Lib/go/.yandex_meta/licenses.list.txt916
-rw-r--r--contrib/tools/swig/Lib/go/argcargv.i62
-rw-r--r--contrib/tools/swig/Lib/go/cdata.i57
-rw-r--r--contrib/tools/swig/Lib/go/director.swg80
-rw-r--r--contrib/tools/swig/Lib/go/exception.i7
-rw-r--r--contrib/tools/swig/Lib/go/go.swg747
-rw-r--r--contrib/tools/swig/Lib/go/gokw.swg33
-rw-r--r--contrib/tools/swig/Lib/go/goruntime.swg217
-rw-r--r--contrib/tools/swig/Lib/go/gostring.swg29
-rw-r--r--contrib/tools/swig/Lib/go/std_array.i43
-rw-r--r--contrib/tools/swig/Lib/go/std_common.i4
-rw-r--r--contrib/tools/swig/Lib/go/std_deque.i1
-rw-r--r--contrib/tools/swig/Lib/go/std_except.i31
-rw-r--r--contrib/tools/swig/Lib/go/std_list.i41
-rw-r--r--contrib/tools/swig/Lib/go/std_map.i70
-rw-r--r--contrib/tools/swig/Lib/go/std_pair.i36
-rw-r--r--contrib/tools/swig/Lib/go/std_string.i162
-rw-r--r--contrib/tools/swig/Lib/go/std_vector.i92
-rw-r--r--contrib/tools/swig/Lib/go/stl.i10
-rw-r--r--contrib/tools/swig/Lib/go/swigmove.i15
-rw-r--r--contrib/tools/swig/Lib/go/typemaps.i298
-rw-r--r--contrib/tools/swig/Lib/go/ya.make24
-rw-r--r--contrib/tools/swig/Lib/intrusive_ptr.i58
-rw-r--r--contrib/tools/swig/Lib/inttypes.i60
-rw-r--r--contrib/tools/swig/Lib/java/.yandex_meta/licenses.list.txt916
-rw-r--r--contrib/tools/swig/Lib/java/argcargv.i36
-rw-r--r--contrib/tools/swig/Lib/java/arrays_java.i398
-rw-r--r--contrib/tools/swig/Lib/java/boost_intrusive_ptr.i484
-rw-r--r--contrib/tools/swig/Lib/java/boost_shared_ptr.i337
-rw-r--r--contrib/tools/swig/Lib/java/cdata.i78
-rw-r--r--contrib/tools/swig/Lib/java/director.swg541
-rw-r--r--contrib/tools/swig/Lib/java/enums.swg116
-rw-r--r--contrib/tools/swig/Lib/java/enumsimple.swg71
-rw-r--r--contrib/tools/swig/Lib/java/enumtypesafe.swg117
-rw-r--r--contrib/tools/swig/Lib/java/enumtypeunsafe.swg72
-rw-r--r--contrib/tools/swig/Lib/java/java.swg1466
-rw-r--r--contrib/tools/swig/Lib/java/javahead.swg91
-rw-r--r--contrib/tools/swig/Lib/java/javakw.swg70
-rw-r--r--contrib/tools/swig/Lib/java/std_array.i62
-rw-r--r--contrib/tools/swig/Lib/java/std_auto_ptr.i41
-rw-r--r--contrib/tools/swig/Lib/java/std_common.i5
-rw-r--r--contrib/tools/swig/Lib/java/std_deque.i1
-rw-r--r--contrib/tools/swig/Lib/java/std_except.i32
-rw-r--r--contrib/tools/swig/Lib/java/std_list.i225
-rw-r--r--contrib/tools/swig/Lib/java/std_map.i215
-rw-r--r--contrib/tools/swig/Lib/java/std_pair.i37
-rw-r--r--contrib/tools/swig/Lib/java/std_set.i207
-rw-r--r--contrib/tools/swig/Lib/java/std_shared_ptr.i2
-rw-r--r--contrib/tools/swig/Lib/java/std_string.i121
-rw-r--r--contrib/tools/swig/Lib/java/std_string_view.i138
-rw-r--r--contrib/tools/swig/Lib/java/std_unique_ptr.i63
-rw-r--r--contrib/tools/swig/Lib/java/std_unordered_map.i215
-rw-r--r--contrib/tools/swig/Lib/java/std_unordered_set.i203
-rw-r--r--contrib/tools/swig/Lib/java/std_vector.i203
-rw-r--r--contrib/tools/swig/Lib/java/std_wstring.i180
-rw-r--r--contrib/tools/swig/Lib/java/stl.i10
-rw-r--r--contrib/tools/swig/Lib/java/swiginterface.i79
-rw-r--r--contrib/tools/swig/Lib/java/swigmove.i16
-rw-r--r--contrib/tools/swig/Lib/java/typemaps.i549
-rw-r--r--contrib/tools/swig/Lib/java/various.i194
-rw-r--r--contrib/tools/swig/Lib/java/ya.make24
-rw-r--r--contrib/tools/swig/Lib/math.i89
-rw-r--r--contrib/tools/swig/Lib/perl5/.yandex_meta/licenses.list.txt916
-rw-r--r--contrib/tools/swig/Lib/perl5/Makefile.pl19
-rw-r--r--contrib/tools/swig/Lib/perl5/argcargv.i30
-rw-r--r--contrib/tools/swig/Lib/perl5/attribute.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/carrays.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/cmalloc.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/cpointer.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/cstring.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/director.swg317
-rw-r--r--contrib/tools/swig/Lib/perl5/exception.i5
-rw-r--r--contrib/tools/swig/Lib/perl5/extra-install.list2
-rw-r--r--contrib/tools/swig/Lib/perl5/factory.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/noembed.h116
-rw-r--r--contrib/tools/swig/Lib/perl5/perl5.swg42
-rw-r--r--contrib/tools/swig/Lib/perl5/perlerrors.swg36
-rw-r--r--contrib/tools/swig/Lib/perl5/perlfragments.swg23
-rw-r--r--contrib/tools/swig/Lib/perl5/perlhead.swg94
-rw-r--r--contrib/tools/swig/Lib/perl5/perlinit.swg78
-rw-r--r--contrib/tools/swig/Lib/perl5/perlkw.swg251
-rw-r--r--contrib/tools/swig/Lib/perl5/perlmacros.swg2
-rw-r--r--contrib/tools/swig/Lib/perl5/perlmain.i77
-rw-r--r--contrib/tools/swig/Lib/perl5/perlopers.swg54
-rw-r--r--contrib/tools/swig/Lib/perl5/perlprimtypes.swg364
-rw-r--r--contrib/tools/swig/Lib/perl5/perlrun.swg493
-rw-r--r--contrib/tools/swig/Lib/perl5/perlruntime.swg8
-rw-r--r--contrib/tools/swig/Lib/perl5/perlstrings.swg59
-rw-r--r--contrib/tools/swig/Lib/perl5/perltypemaps.swg104
-rw-r--r--contrib/tools/swig/Lib/perl5/perluserdir.swg2
-rw-r--r--contrib/tools/swig/Lib/perl5/reference.i261
-rw-r--r--contrib/tools/swig/Lib/perl5/std_auto_ptr.i39
-rw-r--r--contrib/tools/swig/Lib/perl5/std_common.i28
-rw-r--r--contrib/tools/swig/Lib/perl5/std_deque.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/std_except.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/std_list.i377
-rw-r--r--contrib/tools/swig/Lib/perl5/std_map.i71
-rw-r--r--contrib/tools/swig/Lib/perl5/std_pair.i36
-rw-r--r--contrib/tools/swig/Lib/perl5/std_string.i2
-rw-r--r--contrib/tools/swig/Lib/perl5/std_string_view.i2
-rw-r--r--contrib/tools/swig/Lib/perl5/std_unique_ptr.i69
-rw-r--r--contrib/tools/swig/Lib/perl5/std_vector.i592
-rw-r--r--contrib/tools/swig/Lib/perl5/stl.i10
-rw-r--r--contrib/tools/swig/Lib/perl5/swigmove.i1
-rw-r--r--contrib/tools/swig/Lib/perl5/typemaps.i371
-rw-r--r--contrib/tools/swig/Lib/perl5/ya.make24
-rw-r--r--contrib/tools/swig/Lib/python/.yandex_meta/licenses.list.txt916
-rw-r--r--contrib/tools/swig/Lib/python/README103
-rw-r--r--contrib/tools/swig/Lib/python/argcargv.i89
-rw-r--r--contrib/tools/swig/Lib/python/attribute.i1
-rw-r--r--contrib/tools/swig/Lib/python/boost_shared_ptr.i411
-rw-r--r--contrib/tools/swig/Lib/python/builtin.swg778
-rw-r--r--contrib/tools/swig/Lib/python/carrays.i9
-rw-r--r--contrib/tools/swig/Lib/python/ccomplex.i27
-rw-r--r--contrib/tools/swig/Lib/python/cmalloc.i1
-rw-r--r--contrib/tools/swig/Lib/python/complex.i6
-rw-r--r--contrib/tools/swig/Lib/python/cpointer.i1
-rw-r--r--contrib/tools/swig/Lib/python/cstring.i1
-rw-r--r--contrib/tools/swig/Lib/python/cwstring.i3
-rw-r--r--contrib/tools/swig/Lib/python/director.swg359
-rw-r--r--contrib/tools/swig/Lib/python/director_py_mutex.swg24
-rw-r--r--contrib/tools/swig/Lib/python/embed.i113
-rw-r--r--contrib/tools/swig/Lib/python/exception.i6
-rw-r--r--contrib/tools/swig/Lib/python/factory.i1
-rw-r--r--contrib/tools/swig/Lib/python/file.i41
-rw-r--r--contrib/tools/swig/Lib/python/implicit.i7
-rw-r--r--contrib/tools/swig/Lib/python/pyabc.i14
-rw-r--r--contrib/tools/swig/Lib/python/pyapi.swg30
-rw-r--r--contrib/tools/swig/Lib/python/pybackward.swg45
-rw-r--r--contrib/tools/swig/Lib/python/pybuffer.i203
-rw-r--r--contrib/tools/swig/Lib/python/pyclasses.swg157
-rw-r--r--contrib/tools/swig/Lib/python/pycomplex.swg90
-rw-r--r--contrib/tools/swig/Lib/python/pycontainer.swg871
-rw-r--r--contrib/tools/swig/Lib/python/pydocs.swg45
-rw-r--r--contrib/tools/swig/Lib/python/pyerrors.swg112
-rw-r--r--contrib/tools/swig/Lib/python/pyfragments.swg23
-rw-r--r--contrib/tools/swig/Lib/python/pyhead.swg105
-rw-r--r--contrib/tools/swig/Lib/python/pyinit.swg326
-rw-r--r--contrib/tools/swig/Lib/python/pyiterators.swg453
-rw-r--r--contrib/tools/swig/Lib/python/pymacros.swg4
-rw-r--r--contrib/tools/swig/Lib/python/pyname_compat.i78
-rw-r--r--contrib/tools/swig/Lib/python/pyopers.swg264
-rw-r--r--contrib/tools/swig/Lib/python/pyprimtypes.swg362
-rw-r--r--contrib/tools/swig/Lib/python/pyrun.swg2108
-rw-r--r--contrib/tools/swig/Lib/python/pyruntime.swg61
-rw-r--r--contrib/tools/swig/Lib/python/pystdcommon.swg265
-rw-r--r--contrib/tools/swig/Lib/python/pystrings.swg117
-rw-r--r--contrib/tools/swig/Lib/python/python.swg59
-rw-r--r--contrib/tools/swig/Lib/python/pythonkw.swg140
-rw-r--r--contrib/tools/swig/Lib/python/pythreads.swg68
-rw-r--r--contrib/tools/swig/Lib/python/pytypemaps.swg103
-rw-r--r--contrib/tools/swig/Lib/python/pyuserdir.swg242
-rw-r--r--contrib/tools/swig/Lib/python/pywstrings.swg89
-rw-r--r--contrib/tools/swig/Lib/python/std_alloc.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_array.i119
-rw-r--r--contrib/tools/swig/Lib/python/std_auto_ptr.i39
-rw-r--r--contrib/tools/swig/Lib/python/std_basic_string.i89
-rw-r--r--contrib/tools/swig/Lib/python/std_char_traits.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_common.i74
-rw-r--r--contrib/tools/swig/Lib/python/std_complex.i27
-rw-r--r--contrib/tools/swig/Lib/python/std_container.i2
-rw-r--r--contrib/tools/swig/Lib/python/std_deque.i27
-rw-r--r--contrib/tools/swig/Lib/python/std_except.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_filesystem.i127
-rw-r--r--contrib/tools/swig/Lib/python/std_ios.i3
-rw-r--r--contrib/tools/swig/Lib/python/std_iostream.i8
-rw-r--r--contrib/tools/swig/Lib/python/std_list.i28
-rw-r--r--contrib/tools/swig/Lib/python/std_map.i304
-rw-r--r--contrib/tools/swig/Lib/python/std_multimap.i83
-rw-r--r--contrib/tools/swig/Lib/python/std_multiset.i30
-rw-r--r--contrib/tools/swig/Lib/python/std_pair.i206
-rw-r--r--contrib/tools/swig/Lib/python/std_set.i56
-rw-r--r--contrib/tools/swig/Lib/python/std_shared_ptr.i2
-rw-r--r--contrib/tools/swig/Lib/python/std_sstream.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_streambuf.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_string.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_string_view.i135
-rw-r--r--contrib/tools/swig/Lib/python/std_unique_ptr.i69
-rw-r--r--contrib/tools/swig/Lib/python/std_unordered_map.i290
-rw-r--r--contrib/tools/swig/Lib/python/std_unordered_multimap.i90
-rw-r--r--contrib/tools/swig/Lib/python/std_unordered_multiset.i37
-rw-r--r--contrib/tools/swig/Lib/python/std_unordered_set.i56
-rw-r--r--contrib/tools/swig/Lib/python/std_vector.i34
-rw-r--r--contrib/tools/swig/Lib/python/std_vectora.i31
-rw-r--r--contrib/tools/swig/Lib/python/std_wios.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_wiostream.i10
-rw-r--r--contrib/tools/swig/Lib/python/std_wsstream.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_wstreambuf.i1
-rw-r--r--contrib/tools/swig/Lib/python/std_wstring.i3
-rw-r--r--contrib/tools/swig/Lib/python/stl.i10
-rw-r--r--contrib/tools/swig/Lib/python/swigmove.i1
-rw-r--r--contrib/tools/swig/Lib/python/typemaps.i144
-rw-r--r--contrib/tools/swig/Lib/python/wchar.i21
-rw-r--r--contrib/tools/swig/Lib/python/ya.make22
-rw-r--r--contrib/tools/swig/Lib/runtime.swg38
-rw-r--r--contrib/tools/swig/Lib/shared_ptr.i57
-rw-r--r--contrib/tools/swig/Lib/std/README22
-rw-r--r--contrib/tools/swig/Lib/std/_std_deque.i139
-rw-r--r--contrib/tools/swig/Lib/std/std_alloc.i77
-rw-r--r--contrib/tools/swig/Lib/std/std_array.i85
-rw-r--r--contrib/tools/swig/Lib/std/std_basic_string.i276
-rw-r--r--contrib/tools/swig/Lib/std/std_char_traits.i140
-rw-r--r--contrib/tools/swig/Lib/std/std_common.i250
-rw-r--r--contrib/tools/swig/Lib/std/std_container.i169
-rw-r--r--contrib/tools/swig/Lib/std/std_deque.i127
-rw-r--r--contrib/tools/swig/Lib/std/std_except.i73
-rw-r--r--contrib/tools/swig/Lib/std/std_ios.i262
-rw-r--r--contrib/tools/swig/Lib/std/std_iostream.i343
-rw-r--r--contrib/tools/swig/Lib/std/std_list.i148
-rw-r--r--contrib/tools/swig/Lib/std/std_map.i125
-rw-r--r--contrib/tools/swig/Lib/std/std_multimap.i100
-rw-r--r--contrib/tools/swig/Lib/std/std_multiset.i83
-rw-r--r--contrib/tools/swig/Lib/std/std_pair.i163
-rw-r--r--contrib/tools/swig/Lib/std/std_queue.i129
-rw-r--r--contrib/tools/swig/Lib/std/std_set.i122
-rw-r--r--contrib/tools/swig/Lib/std/std_sstream.i195
-rw-r--r--contrib/tools/swig/Lib/std/std_stack.i128
-rw-r--r--contrib/tools/swig/Lib/std/std_streambuf.i94
-rw-r--r--contrib/tools/swig/Lib/std/std_string.i13
-rw-r--r--contrib/tools/swig/Lib/std/std_unordered_map.i122
-rw-r--r--contrib/tools/swig/Lib/std/std_unordered_multimap.i85
-rw-r--r--contrib/tools/swig/Lib/std/std_unordered_multiset.i85
-rw-r--r--contrib/tools/swig/Lib/std/std_unordered_set.i119
-rw-r--r--contrib/tools/swig/Lib/std/std_vector.i225
-rw-r--r--contrib/tools/swig/Lib/std/std_vectora.i7
-rw-r--r--contrib/tools/swig/Lib/std/std_wios.i7
-rw-r--r--contrib/tools/swig/Lib/std/std_wiostream.i7
-rw-r--r--contrib/tools/swig/Lib/std/std_wsstream.i7
-rw-r--r--contrib/tools/swig/Lib/std/std_wstreambuf.i7
-rw-r--r--contrib/tools/swig/Lib/std/std_wstring.i14
-rw-r--r--contrib/tools/swig/Lib/std_except.i57
-rw-r--r--contrib/tools/swig/Lib/stdint.i106
-rw-r--r--contrib/tools/swig/Lib/stl.i7
-rw-r--r--contrib/tools/swig/Lib/swig.swg710
-rw-r--r--contrib/tools/swig/Lib/swigarch.i33
-rw-r--r--contrib/tools/swig/Lib/swigcompat.swg27
-rw-r--r--contrib/tools/swig/Lib/swigerrors.swg15
-rw-r--r--contrib/tools/swig/Lib/swigfragments.swg129
-rw-r--r--contrib/tools/swig/Lib/swiginit.swg233
-rw-r--r--contrib/tools/swig/Lib/swiglabels.swg129
-rw-r--r--contrib/tools/swig/Lib/swigrun.i8
-rw-r--r--contrib/tools/swig/Lib/swigrun.swg581
-rw-r--r--contrib/tools/swig/Lib/swigwarn.swg315
-rw-r--r--contrib/tools/swig/Lib/swigwarnings.swg131
-rw-r--r--contrib/tools/swig/Lib/typemaps/README54
-rw-r--r--contrib/tools/swig/Lib/typemaps/attribute.swg150
-rw-r--r--contrib/tools/swig/Lib/typemaps/carrays.swg114
-rw-r--r--contrib/tools/swig/Lib/typemaps/cdata_begin.swg12
-rw-r--r--contrib/tools/swig/Lib/typemaps/cdata_end.swg71
-rw-r--r--contrib/tools/swig/Lib/typemaps/cmalloc.swg110
-rw-r--r--contrib/tools/swig/Lib/typemaps/cpointer.swg157
-rw-r--r--contrib/tools/swig/Lib/typemaps/cstring.swg9
-rw-r--r--contrib/tools/swig/Lib/typemaps/cstrings.swg288
-rw-r--r--contrib/tools/swig/Lib/typemaps/cwstring.swg10
-rw-r--r--contrib/tools/swig/Lib/typemaps/enumint.swg39
-rw-r--r--contrib/tools/swig/Lib/typemaps/exception.swg87
-rw-r--r--contrib/tools/swig/Lib/typemaps/factory.swg88
-rw-r--r--contrib/tools/swig/Lib/typemaps/fragments.swg231
-rw-r--r--contrib/tools/swig/Lib/typemaps/implicit.swg208
-rw-r--r--contrib/tools/swig/Lib/typemaps/inoutlist.swg279
-rw-r--r--contrib/tools/swig/Lib/typemaps/misctypes.swg21
-rw-r--r--contrib/tools/swig/Lib/typemaps/primtypes.swg369
-rw-r--r--contrib/tools/swig/Lib/typemaps/ptrtypes.swg228
-rw-r--r--contrib/tools/swig/Lib/typemaps/std_except.swg37
-rw-r--r--contrib/tools/swig/Lib/typemaps/std_string.swg25
-rw-r--r--contrib/tools/swig/Lib/typemaps/std_string_view.swg16
-rw-r--r--contrib/tools/swig/Lib/typemaps/std_strings.swg99
-rw-r--r--contrib/tools/swig/Lib/typemaps/std_wstring.swg26
-rw-r--r--contrib/tools/swig/Lib/typemaps/string.swg34
-rw-r--r--contrib/tools/swig/Lib/typemaps/strings.swg649
-rw-r--r--contrib/tools/swig/Lib/typemaps/swigmacros.swg228
-rw-r--r--contrib/tools/swig/Lib/typemaps/swigmove.swg21
-rw-r--r--contrib/tools/swig/Lib/typemaps/swigobject.swg37
-rw-r--r--contrib/tools/swig/Lib/typemaps/swigtype.swg698
-rw-r--r--contrib/tools/swig/Lib/typemaps/swigtypemaps.swg174
-rw-r--r--contrib/tools/swig/Lib/typemaps/typemaps.swg153
-rw-r--r--contrib/tools/swig/Lib/typemaps/valtypes.swg216
-rw-r--r--contrib/tools/swig/Lib/typemaps/void.swg84
-rw-r--r--contrib/tools/swig/Lib/typemaps/wstring.swg36
-rw-r--r--contrib/tools/swig/Lib/unique_ptr.swg22
-rw-r--r--contrib/tools/swig/Lib/wchar.i11
-rw-r--r--contrib/tools/swig/Lib/windows.i152
-rw-r--r--contrib/tools/swig/README139
-rw-r--r--contrib/tools/swig/RELEASENOTES555
-rw-r--r--contrib/tools/swig/Source/CParse/cparse.h83
-rw-r--r--contrib/tools/swig/Source/CParse/cscanner.c1105
-rw-r--r--contrib/tools/swig/Source/CParse/parser.y7858
-rw-r--r--contrib/tools/swig/Source/CParse/templ.c1424
-rw-r--r--contrib/tools/swig/Source/CParse/util.c126
-rw-r--r--contrib/tools/swig/Source/DOH/README124
-rw-r--r--contrib/tools/swig/Source/DOH/base.c938
-rw-r--r--contrib/tools/swig/Source/DOH/doh.h507
-rw-r--r--contrib/tools/swig/Source/DOH/dohint.h131
-rw-r--r--contrib/tools/swig/Source/DOH/file.c342
-rw-r--r--contrib/tools/swig/Source/DOH/fio.c610
-rw-r--r--contrib/tools/swig/Source/DOH/hash.c584
-rw-r--r--contrib/tools/swig/Source/DOH/list.c372
-rw-r--r--contrib/tools/swig/Source/DOH/memory.c284
-rw-r--r--contrib/tools/swig/Source/DOH/string.c1287
-rw-r--r--contrib/tools/swig/Source/DOH/void.c96
-rw-r--r--contrib/tools/swig/Source/Doxygen/csharpdoc.cxx989
-rw-r--r--contrib/tools/swig/Source/Doxygen/csharpdoc.h243
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxycommands.h174
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxyentity.cxx69
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxyentity.h45
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxyparser.cxx1493
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxyparser.h377
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxytranslator.cxx69
-rw-r--r--contrib/tools/swig/Source/Doxygen/doxytranslator.h90
-rw-r--r--contrib/tools/swig/Source/Doxygen/javadoc.cxx849
-rw-r--r--contrib/tools/swig/Source/Doxygen/javadoc.h169
-rw-r--r--contrib/tools/swig/Source/Doxygen/pydoc.cxx993
-rw-r--r--contrib/tools/swig/Source/Doxygen/pydoc.h208
-rw-r--r--contrib/tools/swig/Source/Include/swigconfig.h102
-rw-r--r--contrib/tools/swig/Source/Include/swigwarn.h342
-rw-r--r--contrib/tools/swig/Source/Modules/README9
-rw-r--r--contrib/tools/swig/Source/Modules/allocate.cxx1605
-rw-r--r--contrib/tools/swig/Source/Modules/c.cxx3122
-rw-r--r--contrib/tools/swig/Source/Modules/contract.cxx358
-rw-r--r--contrib/tools/swig/Source/Modules/csharp.cxx4912
-rw-r--r--contrib/tools/swig/Source/Modules/d.cxx4865
-rw-r--r--contrib/tools/swig/Source/Modules/directors.cxx270
-rw-r--r--contrib/tools/swig/Source/Modules/emit.cxx534
-rw-r--r--contrib/tools/swig/Source/Modules/go.cxx5669
-rw-r--r--contrib/tools/swig/Source/Modules/guile.cxx1642
-rw-r--r--contrib/tools/swig/Source/Modules/interface.cxx210
-rw-r--r--contrib/tools/swig/Source/Modules/java.cxx4969
-rw-r--r--contrib/tools/swig/Source/Modules/javascript.cxx3257
-rw-r--r--contrib/tools/swig/Source/Modules/lang.cxx3768
-rw-r--r--contrib/tools/swig/Source/Modules/lua.cxx2239
-rw-r--r--contrib/tools/swig/Source/Modules/main.cxx1400
-rw-r--r--contrib/tools/swig/Source/Modules/mzscheme.cxx761
-rw-r--r--contrib/tools/swig/Source/Modules/nested.cxx406
-rw-r--r--contrib/tools/swig/Source/Modules/ocaml.cxx1837
-rw-r--r--contrib/tools/swig/Source/Modules/octave.cxx1574
-rw-r--r--contrib/tools/swig/Source/Modules/overload.cxx872
-rw-r--r--contrib/tools/swig/Source/Modules/perl5.cxx2513
-rw-r--r--contrib/tools/swig/Source/Modules/php.cxx2717
-rw-r--r--contrib/tools/swig/Source/Modules/python.cxx5927
-rw-r--r--contrib/tools/swig/Source/Modules/r.cxx2850
-rw-r--r--contrib/tools/swig/Source/Modules/ruby.cxx3468
-rw-r--r--contrib/tools/swig/Source/Modules/scilab.cxx1223
-rw-r--r--contrib/tools/swig/Source/Modules/swigmain.cxx278
-rw-r--r--contrib/tools/swig/Source/Modules/swigmod.h461
-rw-r--r--contrib/tools/swig/Source/Modules/tcl8.cxx1293
-rw-r--r--contrib/tools/swig/Source/Modules/typepass.cxx1195
-rw-r--r--contrib/tools/swig/Source/Modules/utils.cxx226
-rw-r--r--contrib/tools/swig/Source/Modules/xml.cxx297
-rw-r--r--contrib/tools/swig/Source/Preprocessor/cpp.c2198
-rw-r--r--contrib/tools/swig/Source/Preprocessor/expr.c515
-rw-r--r--contrib/tools/swig/Source/Preprocessor/preprocessor.h41
-rw-r--r--contrib/tools/swig/Source/README15
-rw-r--r--contrib/tools/swig/Source/Swig/cwrap.c1664
-rw-r--r--contrib/tools/swig/Source/Swig/deprecate.c107
-rw-r--r--contrib/tools/swig/Source/Swig/error.c350
-rw-r--r--contrib/tools/swig/Source/Swig/extend.c140
-rw-r--r--contrib/tools/swig/Source/Swig/fragment.c188
-rw-r--r--contrib/tools/swig/Source/Swig/getopt.c104
-rw-r--r--contrib/tools/swig/Source/Swig/include.c379
-rw-r--r--contrib/tools/swig/Source/Swig/misc.c1503
-rw-r--r--contrib/tools/swig/Source/Swig/naming.c1949
-rw-r--r--contrib/tools/swig/Source/Swig/parms.c350
-rw-r--r--contrib/tools/swig/Source/Swig/scanner.c1810
-rw-r--r--contrib/tools/swig/Source/Swig/stype.c1503
-rw-r--r--contrib/tools/swig/Source/Swig/swig.h456
-rw-r--r--contrib/tools/swig/Source/Swig/swigfile.h41
-rw-r--r--contrib/tools/swig/Source/Swig/swigopt.h18
-rw-r--r--contrib/tools/swig/Source/Swig/swigparm.h40
-rw-r--r--contrib/tools/swig/Source/Swig/swigscan.h117
-rw-r--r--contrib/tools/swig/Source/Swig/swigtree.h54
-rw-r--r--contrib/tools/swig/Source/Swig/swigwrap.h31
-rw-r--r--contrib/tools/swig/Source/Swig/symbol.c2243
-rw-r--r--contrib/tools/swig/Source/Swig/tree.c430
-rw-r--r--contrib/tools/swig/Source/Swig/typemap.c2227
-rw-r--r--contrib/tools/swig/Source/Swig/typeobj.c1404
-rw-r--r--contrib/tools/swig/Source/Swig/typesys.c2301
-rw-r--r--contrib/tools/swig/Source/Swig/wrapfunc.c520
-rw-r--r--contrib/tools/swig/TODO226
-rw-r--r--contrib/tools/swig/patches/fix-unused-parameter.patch33
-rw-r--r--contrib/tools/swig/patches/gostring.patch18
-rw-r--r--contrib/tools/swig/patches/issue-2881.patch611
-rw-r--r--contrib/tools/swig/swig_lib.cpp28
-rw-r--r--contrib/tools/swig/ya.make124
408 files changed, 186194 insertions, 0 deletions
diff --git a/contrib/tools/swig/.yandex_meta/__init__.py b/contrib/tools/swig/.yandex_meta/__init__.py
new file mode 100644
index 00000000000..260aa6863a2
--- /dev/null
+++ b/contrib/tools/swig/.yandex_meta/__init__.py
@@ -0,0 +1,64 @@
+import os
+
+from devtools.yamaker.arcpath import ArcPath
+from devtools.yamaker.modules import Library
+from devtools.yamaker.project import GNUMakeNixProject
+
+
+SWIG_LANGS = {
+ "go",
+ "java",
+ "perl5",
+ "python",
+}
+
+
+def post_install(self):
+ with self.yamakes["."] as swig:
+ swig.SRCS.add("swig_lib.cpp")
+ # replace bison-generated code with its original
+ os.remove(f"{self.dstdir}/Source/CParse/parser.c")
+ os.remove(f"{self.dstdir}/Source/CParse/parser.h")
+ swig.SRCS.remove("Source/CParse/parser.c")
+ swig.SRCS.add("Source/CParse/parser.y")
+ swig.BISON_GEN_C = True
+
+ for lang in SWIG_LANGS:
+ self.yamakes[f"Lib/{lang}"] = self.module(
+ Library,
+ ADDINCL=[
+ ArcPath(f"{self.arcdir}/Lib/{lang}", GLOBAL=True, FOR="swig"),
+ ArcPath(f"{self.arcdir}/Lib", GLOBAL=True, FOR="swig"),
+ ],
+ )
+ swig.RECURSE.add(f"Lib/{lang}")
+
+
+swig = GNUMakeNixProject(
+ arcdir="contrib/tools/swig",
+ nixattr="swig4",
+ flags=["--disable-ccache"],
+ build_subdir="build",
+ cflags=lambda self: [f"-DSWIG_LIB_ARCPATH={self.arcdir}/Lib"],
+ ignore_commands=["bash", "sed", "bison"],
+ copy_sources=[
+ "Lib/*.i",
+ "Lib/*.swg",
+ "Lib/std",
+ "Lib/typemaps",
+ "Source/CParse/parser.y",
+ ]
+ + [
+ # fmt: off
+ f"Lib/{lang}"
+ for lang in SWIG_LANGS
+ # fmt: on
+ ],
+ keep_paths=["swig_lib.cpp"],
+ disable_includes=[
+ "cgocall.h",
+ "runtime.h",
+ "structmember.h",
+ ],
+ post_install=post_install,
+)
diff --git a/contrib/tools/swig/.yandex_meta/devtools.copyrights.report b/contrib/tools/swig/.yandex_meta/devtools.copyrights.report
new file mode 100644
index 00000000000..9acaf522ea7
--- /dev/null
+++ b/contrib/tools/swig/.yandex_meta/devtools.copyrights.report
@@ -0,0 +1,145 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits
+# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files
+# $ # user comments
+# $
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP COPYRIGHT_SERVICE_LABEL 1e6250a81e323955df133e1953c19a25
+BELONGS ya.make
+ License text:
+ Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s);
+ return 0;
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ Source/Modules/lang.cxx [3015:3016]
+
+KEEP COPYRIGHT_SERVICE_LABEL 23aa5d479e8aaa77f0a2bfc6e11b03a3
+BELONGS ya.make
+ License text:
+ This software includes contributions that are Copyright (c) 2005-2006
+ Arizona Board of Regents (University of Arizona).
+ All Rights Reserved
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ LICENSE-UNIVERSITIES [69:71]
+
+KEEP COPYRIGHT_SERVICE_LABEL 2ad026ce0f5d73743b9fd985961e75e6
+BELONGS ya.make
+ License text:
+ Copyright (c) 1995-1998
+ The University of Utah and the Regents of the University of California
+ All Rights Reserved
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ LICENSE-UNIVERSITIES [5:7]
+
+KEEP COPYRIGHT_SERVICE_LABEL 732fcfb6a44d6047f7c032e342ad2617
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ Source/Modules/main.cxx [646:654]
+
+KEEP COPYRIGHT_SERVICE_LABEL 7a54c7ef931d30ecbd65164b1a118bde
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ Source/Modules/main.cxx [646:654]
+
+KEEP COPYRIGHT_SERVICE_LABEL ae2df1d7b8202a35d22b46f5579a84b9
+BELONGS ya.make
+ License text:
+ Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(c), Getline(c), "previous declaration of '%s'.\n", name);
+ } else {
+ /* Make sure node with same name doesn't already exist */
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ Source/Modules/allocate.cxx [417:419]
+ Source/Modules/allocate.cxx [673:673]
+ Source/Swig/extend.c [72:80]
+ Source/Swig/symbol.c [995:998]
+ Source/Swig/symbol.c [1001:1003]
+
+KEEP COPYRIGHT_SERVICE_LABEL f0faebef234e7ccd9f585e9c48077a7c
+BELONGS ya.make
+ License text:
+ This software includes contributions that are Copyright (c) 1998-2005
+ University of Chicago.
+ All rights reserved.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ LICENSE-UNIVERSITIES [37:39]
+
+KEEP COPYRIGHT_SERVICE_LABEL f8a83d96f84af4c756938a5684474aac
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ Source/Modules/main.cxx [646:654]
+
+KEEP COPYRIGHT_SERVICE_LABEL fe6f4a2cadd39168e946fc1f97e42e56
+BELONGS ya.make
+ License text:
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ LICENSE-GPL [4:6]
diff --git a/contrib/tools/swig/.yandex_meta/devtools.licenses.report b/contrib/tools/swig/.yandex_meta/devtools.licenses.report
new file mode 100644
index 00000000000..e701ab60303
--- /dev/null
+++ b/contrib/tools/swig/.yandex_meta/devtools.licenses.report
@@ -0,0 +1,369 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits
+# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files
+# $ # user comments
+# $
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+IGNORE_FILES CHANGES RELEASENOTES
+
+KEEP GPL-3.0-only AND Custom-swig 10f9f75f670510ba2bbc6d83abae0c36
+BELONGS ya.make
+FILE_INCLUDE COPYRIGHT found in files: Source/CParse/cparse.h at line 5, Source/CParse/cscanner.c at line 5, Source/CParse/parser.y at line 5, Source/CParse/templ.c at line 5, Source/CParse/util.c at line 5, Source/DOH/base.c at line 5, Source/DOH/doh.h at line 5, Source/DOH/dohint.h at line 5, Source/DOH/file.c at line 5, Source/DOH/fio.c at line 5, Source/DOH/hash.c at line 5, Source/DOH/list.c at line 5, Source/DOH/memory.c at line 5, Source/DOH/string.c at line 5, Source/DOH/void.c at line 5, Source/Modules/contract.cxx at line 5, Source/Modules/csharp.cxx at line 5, Source/Modules/directors.cxx at line 5, Source/Modules/emit.cxx at line 5, Source/Modules/guile.cxx at line 5, Source/Modules/interface.cxx at line 5, Source/Modules/java.cxx at line 5, Source/Modules/lang.cxx at line 5, Source/Modules/lua.cxx at line 5, Source/Modules/main.cxx at line 5, Source/Modules/mzscheme.cxx at line 5, Source/Modules/nested.cxx at line 5, Source/Modules/ocaml.cxx at line 5, Source/Modules/overload.cxx at line 5, Source/Modules/perl5.cxx at line 5, Source/Modules/ruby.cxx at line 5, Source/Modules/swigmain.cxx at line 5, Source/Modules/swigmod.h at line 5, Source/Modules/tcl8.cxx at line 5, Source/Modules/typepass.cxx at line 5, Source/Modules/utils.cxx at line 5, Source/Modules/xml.cxx at line 5, Source/Preprocessor/cpp.c at line 5, Source/Preprocessor/expr.c at line 5, Source/Preprocessor/preprocessor.h at line 5, Source/Swig/cwrap.c at line 5, Source/Swig/deprecate.c at line 5, Source/Swig/error.c at line 5, Source/Swig/extend.c at line 5, Source/Swig/fragment.c at line 5, Source/Swig/getopt.c at line 5, Source/Swig/include.c at line 5, Source/Swig/misc.c at line 5, Source/Swig/naming.c at line 5, Source/Swig/parms.c at line 5, Source/Swig/scanner.c at line 5, Source/Swig/stype.c at line 5, Source/Swig/swig.h at line 5, Source/Swig/swigfile.h at line 5, Source/Swig/swigopt.h at line 5, Source/Swig/swigparm.h at line 5, Source/Swig/swigscan.h at line 5, Source/Swig/swigtree.h at line 5, Source/Swig/swigwrap.h at line 5, Source/Swig/symbol.c at line 5, Source/Swig/tree.c at line 5, Source/Swig/typemap.c at line 5, Source/Swig/typeobj.c at line 5, Source/Swig/typesys.c at line 5, Source/Swig/wrapfunc.c at line 5
+FILE_INCLUDE LICENSE found in files: Source/CParse/cparse.h at line 5, Source/CParse/cscanner.c at line 5, Source/CParse/parser.y at line 5, Source/CParse/templ.c at line 5, Source/CParse/util.c at line 5, Source/DOH/base.c at line 5, Source/DOH/doh.h at line 5, Source/DOH/dohint.h at line 5, Source/DOH/file.c at line 5, Source/DOH/fio.c at line 5, Source/DOH/hash.c at line 5, Source/DOH/list.c at line 5, Source/DOH/memory.c at line 5, Source/DOH/string.c at line 5, Source/DOH/void.c at line 5, Source/Modules/contract.cxx at line 5, Source/Modules/csharp.cxx at line 5, Source/Modules/directors.cxx at line 5, Source/Modules/emit.cxx at line 5, Source/Modules/guile.cxx at line 5, Source/Modules/interface.cxx at line 5, Source/Modules/java.cxx at line 5, Source/Modules/lang.cxx at line 5, Source/Modules/lua.cxx at line 5, Source/Modules/main.cxx at line 5, Source/Modules/mzscheme.cxx at line 5, Source/Modules/nested.cxx at line 5, Source/Modules/ocaml.cxx at line 5, Source/Modules/overload.cxx at line 5, Source/Modules/perl5.cxx at line 5, Source/Modules/ruby.cxx at line 5, Source/Modules/swigmain.cxx at line 5, Source/Modules/swigmod.h at line 5, Source/Modules/tcl8.cxx at line 5, Source/Modules/typepass.cxx at line 5, Source/Modules/utils.cxx at line 5, Source/Modules/xml.cxx at line 5, Source/Preprocessor/cpp.c at line 5, Source/Preprocessor/expr.c at line 5, Source/Preprocessor/preprocessor.h at line 5, Source/Swig/cwrap.c at line 5, Source/Swig/deprecate.c at line 5, Source/Swig/error.c at line 5, Source/Swig/extend.c at line 5, Source/Swig/fragment.c at line 5, Source/Swig/getopt.c at line 5, Source/Swig/include.c at line 5, Source/Swig/misc.c at line 5, Source/Swig/naming.c at line 5, Source/Swig/parms.c at line 5, Source/Swig/scanner.c at line 5, Source/Swig/stype.c at line 5, Source/Swig/swig.h at line 5, Source/Swig/swigfile.h at line 5, Source/Swig/swigopt.h at line 5, Source/Swig/swigparm.h at line 5, Source/Swig/swigscan.h at line 5, Source/Swig/swigtree.h at line 5, Source/Swig/swigwrap.h at line 5, Source/Swig/symbol.c at line 5, Source/Swig/tree.c at line 5, Source/Swig/typemap.c at line 5, Source/Swig/typeobj.c at line 5, Source/Swig/typesys.c at line 5, Source/Swig/wrapfunc.c at line 5
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: GPL-3.0-or-later
+ Score : 98.61
+ Match type : NOTICE
+ Links : http://www.gnu.org/licenses/gpl-3.0-standalone.html, https://spdx.org/licenses/GPL-3.0-or-later
+ Files with this license:
+ Source/CParse/cparse.h [2:7]
+ Source/CParse/cscanner.c [2:7]
+ Source/CParse/parser.y [2:7]
+ Source/CParse/templ.c [2:7]
+ Source/CParse/util.c [2:7]
+ Source/DOH/base.c [2:7]
+ Source/DOH/doh.h [2:7]
+ Source/DOH/dohint.h [2:7]
+ Source/DOH/file.c [2:7]
+ Source/DOH/fio.c [2:7]
+ Source/DOH/hash.c [2:7]
+ Source/DOH/list.c [2:7]
+ Source/DOH/memory.c [2:7]
+ Source/DOH/string.c [2:7]
+ Source/DOH/void.c [2:7]
+ Source/Modules/contract.cxx [2:7]
+ Source/Modules/csharp.cxx [2:7]
+ Source/Modules/directors.cxx [2:7]
+ Source/Modules/emit.cxx [2:7]
+ Source/Modules/guile.cxx [2:7]
+ Source/Modules/interface.cxx [2:7]
+ Source/Modules/java.cxx [2:7]
+ Source/Modules/lang.cxx [2:7]
+ Source/Modules/lua.cxx [2:7]
+ Source/Modules/main.cxx [2:7]
+ Source/Modules/mzscheme.cxx [2:7]
+ Source/Modules/nested.cxx [2:7]
+ Source/Modules/ocaml.cxx [2:7]
+ Source/Modules/overload.cxx [2:7]
+ Source/Modules/perl5.cxx [2:7]
+ Source/Modules/ruby.cxx [2:7]
+ Source/Modules/swigmain.cxx [2:7]
+ Source/Modules/swigmod.h [2:7]
+ Source/Modules/tcl8.cxx [2:7]
+ Source/Modules/typepass.cxx [2:7]
+ Source/Modules/utils.cxx [2:7]
+ Source/Modules/xml.cxx [2:7]
+ Source/Preprocessor/cpp.c [2:7]
+ Source/Preprocessor/expr.c [2:7]
+ Source/Preprocessor/preprocessor.h [2:7]
+ Source/Swig/cwrap.c [2:7]
+ Source/Swig/deprecate.c [2:7]
+ Source/Swig/error.c [2:7]
+ Source/Swig/extend.c [2:7]
+ Source/Swig/fragment.c [2:7]
+ Source/Swig/getopt.c [2:7]
+ Source/Swig/include.c [2:7]
+ Source/Swig/misc.c [2:7]
+ Source/Swig/naming.c [2:7]
+ Source/Swig/parms.c [2:7]
+ Source/Swig/scanner.c [2:7]
+ Source/Swig/stype.c [2:7]
+ Source/Swig/swig.h [2:7]
+ Source/Swig/swigfile.h [2:7]
+ Source/Swig/swigopt.h [2:7]
+ Source/Swig/swigparm.h [2:7]
+ Source/Swig/swigscan.h [2:7]
+ Source/Swig/swigtree.h [2:7]
+ Source/Swig/swigwrap.h [2:7]
+ Source/Swig/symbol.c [2:7]
+ Source/Swig/tree.c [2:7]
+ Source/Swig/typemap.c [2:7]
+ Source/Swig/typeobj.c [2:7]
+ Source/Swig/typesys.c [2:7]
+ Source/Swig/wrapfunc.c [2:7]
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-other-copyleft
+ Score : 98.61
+ Match type : NOTICE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/other-copyleft.LICENSE
+ Files with this license:
+ Source/CParse/cparse.h [2:7]
+ Source/CParse/cscanner.c [2:7]
+ Source/CParse/parser.y [2:7]
+ Source/CParse/templ.c [2:7]
+ Source/CParse/util.c [2:7]
+ Source/DOH/base.c [2:7]
+ Source/DOH/doh.h [2:7]
+ Source/DOH/dohint.h [2:7]
+ Source/DOH/file.c [2:7]
+ Source/DOH/fio.c [2:7]
+ Source/DOH/hash.c [2:7]
+ Source/DOH/list.c [2:7]
+ Source/DOH/memory.c [2:7]
+ Source/DOH/string.c [2:7]
+ Source/DOH/void.c [2:7]
+ Source/Modules/contract.cxx [2:7]
+ Source/Modules/csharp.cxx [2:7]
+ Source/Modules/directors.cxx [2:7]
+ Source/Modules/emit.cxx [2:7]
+ Source/Modules/guile.cxx [2:7]
+ Source/Modules/interface.cxx [2:7]
+ Source/Modules/java.cxx [2:7]
+ Source/Modules/lang.cxx [2:7]
+ Source/Modules/lua.cxx [2:7]
+ Source/Modules/main.cxx [2:7]
+ Source/Modules/mzscheme.cxx [2:7]
+ Source/Modules/nested.cxx [2:7]
+ Source/Modules/ocaml.cxx [2:7]
+ Source/Modules/overload.cxx [2:7]
+ Source/Modules/perl5.cxx [2:7]
+ Source/Modules/ruby.cxx [2:7]
+ Source/Modules/swigmain.cxx [2:7]
+ Source/Modules/swigmod.h [2:7]
+ Source/Modules/tcl8.cxx [2:7]
+ Source/Modules/typepass.cxx [2:7]
+ Source/Modules/utils.cxx [2:7]
+ Source/Modules/xml.cxx [2:7]
+ Source/Preprocessor/cpp.c [2:7]
+ Source/Preprocessor/expr.c [2:7]
+ Source/Preprocessor/preprocessor.h [2:7]
+ Source/Swig/cwrap.c [2:7]
+ Source/Swig/deprecate.c [2:7]
+ Source/Swig/error.c [2:7]
+ Source/Swig/extend.c [2:7]
+ Source/Swig/fragment.c [2:7]
+ Source/Swig/getopt.c [2:7]
+ Source/Swig/include.c [2:7]
+ Source/Swig/misc.c [2:7]
+ Source/Swig/naming.c [2:7]
+ Source/Swig/parms.c [2:7]
+ Source/Swig/scanner.c [2:7]
+ Source/Swig/stype.c [2:7]
+ Source/Swig/swig.h [2:7]
+ Source/Swig/swigfile.h [2:7]
+ Source/Swig/swigopt.h [2:7]
+ Source/Swig/swigparm.h [2:7]
+ Source/Swig/swigscan.h [2:7]
+ Source/Swig/swigtree.h [2:7]
+ Source/Swig/swigwrap.h [2:7]
+ Source/Swig/symbol.c [2:7]
+ Source/Swig/tree.c [2:7]
+ Source/Swig/typemap.c [2:7]
+ Source/Swig/typeobj.c [2:7]
+ Source/Swig/typesys.c [2:7]
+ Source/Swig/wrapfunc.c [2:7]
+
+KEEP Custom-swig 1151bceb83458fb461be0a08cb27e20a
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: BSD-2-Clause
+ Score : 34.10
+ Match type : TEXT
+ Links : http://opensource.org/licenses/bsd-license.php, http://www.opensource.org/licenses/BSD-2-Clause, https://spdx.org/licenses/BSD-2-Clause
+ Files with this license:
+ LICENSE-UNIVERSITIES [59:64]
+
+KEEP GPL-3.0-or-later AND LicenseRef-scancode-other-copyleft 245a3be24fb0432cc9d568ded05ce9eb
+BELONGS ya.make
+FILE_INCLUDE COPYRIGHT found in files: Source/Modules/allocate.cxx at line 5
+FILE_INCLUDE LICENSE found in files: Source/Modules/allocate.cxx at line 5
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: GPL-3.0-or-later
+ Score : 98.61
+ Match type : NOTICE
+ Links : http://www.gnu.org/licenses/gpl-3.0-standalone.html, https://spdx.org/licenses/GPL-3.0-or-later
+ Files with this license:
+ Source/Modules/allocate.cxx [2:7]
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-other-copyleft
+ Score : 98.61
+ Match type : NOTICE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/other-copyleft.LICENSE
+ Files with this license:
+ Source/Modules/allocate.cxx [2:7]
+
+KEEP LicenseRef-scancode-swig 380e881711ad2fc506e27d809e127654
+BELONGS Lib/go/ya.make Lib/java/ya.make Lib/perl5/ya.make Lib/python/ya.make
+FILE_INCLUDE COPYRIGHT found in files: LICENSE at line 21
+FILE_INCLUDE LICENSE-GPL found in files: LICENSE at line 4
+FILE_INCLUDE LICENSE-UNIVERSITIES found in files: LICENSE at line 8
+ # This is the only reference to the license applied to Lib/
+ # We would like to make this license visible in LICENSE_RESTRICTIONS() macros depending on swig
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: GPL-3.0-or-later
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.gnu.org/licenses/gpl-3.0-standalone.html, https://spdx.org/licenses/GPL-3.0-or-later
+ Files with this license:
+ LICENSE [1:22]
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-swig
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.swig.org/, http://www.swig.org/Release/LICENSE, https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/swig.LICENSE
+ Files with this license:
+ LICENSE [1:22]
+ Belongs difference:
+ + Lib/go/ya.make Lib/java/ya.make Lib/perl5/ya.make Lib/python/ya.make
+ - ya.make
+
+KEEP GPL-3.0-only 4fe869ee987a340198fb0d54c55c47f1
+BELONGS ya.make
+FILE_INCLUDE COPYRIGHT found in files: LICENSE-GPL at line 592, LICENSE-GPL at line 603
+FILE_INCLUDE LICENSE found in files: LICENSE-GPL at line 1
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: GPL-3.0-only
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.gnu.org/licenses/gpl-3.0-standalone.html, http://www.gnu.org/licenses/gpl-3.0.html, https://spdx.org/licenses/GPL-3.0-only
+ Files with this license:
+ LICENSE-GPL [1:674]
+
+KEEP GPL-3.0-or-later AND LicenseRef-scancode-other-copyleft 63e2d3a55d4ee4044cab0e4bd7464334
+BELONGS ya.make
+FILE_INCLUDE COPYRIGHT found in files: Source/Doxygen/csharpdoc.cxx at line 5, Source/Doxygen/csharpdoc.h at line 5
+FILE_INCLUDE LICENSE found in files: Source/Doxygen/csharpdoc.cxx at line 5, Source/Doxygen/csharpdoc.h at line 5
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: GPL-3.0-or-later
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.gnu.org/licenses/gpl-3.0-standalone.html, https://spdx.org/licenses/GPL-3.0-or-later
+ Files with this license:
+ Source/Doxygen/csharpdoc.cxx [2:7]
+ Source/Doxygen/csharpdoc.h [2:7]
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-other-copyleft
+ Score : 100.00
+ Match type : NOTICE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/other-copyleft.LICENSE
+ Files with this license:
+ Source/Doxygen/csharpdoc.cxx [2:7]
+ Source/Doxygen/csharpdoc.h [2:7]
+
+KEEP GPL-3.0-only AND Custom-swig aaf5b0c0b8edd6570ae09cc9a5b4cff4
+BELONGS ya.make
+FILE_INCLUDE COPYRIGHT found in files: Source/Doxygen/doxycommands.h at line 5, Source/Doxygen/doxyentity.cxx at line 5, Source/Doxygen/doxyentity.h at line 5, Source/Doxygen/doxyparser.cxx at line 5, Source/Doxygen/doxyparser.h at line 5, Source/Doxygen/doxytranslator.cxx at line 5, Source/Doxygen/doxytranslator.h at line 5, Source/Doxygen/javadoc.cxx at line 5, Source/Doxygen/javadoc.h at line 5, Source/Doxygen/pydoc.cxx at line 5, Source/Doxygen/pydoc.h at line 5, Source/Include/swigwarn.h at line 5, Source/Modules/d.cxx at line 5, Source/Modules/go.cxx at line 5, Source/Modules/javascript.cxx at line 5, Source/Modules/octave.cxx at line 5, Source/Modules/php.cxx at line 5, Source/Modules/python.cxx at line 5, Source/Modules/r.cxx at line 6, Source/Modules/scilab.cxx at line 5
+FILE_INCLUDE LICENSE found in files: Source/Doxygen/doxycommands.h at line 5, Source/Doxygen/doxyentity.cxx at line 5, Source/Doxygen/doxyentity.h at line 5, Source/Doxygen/doxyparser.cxx at line 5, Source/Doxygen/doxyparser.h at line 5, Source/Doxygen/doxytranslator.cxx at line 5, Source/Doxygen/doxytranslator.h at line 5, Source/Doxygen/javadoc.cxx at line 5, Source/Doxygen/javadoc.h at line 5, Source/Doxygen/pydoc.cxx at line 5, Source/Doxygen/pydoc.h at line 5, Source/Include/swigwarn.h at line 5, Source/Modules/d.cxx at line 5, Source/Modules/go.cxx at line 5, Source/Modules/javascript.cxx at line 5, Source/Modules/octave.cxx at line 5, Source/Modules/php.cxx at line 5, Source/Modules/python.cxx at line 5, Source/Modules/r.cxx at line 6, Source/Modules/scilab.cxx at line 5
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: GPL-3.0-or-later
+ Score : 98.61
+ Match type : NOTICE
+ Links : http://www.gnu.org/licenses/gpl-3.0-standalone.html, https://spdx.org/licenses/GPL-3.0-or-later
+ Files with this license:
+ Source/Doxygen/doxycommands.h [2:7]
+ Source/Doxygen/doxyentity.cxx [2:7]
+ Source/Doxygen/doxyentity.h [2:7]
+ Source/Doxygen/doxyparser.cxx [2:7]
+ Source/Doxygen/doxyparser.h [2:7]
+ Source/Doxygen/doxytranslator.cxx [2:7]
+ Source/Doxygen/doxytranslator.h [2:7]
+ Source/Doxygen/javadoc.cxx [2:7]
+ Source/Doxygen/javadoc.h [2:7]
+ Source/Doxygen/pydoc.cxx [2:7]
+ Source/Doxygen/pydoc.h [2:7]
+ Source/Include/swigwarn.h [2:7]
+ Source/Modules/d.cxx [2:7]
+ Source/Modules/go.cxx [2:7]
+ Source/Modules/javascript.cxx [2:7]
+ Source/Modules/octave.cxx [2:7]
+ Source/Modules/php.cxx [2:7]
+ Source/Modules/python.cxx [2:7]
+ Source/Modules/r.cxx [3:8]
+ Source/Modules/scilab.cxx [2:7]
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-other-copyleft
+ Score : 98.61
+ Match type : NOTICE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/other-copyleft.LICENSE
+ Files with this license:
+ Source/Doxygen/doxycommands.h [2:7]
+ Source/Doxygen/doxyentity.cxx [2:7]
+ Source/Doxygen/doxyentity.h [2:7]
+ Source/Doxygen/doxyparser.cxx [2:7]
+ Source/Doxygen/doxyparser.h [2:7]
+ Source/Doxygen/doxytranslator.cxx [2:7]
+ Source/Doxygen/doxytranslator.h [2:7]
+ Source/Doxygen/javadoc.cxx [2:7]
+ Source/Doxygen/javadoc.h [2:7]
+ Source/Doxygen/pydoc.cxx [2:7]
+ Source/Doxygen/pydoc.h [2:7]
+ Source/Include/swigwarn.h [2:7]
+ Source/Modules/d.cxx [2:7]
+ Source/Modules/go.cxx [2:7]
+ Source/Modules/javascript.cxx [2:7]
+ Source/Modules/octave.cxx [2:7]
+ Source/Modules/php.cxx [2:7]
+ Source/Modules/python.cxx [2:7]
+ Source/Modules/r.cxx [3:8]
+ Source/Modules/scilab.cxx [2:7]
+
+KEEP Custom-swig e62a227ee995927992859c382a1fe9b3
+BELONGS ya.make
+ License text:
+ SWIG is distributed under the following terms:
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-unknown-license-reference
+ Score : 11.00
+ Match type : INTRO
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/unknown-license-reference.LICENSE
+ Files with this license:
+ LICENSE-UNIVERSITIES [1:1]
+
+KEEP Custom-swig e8fff8d859e22a2009986f527716e571
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: BSD-Source-Code
+ Score : 59.89
+ Match type : TEXT
+ Links : https://github.com/infusion/PHP/blob/master/TSRM/LICENSE, https://spdx.org/licenses/BSD-Source-Code
+ Files with this license:
+ LICENSE-UNIVERSITIES [80:94]
+
+KEEP Custom-swig f9369110d4dc1822fa87791dfa7fef55
+BELONGS ya.make
+ License text:
+ Permission is hereby granted, without written agreement and without
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-unknown-license-reference
+ Score : 22.00
+ Match type : INTRO
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/unknown-license-reference.LICENSE
+ Files with this license:
+ LICENSE-UNIVERSITIES [9:9]
+ LICENSE-UNIVERSITIES [73:73]
diff --git a/contrib/tools/swig/.yandex_meta/licenses.list.txt b/contrib/tools/swig/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..03d09fd0b99
--- /dev/null
+++ b/contrib/tools/swig/.yandex_meta/licenses.list.txt
@@ -0,0 +1,935 @@
+====================COPYRIGHT====================
+ Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(c), Getline(c), "previous declaration of '%s'.\n", name);
+ } else {
+ /* Make sure node with same name doesn't already exist */
+
+
+====================COPYRIGHT====================
+ Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s);
+ return 0;
+
+
+====================COPYRIGHT====================
+ } else if (strcmp(argv[i], "-copyright") == 0) {
+ fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
+ fprintf(stdout, "Copyright (c) 1995-1998\n");
+ fprintf(stdout, "University of Utah and the Regents of the University of California\n");
+ fprintf(stdout, "Copyright (c) 1998-2005\n");
+ fprintf(stdout, "University of Chicago\n");
+ fprintf(stdout, "Copyright (c) 2005-2006\n");
+ fprintf(stdout, "Arizona Board of Regents (University of Arizona)\n");
+ Exit(EXIT_SUCCESS);
+
+
+====================COPYRIGHT====================
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+====================COPYRIGHT====================
+Copyright (c) 1995-1998
+The University of Utah and the Regents of the University of California
+All Rights Reserved
+
+
+====================COPYRIGHT====================
+This software includes contributions that are Copyright (c) 1998-2005
+University of Chicago.
+All rights reserved.
+
+
+====================COPYRIGHT====================
+This software includes contributions that are Copyright (c) 2005-2006
+Arizona Board of Regents (University of Arizona).
+All Rights Reserved
+
+
+====================Custom-swig====================
+Permission is hereby granted, without written agreement and without
+
+
+====================Custom-swig====================
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+====================Custom-swig====================
+SWIG is distributed under the following terms:
+
+
+====================Custom-swig====================
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF ARIZONA AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+ARIZONA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+====================File: COPYRIGHT====================
+SWIG Copyright and Authors
+--------------------------
+
+Copyright (c) 1995-2023 The SWIG Developers
+Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
+Copyright (c) 1998-2005 University of Chicago.
+Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
+
+Portions also copyrighted by:
+ Network Applied Communication Laboratory, Inc
+ Information-technology Promotion Agency, Japan
+
+Active SWIG Developers:
+ William Fulton ([email protected]) (SWIG core, Java, C#, Windows, Cygwin)
+ Olly Betts ([email protected]) (PHP)
+ Joseph Wang ([email protected]) (R)
+ Momtchil Momtchev ([email protected]) (Javascript Node-API)
+ Simon Marchetto ([email protected]) (Scilab)
+ Zackery Spytz ([email protected]) (OCaml, SWIG core)
+
+Past SWIG developers and major contributors include:
+ Dave Beazley ([email protected]) (SWIG core, Python, Tcl, Perl)
+ Henning Thielemann ([email protected]) (Modula3)
+ Matthias Köppe ([email protected]) (Guile, MzScheme)
+ Luigi Ballabio ([email protected]) (STL wrapping)
+ Mikel Bancroft ([email protected]) (Allegro CL)
+ Surendra Singhi ([email protected]) (CLISP, CFFI)
+ Marcelo Matus ([email protected]) (SWIG core, Python, UTL[python,perl,tcl,ruby])
+ Art Yerkes ([email protected]) (OCaml)
+ Lyle Johnson ([email protected]) (Ruby)
+ Charlie Savage ([email protected]) (Ruby)
+ Thien-Thi Nguyen ([email protected]) (build/test/misc)
+ Richard Palmer ([email protected]) (PHP)
+ Sam Liddicott - Ananova Ltd ([email protected]) (PHP)
+ Tim Hockin - Sun Microsystems ([email protected]) (PHP)
+ Kevin Ruland (PHP)
+ Shibukawa Yoshiki (Japanese Translation)
+ Jason Stewart ([email protected]) (Perl5)
+ Loic Dachary (Perl5)
+ David Fletcher (Perl5)
+ Gary Holt (Perl5)
+ Masaki Fukushima (Ruby)
+ Scott Michel ([email protected]) (Java directors)
+ Tiger Feng ([email protected]) (SWIG core)
+ Mark Rose ([email protected]) (Directors)
+ Jonah Beckford ([email protected]) (CHICKEN)
+ Ahmon Dancy ([email protected]) (Allegro CL)
+ Dirk Gerrits (Allegro CL)
+ Neil Cawse (C#)
+ Harco de Hilster (Java)
+ Alexey Dyachenko ([email protected]) (Tcl)
+ Bob Techentin (Tcl)
+ Martin Froehlich <[email protected]> (Guile)
+ Marcio Luis Teixeira <[email protected]> (Guile)
+ Duncan Temple Lang (R)
+ Miklos Vajna <[email protected]> (PHP directors)
+ Mark Gossage ([email protected]) (Lua)
+ Raman Gopalan ([email protected]) (eLua)
+ Gonzalo Garramuno ([email protected]) (Ruby, Ruby's UTL)
+ John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
+ Baozeng Ding <[email protected]> (Scilab)
+ Ian Lance Taylor (Go)
+ Dmitry Kabak ([email protected]) (Doxygen)
+ Vadim Zeitlin (PCRE, Python, Doxygen)
+ Stefan Zager ([email protected]) (Python)
+ Vincent Couvert (Scilab)
+ Sylvestre Ledru (Scilab)
+ Wolfgang Frisch (Scilab)
+ Oliver Buchtala ([email protected]) (Javascript)
+ Neha Narang ([email protected]) (Javascript)
+ Xavier Delacour ([email protected]) (Octave)
+ David Nadlinger ([email protected]) (D)
+ Leif Middelschulte ([email protected]) (C)
+
+Past contributors include:
+ James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
+ Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
+ Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
+ Klaus Wiederänders, Richard Beare, Hans Oesterholt.
+ (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
+
+Past students:
+ Songyan Feng (Chicago).
+ Xinghua Shi (Chicago).
+ Jing Cao (Chicago).
+ Aquinas Hobor (Chicago).
+
+Historically, the following people contributed to early versions of SWIG.
+Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
+at Los Alamos National Laboratory were the first users. Patrick
+Tullmann at the University of Utah suggested the idea of automatic
+documentation generation. John Schmidt and Kurtis Bleeker at the
+University of Utah tested out the early versions. Chris Johnson
+supported SWIG's developed at the University of Utah. John Buckman,
+Larry Virden, and Tom Schwaller provided valuable input on the first
+releases and improving the portability of SWIG. David Fletcher and
+Gary Holt have provided a great deal of input on improving SWIG's
+Perl5 implementation. Kevin Butler contributed the first Windows NT
+port.
+
+Early bug reports and patches:
+Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
+Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
+Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
+Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
+Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
+Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
+Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
+Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
+Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
+Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
+Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
+Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
+Zhong Ren.
+
+
+
+====================File: LICENSE====================
+SWIG is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. See the LICENSE-GPL file for
+the full terms of the GNU General Public license version 3.
+
+Portions of SWIG are also licensed under the terms of the licenses
+in the file LICENSE-UNIVERSITIES. You must observe the terms of
+these licenses, as well as the terms of the GNU General Public License,
+when you distribute SWIG.
+
+The SWIG library and examples, under the Lib and Examples top level
+directories, are distributed under the following terms:
+
+ You may copy, modify, distribute, and make derivative works based on
+ this software, in source code or object code form, without
+ restriction. If you distribute the software to others, you may do
+ so according to the terms of your choice. This software is offered as
+ is, without warranty of any kind.
+
+See the COPYRIGHT file for a list of contributors to SWIG and their
+copyright notices.
+
+
+====================GPL-3.0-only====================
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+====================GPL-3.0-only AND Custom-swig====================
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+
+
+====================GPL-3.0-only AND Custom-swig====================
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+
+
+====================GPL-3.0-or-later AND LicenseRef-scancode-other-copyleft====================
+ * 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.
+
+
+====================GPL-3.0-or-later AND LicenseRef-scancode-other-copyleft====================
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
diff --git a/contrib/tools/swig/.yandex_meta/override.nix b/contrib/tools/swig/.yandex_meta/override.nix
new file mode 100644
index 00000000000..8fd68219360
--- /dev/null
+++ b/contrib/tools/swig/.yandex_meta/override.nix
@@ -0,0 +1,24 @@
+pkgs: attrs: with pkgs; with attrs; rec {
+ version = "4.3.1";
+
+ src = fetchFromGitHub {
+ owner = "swig";
+ repo = "swig";
+ rev = "v${version}";
+ hash = "sha256-wEqbKDgXVU8kQxdh7uC+EZ0u5leeoYh2d/61qB4guOg=";
+ };
+
+ # Setup split build to make copy_sources omit generated files.
+ preConfigure = attrs.preConfigure + ''
+ mkdir -p build
+ cd build
+ ln -s ../configure .
+ '';
+
+ configureFlags = [
+ "--build=x86_64-pc-linux-gnu"
+ "--without-tcl"
+ ];
+
+ buildInputs = [ pcre2 ];
+}
diff --git a/contrib/tools/swig/ANNOUNCE b/contrib/tools/swig/ANNOUNCE
new file mode 100644
index 00000000000..3a5b3478526
--- /dev/null
+++ b/contrib/tools/swig/ANNOUNCE
@@ -0,0 +1,38 @@
+*** ANNOUNCE: SWIG 4.3.1 (15 Apr 2025) ***
+
+https://www.swig.org
+
+We're pleased to announce SWIG-4.3.1, the latest SWIG release.
+
+What is SWIG?
+=============
+
+SWIG is a software development tool that reads C/C++ header files and
+generates the wrapper code needed to make C and C++ code accessible
+from other programming languages including Perl, Python, Tcl, Ruby,
+PHP, C#, Go, Java, Javascript, Lua, Scheme (Guile, MzScheme), D,
+Ocaml, Octave, R, Scilab. SWIG can also export its parse tree in
+the form of XML. Major applications of SWIG include generation of
+scripting language extension modules, rapid prototyping, testing,
+and user interface development for large C/C++ systems.
+
+Release Notes
+=============
+Detailed release notes are available with the release and are also
+published on the SWIG web site at https://swig.org/release.html.
+
+Availability
+============
+The release is available for download on Sourceforge at
+
+ https://prdownloads.sourceforge.net/swig/swig-4.3.1.tar.gz
+
+A Windows version is also available at
+
+ https://prdownloads.sourceforge.net/swig/swigwin-4.3.1.zip
+
+Please report problems with this release to the swig-devel mailing list,
+details at https://www.swig.org/mail.html.
+
+--- The SWIG Developers
+
diff --git a/contrib/tools/swig/CHANGES b/contrib/tools/swig/CHANGES
new file mode 100644
index 00000000000..747efa80add
--- /dev/null
+++ b/contrib/tools/swig/CHANGES
@@ -0,0 +1,29923 @@
+SWIG (Simplified Wrapper and Interface Generator)
+
+See the CHANGES.current file for changes in the current version.
+See the RELEASENOTES file for a summary of changes in each release.
+Issue # numbers mentioned below can be found on Github. For more details, add
+the issue number to the end of the URL: https://github.com/swig/swig/issues/
+
+Version 4.3.0 (20 Oct 2024)
+===========================
+
+2024-10-20: wsfulton
+ #3051 Fix seg fault passing invalid unicode values when expecting a
+ std::string type - fix for python-3.13.
+
+2024-10-19: olly
+ [Ruby] Documentation comments now use `true` and `false` for bool
+ parameter default values, instead of `True` and `False` (which are
+ the Python names and wrong for Ruby!)
+
+2024-10-16: wsfulton
+ #874 Add nested classes to the parse tree dumped out by -xml.
+
+2024-10-16: wsfulton
+ #2213 Documentation for the XML output options of SWIG's parse tree has
+ been added to the Extending chapter.
+
+2024-10-09: wsfulton
+ Remove -xmllang option used with -xml, which had no effect on the output.
+
+2024-10-06: wsfulton
+ [PHP] #2907 Fix returning NULL from functions with output
+ parameters.
+
+ Ensures OUTPUT and INOUT typemaps are handled consistently wrt
+ return type.
+
+ Added:
+ void SWIG_Php_AppendOutput(zval *target, zval *o, int is_void);
+
+ The t_output_helper function is deprecated. Replace t_output_helper
+ in typemaps with SWIG_AppendOutput which calls SWIG_Php_AppendOutput
+ appropriately setting the is_void parameter using the $isvoid special
+ variable. If t_output_helper is currently being used and a completely
+ backwards compatible (but technically incorrect) solution is required,
+ then use SWIG_Php_AppendOutput and pass 1 instead of $isvoid for the
+ is_void parameter.
+
+ The t_output_helper fragment is also deprecated and is no longer
+ needed as the SWIG_Php_AppendOutput function is now always
+ generated.
+
+2024-10-05: wsfulton
+ [Ruby] Removed backwards compatible output_helper fragment and
+ macro.
+
+ Use SWIG_AppendOutput instead of output_helper (does not require
+ the output_helper fragment).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2024-10-05: wsfulton
+ [Ruby] #2907 Fix returning NULL from functions with output
+ parameters.
+
+ Ensures OUTPUT and INOUT typemaps are handled consistently wrt
+ return type.
+
+ New declaration of SWIG_Ruby_AppendOutput is now:
+
+ SWIG_Ruby_AppendOutput(VALUE target, VALUE o, int is_void);
+
+ The 3rd parameter is new and the new $isvoid special variable
+ should be passed to it, indicating whether or not the wrapped
+ function returns void. If SWIG_Python_AppendOutput is currently being
+ used and a completely backwards compatible (but technically incorrect)
+ solution is required, then pass 1 for the is_void parameter.
+
+ Also consider replacing with:
+
+ SWIG_AppendOutput(VALUE target, VALUE o);
+
+ which calls SWIG_Ruby_AppendOutput with same parameters but adding
+ $isvoid for final parameter.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2024-09-29: clintonstimpson
+ [Python] #2350 Switch implementation from static types to heap
+ types using PyType_FromSpec() introduced in Python 3.
+
+ This currently only applies to the default code generation and is
+ not available for the -builtin code generation.
+
+2024-09-29: wsfulton
+ [Python] Single line docstring comments are stripped of leading and
+ trailing whitespace.
+
+2024-09-29: olly
+ SWIG can now handle arbitrary expressions as a subscript (i.e. in
+ `[`...`]`). We don't actually need to parse expressions in this
+ context so we can just skip to the matching closing square bracket.
+
+2024-09-29: olly
+ C++11 auto variables for which SWIG can't parse the initialiser
+ now give a warning and are ignored rather than SWIG exiting with a
+ parse error.
+
+2024-09-26: olly
+ SWIG now recognises --version as an alias for -version (it has
+ supported --help as an alias for -help since 2006).
+
+2024-09-25: wsfulton
+ [MzScheme/Racket] #920 #2830 MzScheme/Racket Deprecation notice.
+
+ This language module no longer works with modern Racket versions
+ (Racket 8 and later) due to the introduction of a different C API.
+ We are thus putting out a plea for a Racket maintainer to step
+ forward and rewrite the MzScheme module for Racket 8, otherwise it
+ will be removed in swig-4.4.
+
+2024-09-25: olly
+ SWIG can now handle arbitrary expressions in the parameter list of
+ a method call. We don't actually need to parse expressions in this
+ context so we can just skip to the matching closing parenthesis.
+
+2024-09-25: olly
+ Add support for C99 _Bool. SWIG now treats _Bool as an alias for
+ the bool keyword when in C mode.
+
+2024-09-23: olly
+ #3031 Improve support for C++11 trailing return types. SWIG now
+ supports const references, const and non-const rvalue references,
+ and enum types with an explicit `enum`, `enum class` or `enum
+ struct`.
+
+2024-09-22: wsfulton
+ #3023 The binary executables in the Windows distribution are now
+ 64-bit now instead of 32-bit. Any 32-bit Windows OS users will need
+ to build their own version using instructions in Windows.html or
+ the "Getting Started Guide" for Windows on the Wiki at
+ https://github.com/swig/swig/wiki/Getting-Started#windows.
+
+2024-09-21: wsfulton
+ #2879 Don't show warning SWIGWARN_LANG_SMARTPTR_MISSING (520) if
+ class is ignored.
+
+2024-09-21: olly
+ SWIG was ignoring `final` if specified after `noexcept`.
+
+2024-09-20: olly
+ [Javascript] Fix problems with v8 support. The tests and examples
+ now work, and configure can now successfully probe for v8 without
+ assistance on Debian and Ubuntu.
+
+2024-09-19: wsfulton
+ #2866 Fix incorrect variable setters being generated when wrapping
+ reference member variables. A setter is no longer generated if the
+ type of the reference member variable is non-assignable.
+
+2024-09-18: olly
+ Fix parse error for a misplaced Doxygen comment which is the only
+ thing in a class/struct.
+
+2024-09-18: olly
+ Fix parse error for %include/#include in a class/struct followed
+ by a member declaration.
+
+2024-09-16: olly
+ #2995 SWIG now has generic handling for converting integer and
+ boolean literal values for use in target language code, replacing
+ code to do with in many of the target language backends. This is
+ mainly an internal clean-up but it does fix a bug in the code it
+ replaces when wrapping code such as this:
+
+ typedef enum { T = (bool)1 } b;
+
+ With suitable enum wrapping settings, SWIG could incorrect wrap T
+ with value 0 in C#, D and Java.
+
+ Such cases now work correctly for D, but for C# and Java SWIG now
+ generates invalid C#/Java code because the C++ enum initialiser
+ expression isn't valid for initialising a C#/Java enum - this is
+ really an improvement over generating code which compiled but used
+ the wrong value!
+
+ If you are affected by this, use %csconstvalue/%javaconstvalue to
+ specify the value of such enumerators as a suitable C#/Java
+ expression.
+
+2024-09-16: olly
+ #2560 Document complex.i in the manual.
+
+2024-09-15: FredBonThermo
+ [C#] #2835 Support -doxygen option for converting doxygen comments
+ to XML formatted C# comments.
+
+2024-09-14: wsfulton
+ #2987 C++ reference errors when passing in a 'NULL' change of
+ behaviour. Most languages now use "NullReferenceError" in the
+ error message where they previously used "ValueError". Also
+ exception changes:
+
+ Guile: "swig-null-reference-error" instead of "swig-value-error"
+ MzScheme: "swig-null-reference-error" instead of "swig-value-error"
+ PHP: TypeError instead of ValueError
+ Python: Consistently raises TypeError instead of a mix of
+ ValueError and TypeError.
+ Ruby: Consistently raises NullReferenceError instead of a mix
+ of ArgumentError and NullReferenceErrorError.
+
+ The consistent raising of a TypeError instead of ValueError for
+ Python ensures that incorrectly passing 'None' into a C++ reference
+ argument will correctly convert the error into a NotImplemented
+ error for the rich comparisons implementations per PEP 207.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2024-09-13: vadz
+ [C] #2086 Add support for C as a target language. This support is
+ currently experimental.
+
+2024-09-12: olly
+ Remove remains of %nestedworkaround and the nestedworkaround
+ feature it uses, which were deprecated over 10 years ago in SWIG
+ 3.0.0. Since then uses of these have done nothing except emit a
+ warning.
+
+2024-09-11: wsfulton
+ [C# Java] #1188 Add the %interface_additional macro to the family
+ of %interface macros for adding additional interfaces for the
+ %generated interface to extend/derive from.
+
+2024-09-11: olly
+ #197 #675 #1677 #2047 Fix incorrect inclusion of "enum " when
+ qualifying C++11 "enum class" enumerator names.
+
+2024-09-11: olly
+ [Perl] #630 Fix wrapping of C++11 enum class when -const command
+ line option is specified.
+
+2024-09-07: wsfulton
+ #2875 Fix swig-4.1.0 regression using the %interface family of
+ macros for multiple inheritance and common bases.
+
+2024-09-06: olly
+ [Python] Stop documenting to define SWIG_FILE_WITH_INIT - this does
+ not actually do anything (and apparently never has!)
+
+2024-09-05: wsfulton
+ #2845 Fix duplicate friend wrappers for friend declarations in
+ nested classes.
+
+2024-09-03: olly
+ #3010 Improve handling of zero bytes in input files. This is
+ certainly a corner case, but GCC and clang both accept zero bytes
+ at least in comments, and SWIG's current handling is to ignore
+ the zero byte and all following characters up to and including the
+ next newline, so for example if a // comment contains a zero byte
+ SWIG would quietly ignore the next line.
+
+2024-08-30: olly
+ #2996 Fix generic string literal handling to handle embedded zero
+ bytes. This allows such strings to work for C# (with %csconst), D
+ (with %dmanifestconst), Go and Java (with %javaconst). For other
+ target languages SWIG-generated wrappers still truncate such string
+ literals at a zero byte (which is probably the best we can do for
+ target languages where the native string can't contain zero bytes).
+
+2024-08-23: wsfulton
+ [Java] #2991 Document solutions for mismatch in C++ access
+ specifiers and Java access modifiers in an inheritance hierarchy.
+
+2024-08-19: wsfulton
+ [Python] #2993 Add missing std::filesystem namespace to
+ std_filesystem.i.
+
+2024-08-17: olly
+ #904 #1907 #2579 Fix string literal and character literal wrapping
+ bugs.
+
+2024-08-15: olly
+ Fix parsing of octal string escapes. We now stop when the next
+ character is digit 8 or 9, and stop after 3 octal digits even if
+ the next character is an octal digit.
+
+2024-08-15: olly
+ SWIG now gives an error for digits 8 and 9 in octal constants -
+ previously these were quietly accepted resulting in a bogus value.
+ C++11 binary constants are now treated similarly - only digits 0
+ and 1 were allowed before, but trying to use other digits now gives
+ a clearer error.
+
+2024-08-12: olly
+ #657 Allow unmatched ' and " in #error and #warning.
+
+2024-08-09: wsfulton
+ [Java] #409 Add the constantsmodifiers pragma so that the
+ visibility for the Java constants interface can be changed from
+ public to default.
+
+2024-08-02: vadz
+ [Python] #2966 Fix overloaded Doxygen comments. Sometimes the
+ Doxygen comments were not combined into one Pydoc comment.
+
+2024-08-01: olly
+ Fix wrapping of string constants containing bytes 0-8, 11, 12 or
+ 14-31 followed by a digit '0' to '7'. We were emitting these bytes
+ as a one or two character octal escape sequence which when
+ interpreted would include the following character.
+
+2024-07-27: olly
+ #2087 Fix parsing of `noexcept` on a function pointer type used
+ as the type of a function parameter. We currently generate
+ invalid C++ code if we try to wrap the function parameter, but
+ at least the user can `%ignore` the parameter or the whole
+ function, whereas the parse error was hard to work around.
+
+2024-07-26: olly
+ Support parsing `noexcept(X)` in expressions, including deducing
+ its type (which is always `bool`).
+
+2024-07-21: wsfulton
+ [Python] Add missing slot for init in struct _specialization_cache
+ needed for python-3.13 builtin wrappers.
+
+2024-07-21: shadchin
+ [Python] #2968 Add missing tp_versions_used slot needed for
+ python-3.13.
+
+2024-07-19: olly
+ -Wallkw now includes keywords for Javascript.
+
+2024-07-19: vadz
+ [Javascript] #2940 Names of object properties can be keywords in
+ Javascript so don't auto-rename them to have a leading underscore.
+
+2024-07-18: olly
+ #1917 Stop removing `f` and `F` suffixes from float literals.
+ This was resulting in incorrect generated C# and Java code. For
+ some cases such as `#define CONSTANT 1.0f` this was a regression
+ introduced in 4.2.0 when we started more correctly wrapping these
+ as `float` rather than `double`.
+
+2024-07-15: vadz
+ #2941 Suppress warning WARN_PARSE_USING_UNDEF for ignored using
+ declarations.
+
+2024-07-03: wsfulton
+ #2860 Enhance Windows.html documentation for the popular Visual C++
+ compiler recommending users to correctly set the __cplusplus macro
+ in order to benefit from modern standards based features that SWIG
+ provides.
+
+2024-07-02: erezgeva
+ [Python, Ruby] #2870 Change the thread safety options for the
+ director code that manages C++ director pointer ownership. Please
+ define SWIG_THREADS to turn on thread safety. For Python, this can
+ also be done via the threads module option or -threads.
+ Implementation now includes a C++11 std::mutex option as priority
+ over WIN32 and pthread mutexes. See director_guard.swg for further
+ implementation details.
+
+2024-06-28: vadz
+ #2935 Fix instantiation of specialized template where the primary
+ template is a forward class template declaration.
+
+2024-06-16: wsfulton
+ #2927 Don't ignore overloaded friend functions that are also
+ declared constexpr.
+
+2024-06-15: wsfulton
+ [Python] Removed deprecated pytuplehlp.swg file and t_output_helper.
+ Use SWIG_AppendOutput as a direct replacement for t_output_helper.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2024-06-15: vadz
+ [Python] #2907 Fix returning null from functions with output
+ parameters. Ensures OUTPUT and INOUT typemaps are handled
+ consistently wrt return type.
+
+ New declaration of SWIG_Python_AppendOutput is now:
+
+ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj, int is_void);
+
+ The 3rd parameter is new and the new $isvoid special variable
+ should be passed to it, indicating whether or not the wrapped
+ function returns void. If SWIG_Python_AppendOutput is currently being
+ used and a completely backwards compatible (but technically incorrect)
+ solution is required, then pass 1 for the is_void parameter.
+
+ Also consider replacing with:
+
+ SWIG_AppendOutput(PyObject* result, PyObject* obj);
+
+ which calls SWIG_Python_AppendOutput with same parameters but adding $isvoid
+ for final parameter.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2024-06-15: wsfulton
+ #2907 Add $isvoid special variable which expands to 1 if the
+ wrapped function has a void return, otherwise expands to 0.
+
+2024-06-14: jschueller
+ #2863 Support Python 3.13 (currently in prerelease).
+
+2024-06-13: erezgeva
+ #2609 Fix Java typemap (const char *STRING, size_t LENGTH) to
+ marshall as Java String instead of Java byte[]. If the old
+ behaviour is required, replace with typemap (const void *BYTES,
+ size_t LENGTH).
+
+ Add multi-argument typemaps to most languages:
+
+ (const char *STRING, size_t LENGTH)
+
+ All languages now use a target language string type for this
+ typemap.
+
+ New multi-argument typemaps have been added to most target
+ languages for use with C raw data (cdata):
+
+ (const void *BYTES, size_t LENGTH) to
+
+ Statically typed languages use a byte array for this typemap, while
+ scripting languages remain using a string.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ * Raw C data: Go uses byte array and int64 for size.
+ Users can use the (const char *STRING, size_t LENGTH) typemaps for
+ strings.
+
+2024-06-06: olly
+ Support alignof(T) for arbitrary type T, and deduce the type of
+ alignof(T) as size_t.
+
+2024-06-06: olly
+ #2919 Support parsing `sizeof(X)` for any expression or type X by
+ skipping balanced parentheses. We don't need to actually parse X
+ since the type of sizeof is always size_t.
+
+2024-06-05: leakec
+ #2873 Fix -fvirtual and using declarations for inheriting base
+ class methods corner case.
+
+2024-05-31: wsfulton
+ [C#, D, Java, Javascript, Lua] Fix %nspace and %nspacemove for
+ nested classes and enums in a class. For example:
+
+ %nspace Space::OuterClass80;
+ namespace Space {
+ struct OuterClass80 {
+ struct InnerClass80 {
+ struct BottomClass80 {};
+ };
+ enum InnerEnum80 { ie80a, ie80b };
+ };
+ }
+
+ Previously the following were additionally required for some
+ languages:
+
+ %nspace Space::OuterClass80::InnerClass80;
+ %nspace Space::OuterClass80::InnerClass80::Bottom80;
+
+ Now the appropriate nspace setting is taken from the outer class.
+
+ A new warning has also been introduced to check and correct
+ conflicting nspace usage, for example if the following is
+ additionally added:
+
+ %nspacemove(AnotherSpace) Space::OuterClass80::InnerClass80;
+
+ The following warning appears as an inner class can't be moved
+ outside of the outer class:
+
+ Warning 406: Ignoring nspace setting (AnotherSpace) for 'Space::OuterClass80::InnerClass80',
+ Warning 406: as it conflicts with the nspace setting (Space) for outer class 'Space::OuterClass80'.
+
+2024-05-31: wsfulton
+ [C#, D, Java, Javascript, Lua] #2782 Enhance the nspace feature
+ with %nspacemove for moving a class or enum into a differently
+ named %target language equivalent of a namespace.
+
+2024-05-31: binaire10
+ [Ruby] #2906 Fix SWIG wrappers for std::map and std::vector to
+ work with Ruby's "select".
+
+2024-05-30: olly
+ #2914 Handle alternative operator names in C++ preprocessor
+ expressions. Handle full set of alternative operator names in
+ C++ expressions (previously only "and", "or" and "not" were
+ understood).
+
+2024-05-15: olly
+ #2868 Support C++17 fold expressions.
+
+2024-05-15: olly
+ #2876 Report error if parser stack depth exceeded. Previously SWIG
+ would quietly exit with status 0 in this situation.
+
+2024-04-12: pfusik
+ [Javascript] #2869 Fix JavaScript _wrap_getCPtr on 64-bit Windows
+
+2024-04-12: wsfulton
+ [Javascript, MzScheme, Python, Ruby] #202 Remove the vast majority
+ of the /*@SWIG:...*/ locator strings in the generated wrappers for
+ these 4 languages to help with reproducible builds.
+
+2024-04-08: thewtex
+ [Python] #2856 Include stdlib.h for more recent Python Stable ABI
+
+2024-03-28: olly
+ Fix preprocessor to handle C-style comment ending **/ in macro
+ argument.
+
+2024-03-27: wsfulton
+ [Python] #2844 Fix for using more than one std::string_view type in
+ a method.
+
+2024-03-27: wsfulton
+ [R] #2847 Add missing std::vector<long> and std::vector<long long>
+ typemaps which were missing depending on whether or not
+ SWIGWORDSIZE64 was defined.
+
+2024-03-25: wsfulton
+ [Python] #2826 Stricter stable ABI conformance.
+ 1. Use Py_DecRef and Py_IncRef when Py_LIMITED_API is defined
+ instead of macro equivalents, such as Py_INCREF.
+ 2. Don't use PyUnicode_GetLength from python-3.7 and later.
+ 3. Use PyObject_Free instead of deprecated equivalents.
+
+2024-03-25: olly
+ #2848 Fix elision of comma before ##__VA_ARGS__ which we document
+ as supported but seems to have not worked since before 2009.
+
+2024-03-11: wsfulton
+ [C#] #2829 Improve handling and documentation of missing enum base
+ type information.
+
+2024-03-07: wsfulton
+ [Ocaml] Fix SWIGTYPE MOVE 'in' typemap to fix compilation error.
+
+2024-03-07: wsfulton
+ Add SWIGTYPE MOVE 'typecheck' typemaps to remove warning 472
+ (SWIGWARN_TYPEMAP_TYPECHECK_UNDEF).
+
+2024-03-06: wsfulton
+ Add support for std::unique_ptr & typemaps. Non-const inputs
+ implement move semantics from proxy class to C++ layer, otherwise
+ const inputs and all reference returns behave like any other lvalue
+ reference to a class.
+
+2024-03-06: wsfulton
+ [Javascript, MzScheme, Octave] Support NULL being passed into char*
+ typemaps.
+
+2024-03-06: christophe-calmejane,wsfulton
+ #2650 Add support for movable std::unique_ptr by adding in
+ std::unique_ptr && input typemaps. The std::unique && output
+ typemaps do not support move semantics by default and behave like
+ lvalue references.
+
+2024-03-06: wsfulton
+ Add missing use of move constructor instead of copy constructor
+ when passing movable types by value. This was previously
+ implemented only for parameters passed to a global function or
+ static member function and is now extended to parameters passed to
+ member methods as well as constructors.
+
+2024-03-01: olly
+ [Java] #2819 Suppress Java removal warnings for uses of
+ System.runFinalization(). SWIG will need to stop relying on
+ finalize methods, but we know that and meanwhile these warnings
+ make the testsuite output noisy. Fix use of deprecated form
+ of Runtime.exec() in the doxygen example.
+
+2024-02-28: wsfulton
+ #1754 Fix compilation errors in generated code when instantiating a
+ templated static method within a template (non-static methods and
+ constructors were always okay). For example:
+
+ template <typename T> class X {
+ template <class InputIterator>
+ static void fn(InputIterator first, InputIterator last) {
+ ...
+ }
+ };
+ class SimpleIterator { ... };
+
+ %extend X<int> {
+ %template(fn) fn<SimpleIterator>;
+ }
+
+Version 4.2.1 (24 Feb 2024)
+===========================
+
+2024-02-23: wsfulton
+ #2814 Correctly ignore duplicate template instantiation (when the
+ duplicate contains typedef'd template parameters).
+
+2024-02-22: erezgeva
+ [Ruby, Octave, R] #2284 Fix segfault shrinking STL containers.
+
+2024-02-22: simark
+ Fix -Wundef warning about testing the value of __cplusplus when
+ compiling SWIG-generated C code. Warning introduced by a change in
+ SWIG 4.2.0.
+
+2024-02-21: olly
+ #2808 [PHP] Fix memory leak when getting or setting a PHP
+ attribute which wraps a C++ member variable. Bug introduced in
+ SWIG 4.1.0.
+
+2024-02-18: wsfulton
+ #2745 Fix for wrapping STL containers that are static member variables
+ or global variables (most scripting languages). Previously a copy of the
+ STL container was made into a target language container when reading the
+ variable. Changes, such as adjusting an element or adding/erasing
+ elements, were made to the copy of the container rather the actual
+ underlying C++ container. Also applies to const reference STL static
+ members.
+
+ If you really need the old behaviour, add in the typemap that used
+ to provide it. For example, for std::list< int > and
+ const std::list< int >&, use:
+
+ %typemap(varout,noblock=1,fragment="SWIG_" "Traits" "_" {std::list< int >})
+ std::list< int >, const std::list< int >& {
+ $result = swig::from(static_cast< std::list< int > >($1));
+ }
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2024-02-15: olly
+ Improve type deduction for enum values in expressions.
+
+2024-02-15: rlaboiss
+ #2799 [Octave] Add support for Octave 9.0; fix warnings about use
+ of deprecated Octave APIs with Octave 7 and later.
+
+2024-02-14: olly
+ SWIG now warns and ignores if %constant is used with an implicit
+ type which SWIG can't deduce.
+
+2024-02-13: olly
+ Fix type deduction for certain cases involving C-style casts, or
+ which are syntactically like a C-style cast applied to an unary
+ operator, such as: (7)*6
+
+2024-02-13: olly
+ #2796 Fix handling of enum initialised by expression including a
+ cast to a typedef-ed type. Regression introduced in 4.2.0.
+
+2024-02-09: wsfulton
+ #2794 Fix SwigType_isvariadic assertion to add support for variadic
+ templated functions in a template.
+
+2024-02-08: wsfulton
+ #2761 [Tcl] Fix assert in SWIG_Tcl_ConvertPtrFromString().
+
+2024-02-03: wsfulton
+ #1897 [C#, Java] Fix crash handling enums with same name in different
+ namespaces.
+
+2024-02-01: wsfulton
+ #2781 Correctly report line number warnings/errors for base classes that
+ are templates.
+
+2024-01-31: olly
+ Fix assertion failure and segfault trying to use %constant to
+ deduce the type of a "float _Complex" constant.
+
+2024-01-31: jim-easterbrook
+ #2771 [Python] builtin fixes to handle NULL values passed to slots using
+ functype: ssizeobjargproc and ternaryfunc.
+
+2024-01-31: olly
+ [Java] #2766 Fix segfault trying to wrap a constant whose type is unknown
+ to SWIG with "%javaconst(1);" enabled.
+
+2024-01-31: wsfulton
+ #2768 Fix seg fault handling upcasting when using %shared_ptr on some
+ templates.
+
+2024-01-31: olly
+ #2783 Fix incorrectly deduced type for function call. Regression
+ introduced in 4.2.0.
+
+2024-01-27: wsfulton
+ [Python] Fix compilation error when wrapping two or more classes that
+ have the same friend operator overload when the classes are in a namespace.
+
+2024-01-15: wsfulton
+ https://sourceforge.net/p/swig/bugs/960/
+ https://sourceforge.net/p/swig/bugs/807/
+ Fix so that friend operators within a namespace can be correctly ignored
+ or renamed.
+
+2024-01-15: wsfulton
+ Wrap friend functions that are defined or declared within a namespace.
+ Previously unqualified friend definitions/declarations in a namespace were
+ ignored.
+
+ The visibility of unqualified friend functions in C++ is somewhat quirky
+ and the documentation has been enhanced to aid wrapping of friends.
+
+2024-01-12: wsfulton
+ #2749 Fix seg fault handling friend constructor/destructor declarations.
+
+2024-01-12: olly
+ [Ruby, Tcl] #2751 Fix -external-runtime output to define
+ SWIG_snprintf (bug introduced in 4.2.0).
+
+2024-01-12: olly
+ Improve preprocessor warning for use of an undefined function-like
+ macro. SWIG now warns:
+
+ Warning 202: Could not evaluate expression 'MY_VERSION_AT_LEAST(1,2,3)'
+ Warning 202: Use of undefined function-like macro
+
+ instead of:
+
+ Warning 202: Could not evaluate expression 'MY_VERSION_AT_LEAST(1,2,3)'
+ Warning 202: Syntax error: expected operator
+
+2024-01-11: PaulObermeier
+ [Tcl] Improve support for Tcl 9.0. All examples and tests now pass
+ with Tcl 9.0.b1.
+
+2024-01-06: wsfulton
+ [Python] #2744 Regression fix - add in missing SwigPyIterator_T fragment for
+ SwigPyIteratorClosed_T when using %import on an instantiated std::map.
+
+Version 4.2.0 (30 Dec 2023)
+===========================
+
+2023-12-24: degasus
+ [Python] #2494 Fix integer overflow / undefined behavior for python
+ castmode on sizeof(long)==8 platforms for implicit conversions around
+ edge cases of LONG_MAX and ULONG_MAX, for example:
+
+ void as_l(long x); // C interface
+
+ Usage from Python:
+
+ lmaxd = math.nextafter(float(2**63), 0.0) # LONG_MAX == 2**63-1
+ # Now below correctly raises a TypeError due to the overflow
+ as_l(math.nextafter(lmaxd, float('inf')))
+
+2023-12-21: olly
+ [PHP] `%feature("php:allowdynamicproperties", 0) Foo;` is now handled as
+ the feature being off to match other boolean features. Previously
+ any value set was treated as on.
+
+2023-12-20: treitmayr
+ [Ruby] #2033 Fix missing checks for negative numbers when passing numbers
+ to unsigned long/unsigned long long C types.
+
+2023-12-20: crhilton
+ [C#] #2722 Add support the "cs:defaultargs" feature.
+
+ This adds a way to wrap C++ functions that have default arguments
+ with an equivalent C# function with default arguments, instead of
+ generating an overloaded C# method for each defaulted argument.
+
+2023-12-20: vadz, vadimcn, wangito33, wsfulton, clintonstimpson
+ [Python] #1613 #1687 #1727 #2190 #2727 #2428 Add support for the Python stable
+ ABI using default Python options. Code is generated that compiles when
+ setting the C macro Py_LIMITED_API to 0x03040000 (at C/C++ compile time).
+ Note that the -builtin, -fast (used by -O) options are not supported.
+
+2023-12-20: wsfulton
+ [Python] More efficient input string marshalling for Python 3.
+
+ Previously a copy of a string was made while converting from a Python 3
+ string to a char * or std::string. This copy is no longer needed making
+ string marshalling more efficient. Does not apply to the stable ABI
+ targetting Python < 3.10 where a copy is still required where the stable
+ ABI does not provide PyUnicode_AsUTF8AndSize.
+
+2023-12-20: wsfulton
+ #2190 Replace SWIG_Python_str_AsChar with SWIG_PyUnicode_AsUTF8AndSize.
+
+ SWIG_Python_str_AsChar has undefined behaviour when Py_LIMITED_API is defined
+ as it returns a pointer to a string in a PyBytes object that no longer exists.
+
+ SWIG_PyUnicode_AsUTF8AndSize is an efficient replacement, but requires a
+ different API and the caller to decrement the refcount on the intermediate
+ PyObject in the Py_LIMITED_API < 0x030A0000 implementation. The alternative
+ would have required copying the returned char * string as was done in a
+ previous implementation requiring a call to the defunct SWIG_Python_str_DelForPy3
+ function.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-12-14: PaulObermeier
+ [Tcl] #2730 Rename SWIG's Tcl_GetBoolFromObj() since Tcl 8.7 (TIP 618)
+ introduces a function with the same name.
+
+ [Tcl] #2729 Use Tcl_GetString() instead of Tcl_GetStringFromObj(..., NULL)
+ for compatibility with Tcl 9.
+
+2023-12-03: olly
+ [Ocaml] Remove -suffix command line option which has emitted a
+ deprecation warning since SWIG 3.0.4 - if you want to specify
+ a different filename extension for generated C++ files use -cppext
+ instead, which works for all SWIG target language backends.
+
+2023-12-01: saiarcot895
+ [Python] #2413 Prevent potential multi-threading crash; gracefully exit running
+ daemon threads on main thread exit.
+
+2023-11-24: wsfulton
+ Add support for parsing C++20 constexpr destructors.
+
+2023-11-19: olly
+ Fix handling of constant expressions containing < and > to not
+ drop parentheses around the subexpression as doing so can change
+ its value in some cases.
+
+2023-11-18: yasamoka, jmarrec
+ [Python] #2639 Add std_filesystem.i for wrapping std::filesystem::path
+ with pathlib.Path.
+
+2023-11-17: chrstphrchvz
+ [Tcl] #2711 Fix -Wmissing-braces warning in generated code.
+
+2023-11-17: chrstphrchvz
+ [Tcl] #2710 Stop using Tcl's CONST macro. It's no longer needed
+ and is set to be deprecated in Tcl 8.7, and removed in Tcl 9.0.
+
+2023-11-08: wsfulton
+ [C#] Replace empty() method with IsEmpty property for std::vector, std::list, std::map
+ containers for consistency across all containers.
+
+ The empty() method is actually still wrapped, but as a private proxy method. For backwards
+ compatibility, the method can be made public again using %csmethodmodifiers for all
+ vectors as follows:
+
+ %extend std::vector {
+ %csmethodmodifiers empty() const "public"
+ }
+ %include "std_vector.i"
+
+ or alternatively for each individual %template instantiation as follows:
+
+ %csmethodmodifiers std::vector<double>::empty() const "public"
+ %template(VectorDouble) std::vector<double>;
+
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-11-08: wsfulton
+ [C#] Add std_unordered_set.i for wrapping std::std_unordered_set, implementing
+ C# System.Collections.Generic.ISet<>.
+
+2023-11-09: olly
+ #2591 SWIG now supports command line options -std=cXX and
+ -std=c++XX to specify the C/C++ standards version. The only effect
+ of these options is to set appropriate values for __STDC_VERSION__
+ and __cplusplus respectively, which is useful if you're wrapping
+ headers which have preprocessor checks based on their values.
+
+2023-11-09: olly
+ SWIG now defines __STDC__ to 1 to match the behaviour of ISO C/C++
+ compilers - previously it had an empty value.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-11-09: olly
+ When -c++ is used, SWIG now defines __cplusplus to be 199711L (the
+ value for C++98) by default - previously its value was set to
+ __cplusplus.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-11-08: emmenlau
+ #2480 [C#] Add std_unordered_map.i for wrapping std::std_unordered_map, implementing
+ C# System.Collections.Generic.IDictionary<>.
+
+2023-11-06: wsfulton
+ [D, Java] Add the dbegin option to the %module directive for generating code at
+ the beginning of every D file. Similarly javabegin for Java. This enables one
+ to add a common comment at the start of each D/Java file.
+
+2023-11-06: wsfulton
+ [C#] #2681 Support nullable reference types. A generic C# option to the
+ %module directive allows one to add in any code at the beginning of every
+ C# file. This can add the #nullable enable preprocessor directive at the beginning
+ of every C# file in order to enable nullable reference types as follows:
+
+ %module(csbegin="#nullable enable\n") mymodule
+
+2023-10-21: wsfulton
+ [Python] #1783 Don't swallow all exceptions into a NotImplemented return
+ when wrapping operators which are marked with %pythonmaybecall. Corrects the
+ implementation of PEP 207.
+
+2023-10-18: wsfulton
+ [C#, D] #902 Use the C++11 enum base, that is, the underlying enum
+ type.
+
+ For C#, it is used as the underlying type in the generated C# enum.
+ For D, it is used as the enum base type in the generated D enum.
+
+2023-10-16: wsfulton
+ #2687 Another using declarations fix for inheritance hierarchies more than
+ two deep and the using declarations are overloaded. Using declarations
+ from a base class' base were not available for use in the target
+ language when the using declaration was before a method declaration.
+
+2023-10-11: wsfulton
+ [C#, D, Go, Guile, Java, Javascript, Lua, Ocaml, R, Racket] #1680
+ carrays.i library modified to use size_t instead of int for the functions
+ provided by %array_functions and %array_class.
+
+ If the old types are required for backwards compatibility, use %apply to
+ restore the old types as follows:
+
+ %include "carrays.i"
+ %apply int { size_t nelements, size_t index }
+ ... %array_functions and %array_class ...
+ %clear size_t nelements, size_t index; # To be safe in case used elsewhere
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-10-11: olly
+ [PHP] #2685 Fix testcase director_finalizer to work with PHP 8.3.
+
+2023-10-06: wsfulton
+ #2307 std::vector::capacity and std::vector::reserve signature changes.
+
+ Java api changes from:
+ public long capacity() { ... }
+ public void reserve(long n) { ... }
+ to:
+ public int capacity() { ... }
+ public void reserve(int n) { ... }
+ to fit in with the usual Java convention of using int for container
+ indexing and sizing.
+
+ The original api for std::vector::reserve can be also be made available via
+ %extend to add in an overloaded method as follows:
+
+ %include <std_vector.i>
+ %extend std::vector {
+ void reserve(jlong n) throw (std::length_error, std::out_of_range) {
+ if (n < 0)
+ throw std::out_of_range("vector reserve size must be positive");
+ self->reserve(n);
+ }
+ }
+
+ This change is partially driven by the need to seamlessly support the full
+ 64-bit range for size_t generically, apart from the customisations for the
+ STL containers, by using:
+
+ %apply unsigned long long { size_t };
+ %apply const unsigned long long & { const size_t & };
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-10-05: wsfulton
+ [C#] #2379 Defining SWIGWORDSIZE64 now applies the (unsigned)
+ long long typemaps to (unsigned) long for a better match on systems
+ where long is 64-bits. A new "Type mapping" section has been added into
+ the CSharp.html documentation covering this and marshalling of primitive
+ types. C (unsigned) long handling remains as is by default, that is,
+ marshall as 32-bit.
+
+ The INPUT[], OUTPUT[], INOUT[], FIXED[] typemaps for long and unsigned long
+ in arrays_csharp.i can now be used and compiled on 64-bit platforms where
+ sizeof(long) != sizeof(int). Requires SWIGWORDSIZE64 to be defined.
+
+2023-09-27: wsfulton
+ [Java] #646 #649 Defining SWIGWORDSIZE64 now applies the (unsigned)
+ long long typemaps to (unsigned) long for a better match on systems
+ where long is 64-bits.
+
+2023-09-18: christophe-calmejane
+ #2631 C++17 std::map fix for values that are not default constructible.
+ Enhancements for all target languages except Python and Ruby.
+
+2023-09-14: mmomtchev
+ #2675 #2676 Temporary variable zero initialisation in the wrappers for
+ consistency with handling pointers.
+
+2023-09-11: emmenlau
+ #2394 Add support to preprocessor for true and false. Note that this
+ is for C++ not C.
+
+2023-09-11: wsfulton
+ [R] #2605 Complete transition to rtypecheck typemaps from hard coded
+ logic. Also see entry dated 2022-10-28 for swig-4.1.1. The rtypecheck
+ typemaps implement typechecking in R for each function parameter using
+ functions such as is.numeric, is.character, is.logical, is.null etc.
+
+2023-09-09: wsfulton
+ https://sourceforge.net/p/swig/bugs/919/
+
+ Fix incorrect variable setters being generated when wrapping arrays.
+ A setter is no longer generated if the type of the array members
+ are non-assignable.
+
+2023-09-09: wsfulton
+ Non-assignable detection fixes when wrapping const member variables.
+ Const member variables such as the following are non-assignable by
+ by default:
+
+ char * const x;
+ const int x;
+ const int x[1];
+
+ but not:
+
+ const char * x;
+
+ Variable setters are not generated when wrapping these non-assignable
+ variables and classes containing such non-assignable variables.
+
+2023-09-07: wsfulton
+ Non-assignable detection fixes when wrapping rvalue reference variables.
+ Rvalue reference variables such as the following are non-assignable by
+ by default:
+
+ X &&v;
+
+ Variable setters are not generated when wrapping these non-assignable
+ variables and classes containing such non-assignable variables.
+
+2023-09-06: wsfulton
+ Non-assignable detection fixes when wrapping reference variables.
+ Reference variables such as the following are non-assignable by
+ by default:
+
+ int &v;
+
+ Variable setters are not generated when wrapping these non-assignable
+ variables and classes containing such non-assignable variables.
+
+2023-09-06: wsfulton
+ Assignment operator detection fixes when wrapping static member
+ variables.
+
+2023-09-06: wsfulton
+ #1416 Implicit assignment operator detection fixes.
+
+ A class that does not have an explicit assignment operator does not
+ have an implicit assignment operator if a member variable is not
+ assignable. Similarly should one of the base classes also not be
+ assignable. Detection of these scenarios has been fixed so that when
+ wrapping a variable that is not assignable, a variable setter is not
+ generated in order to avoid a compiler error.
+
+ Template instantiation via %template is required in order for this to
+ work for templates that are not assignable.
+
+2023-09-03: wsfulton
+ https://sourceforge.net/p/swig/bugs/1006/
+ Fix incorrect variable setters being generated when the type of the
+ variable is not assignable, due to variable type inheriting a private
+ assignment operator further up the inheritance chain (further up than
+ the immediate base).
+
+2023-09-03: wsfulton
+ [Guile, Ocaml, Perl] Don't attempt to generate a setter when wrapping
+ variables which have a private assignment operator as assignment is not
+ possible. This now matches the behaviour of all the other target languages.
+
+2023-09-02: wsfulton
+ Fix problems wrapping deleted destructors. Derived classes are not
+ constructible, so don't attempt to generate default constructor or
+ copy constructor wrappers.
+
+ struct StackOnly1 {
+ // Only constructible on the stack
+ ~StackOnly1() = delete;
+ };
+ struct StackOnlyDerived1 : StackOnly1 {
+ // this class is not constructible due to deleted base destructor
+ };
+
+2023-09-02: wsfulton
+ Fix %copyctor feature when used on classes with deleted copy constructors.
+ A default constructor wrapper was sometimes incorrectly generated.
+
+2023-09-02: wsfulton
+ #1644 Fix wrapping types passed by value where the type has a deleted
+ default constructor.
+
+2023-08-16: shadchin
+ [Python] #2665 Fix missing-field-initializers warning to provide support
+ for python-3.12.
+
+2023-08-09: olly
+ [Ruby] Remove -feature command line option which has been
+ deprecated since SWIG 1.3.32 in 2007. Use -initname instead.
+
+2023-08-06: wsfulton
+ Add support for using declarations to introduce templated member
+ methods and for inheriting templated constructors, such as:
+
+ struct Base {
+ // templated constructor
+ template <typename T> Base(const T &t, const char *s) {}
+ // templated member method
+ template <typename T> void template_method(const T &t, const char *s) {}
+ };
+
+ %template(Base) Base::Base<int>;
+ %template(template_method) Base::template_method<double>;
+
+ struct Derived : Base {
+ using Base::Base;
+ using Base::template_method;
+ };
+
+ Previously the templated methods and constructors were ignored and
+ not introduced into the Derived class.
+
+2023-08-04: wsfulton
+ Fix using declarations for inheritance hierarchies more than
+ two deep and the using declarations are overloaded. Using declarations
+ from a base class' base were not available for use in the target
+ language. For example in the code below, Using1::usingmethod(int i)
+ was not wrapped for use in Using3:
+
+ struct Using1 {
+ protected:
+ void usingmethod(int i) {}
+ };
+ struct Using2 : Using1 {
+ protected:
+ void usingmethod(int i, int j) {}
+ using Using1::usingmethod;
+ };
+ struct Using3 : Using2 {
+ void usingmethod(int i, int j, int k) {}
+ using Using2::usingmethod;
+ };
+
+ Similarly for C++11 using declarations for inheriting constructors.
+
+2023-08-02: wsfulton
+ https://sourceforge.net/p/swig/bugs/932/
+ Fix missing constructor generation due to abstract class test
+ failure when a method is declared in the class along with a
+ using declaration and the using declaration is declared before
+ the method that implemented the pure virtual method, such as:
+
+ struct ConcreteDerived : AbstractBase {
+ ConcreteDerived() {} // was not wrapped
+ using AbstractBase::f;
+ virtual void f(int n) override {}
+ };
+
+2023-08-02: olly
+ [PHP] Implement overloading between different integer types and
+ between double and float.
+
+2023-07-29: wsfulton
+ https://sourceforge.net/p/swig/bugs/678/
+ Fix %copyctor used on class hierarchies with non-const copy
+ constructors. Previously SWIG always attempted to call a copy
+ constructor taking a const reference parameter instead of a
+ non-const reference parameter.
+
+2023-07-28: wsfulton
+ #2541 Fix overloading of templated constructors and %copyctor.
+
+2023-07-21: wsfulton
+ Don't generate a default constructor wrapper when a class has a
+ templated constructor, as there isn't actually an implied default
+ constructor. For example:
+
+ struct TConstructor3 {
+ template<typename T> TConstructor3(T val) {}
+ };
+
+ Previously wrappers were generated for a non-existent default
+ constructor which failed to compile.
+
+2023-07-15: wsfulton
+ C++11 using declarations for inheriting constructors has now been
+ extended to support the directors feature.
+
+2023-07-13: wsfulton
+ C++11 using declarations for inheriting constructors support now
+ also includes inheriting implicitly defined default constructors
+ from the base class.
+
+2023-07-04: wsfulton
+ #2641 Add support for C++11 using declarations for inheriting
+ constructors.
+
+2023-06-30: wsfulton
+ #2640 Fix syntax error parsing an expression which calls a function
+ with no parameters within additional brackets.
+
+2023-06-27: mmomtchev
+ [Javascript] #2545 New Javascript generator targeting the Node.js
+ binary stable ABI Node-API.
+
+2023-06-27: olly
+ [Java] Completely remove pragmas which were deprecated in 2002 and
+ have triggered an error since SWIG 2.0:
+
+ moduleimport Use the moduleimports pragma
+ moduleinterface Use the moduleinterfaces pragma
+ modulemethodmodifiers Use %javamethodmodifiers
+ allshadowimport Use %typemap(javaimports)
+ allshadowcode Use %typemap(javacode)
+ allshadowbase Use %typemap(javabase)
+ allshadowinterface Use %typemap(javainterfaces)
+ allshadowclassmodifiers Use %typemap(javaclassmodifiers)
+ shadowcode Use %typemap(javacode)
+ shadowimport Use %typemap(javaimports)
+ shadowbase Use %typemap(javabase)
+ shadowinterface Use %typemap(javainterfaces)
+ shadowclassmodifiers Use %typemap(javaclassmodifiers)
+
+2023-06-24: wsfulton
+ #2616 https://sourceforge.net/p/swig/bugs/1102/ Fix directors and
+ allprotected mode and using declarations. Previously SWIG either
+ seg faulted or generated code that did not compile.
+
+2023-06-20: olly
+ #2486 Fix handling of template in array size, which was being
+ rejected by SWIG because the type string contains '<' not followed
+ by '('. Drop this check as it should be unnecessary now since the
+ fixes that ensure that template parameters are enclosed within
+ '<(' and ')>'.
+
+2023-06-16: olly
+ [Java] Remove deprecated command line options which have done
+ nothing except emit a deprecation message since 2002 or before:
+
+ -jnic / -jnicpp JNI calling convention now automatic.
+ -nofinalize Use javafinalize typemap instead.
+ -proxy / -shadow Now on by default.
+
+2023-06-16: olly
+ [Guile] Drop support for -Linkage ltdlmod which was only useful
+ for Guile <= 1.4 which we no longer support.
+
+2023-06-15: olly
+ [Guile] The -gh and -scm command line options have been removed.
+ These have done nothing except emit a message since 2013 when
+ SWIG dropped support for generating bindings which used GH.
+
+2023-06-15: olly
+ Remove pointer.i from the SWIG library. It's been a dummy file
+ which has done nothing except %echo a deprecation message since
+ 2002. The replacement is cpointer.i.
+
+2023-06-15: olly
+ SWIG will no longer fall back to using the include path to find the
+ input file, which has been deprecated and emitted a warning since
+ SWIG 1.3.37 (2009-01-13). This makes the behaviour of SWIG the
+ same as C/C++ compilers and works with ccache.
+
+2023-06-15: olly
+ Remove features deprecated in SWIG 1.x and 2.x. Most of these have
+ emitted a deprecation warning or error for well over a decade and
+ have replacements with fewer shortcomings so we expect users will
+ have migrated away from them long ago, but in case you need
+ them replacements are noted below:
+
+ %addmethods Use %extend instead.
+ %attribute_ref Use %attributeref instead (NB: If called with
+ 4 parameters, the 3rd and 4th need switching).
+ %disabledoc Use Doxygen support instead.
+ %doconly Use Doxygen support instead.
+ %enabledoc Use Doxygen support instead.
+ %except Use %exception instead.
+ %extern Use %import instead.
+ %localstyle Use Doxygen support instead.
+ %name Use %rename instead.
+ %new Use %newobject instead.
+ %out %apply OUTPUT typemap rule instead.
+ %readonly Use %immutable instead.
+ %readwrite Use %mutable instead.
+ %section Use Doxygen support instead.
+ %style Use Doxygen support instead.
+ %subsection Use Doxygen support instead.
+ %subsubsection Use Doxygen support instead.
+ %text Use Doxygen support instead.
+ %title Use Doxygen support instead.
+ %typemap(except) Use %exception instead.
+ %typemap(ignore) Use %typemap(in,numinputs=0) instead.
+ %val Use typemaps instead.
+ -debug_template Use -debug-template instead.
+ -debug_typemap Use -debug-typemap instead.
+ -dump_classes Use -debug-classes instead.
+ -dump_memory Use -debug-memory instead.
+ -dump_module Use -debug-module 4 instead.
+ -dump_parse_module Use -debug-module 1 instead.
+ -dump_parse_top Use -debug-top 1 instead.
+ -dump_tags Use -debug-tags instead.
+ -dump_top Use -debug-top 4 instead.
+ -dump_tree Use -debug-top 4 instead.
+ -dump_typedef Use -debug-typedef instead.
+ -dump_xml Use -xmlout /dev/stdout instead.
+ -make_default On by default since SWIG 1.3.7 (2001-09-03).
+ -makedefault On by default since SWIG 1.3.7 (2001-09-03).
+ -no_default Use %nodefaultctor/%nodedefaultdtor instead.
+ -nodefault Use %nodefaultctor/%nodedefaultdtor instead.
+ -noextern option On by default since SWIG 1.3.26 (2005-10-09).
+ -noruntime Type sharing happens via target lang global.
+ -runtime Type sharing happens via target lang global.
+ -show_templates Use -debug-template instead.
+ -tm_debug Use -debug-typemap instead.
+ -xml out.xml Use -xml -o out.xml instead.
+ BOTH typemap rule Use INOUT typemap rule instead.
+ SWIG_INTRUSIVE_PTR(PROXYCLASS, TYPE)
+ Use %intrusive_ptr(TYPE) instead.
+ SWIG_INTRUSIVE_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE)
+ Use %intrusive_ptr(TYPE) instead.
+ SWIG_INTRUSIVE_PTR_NO_WRAP(PROXYCLASS, TYPE)
+ Use %intrusive_ptr_no_wrap(TYPE) instead.
+ SWIG_INTRUSIVE_PTR_DERIVED_NO_WRAP(PROXYCLASS, BASECLASSTYPE, TYPE)
+ Use %intrusive_ptr_no_wrap(TYPE) instead.
+ SWIG_SHARED_PTR(PROXYCLASS, TYPE)
+ Use %shared_ptr(TYPE) instead.
+ SWIG_SHARED_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE...)
+ Use %shared_ptr(TYPE) instead.
+ SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE)
+ Use SWIG_STD_VECTOR_ENHANCED(CTYPE) instead.
+ SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE)
+ No longer required - remove uses.
+ specialize_std_map_on_both
+ No longer required - remove uses.
+ specialize_std_map_on_key
+ No longer required - remove uses.
+ specialize_std_map_on_value
+ No longer required - remove uses.
+
+2023-06-15: olly
+ [Guile] Fix freearg typemaps to go with char **INOUT and char
+ *INOUT in typemaps. Previously the char **INOUT typemap would
+ leak memory if must_free$argnum was true, and the char *INOUT
+ typemap would generate code that didn't compile.
+
+2023-06-07: olly
+ #2630 Fix preprocessor handling of a slash immediately followed by
+ a single quote, which wasn't getting recognised as starting a
+ character literal.
+
+2023-06-07: olly
+ #2630 Fix parsing of <= and >= in templated lambda.
+
+ Skipping between matching delimiters is now done at the token level
+ rather than the character level.
+
+2023-06-02: mmomtchev
+ [Javascript] #2622 Fix support for %typemap(default) and improve
+ support for default arguments in general.
+
+2023-06-01: olly
+ [Perl] #2470 Fix some integer truncation warnings in generated
+ wrappers.
+
+2023-05-30: olly
+ [Lua] Fix bug when passing a Lua number to a C++ function expected
+ std::string. Order of evaluation of C++ function arguments is not
+ defined, and if lua_rawlen() was called before lua_tostring() then
+ it would return 0 (because the value was still a number) and an
+ empty string would be passed.
+
+2023-05-30: mmomtchev
+ [Javascript] #2618 Fix handling of C++ pointer to member function.
+
+2023-05-25: olly
+ #1032 Allow typename disambiguator in:
+
+ using typename NodeT::links_type;
+
+2023-05-25: olly
+ SWIG now discriminates between long double, double and float
+ constants. For example, this means that for target languages which
+ support a separate float type (such as C# and D) this will now
+ create a float constant instead of a double constant in the target
+ language:
+
+ #define PI_ISH 3.1414f
+
+2023-05-25: olly
+ C++11 `auto` variables and `decltype()` can now deduce the
+ type of some expressions which involve literals of built-in types.
+
+2023-05-25: olly
+ #1125 Support parsing C++11 auto variables. This uses the
+ existing type deduction code from decltype so has the same
+ limitations, and such variables will only actually be wrapped
+ when SWIG can deduce the type.
+
+2023-05-23: olly
+ [Ruby] Fix deprecation warnings about ANYARGS when compiling
+ C++ code for SWIG-generated Ruby wrappers with Ruby 3.x.
+
+ This is a recurrence of a problem fixed in 4.0.2. Our fix was
+ conditional on RB_METHOD_DEFINITION_DECL being defined, but Ruby
+ 3.0 stopped defining this.
+
+2023-05-23: olly
+ #2606 Improve error output when SWIG reaches EOF while looking for
+ a closing delimiter. This is reported with an error like:
+
+ Error: Missing '}'. Reached end of input.
+
+ We now exit after reporting this and so no longer report a second
+ more generic error like:
+
+ Error: Syntax error in input(1).
+
+2023-05-22: mmomtchev
+ [Javascript] #2600 Improve test coverage by adding _runme.js files
+ for 22 test cases.
+
+2023-05-20: erezgeva
+ [C#, D, Java, Javascript, Guile, Scilab] #2552 Implement argcargv.i
+ library multi-argument typemaps.
+
+2023-05-20: erezgeva
+ [D] #56 #2538 #2570 The generated code now works with recent D releases:
+ adds override keyword on overridden methods.
+
+ Support is now working using DMD, gcc D and LLVM D compilers.
+
+2023-05-20: olly
+ Support deducing the type for decltype(false) and
+ decltype(true).
+
+2023-05-19: olly
+ #2446 Add support for auto without trailing return type, which is a
+ C++14 feature.
+
+2023-05-19: olly
+ SWIG no longer defines preprocessor symbols corresponding to
+ command line options (e.g. `-module blah` was resulting in
+ `SWIGOPT_MODULE` being set to `blah`). This feature was added in
+ 2001 so that "[m]odules can look for these symbols to alter their
+ code generation if needed", but it's never been used for that
+ purpose in over 20 years, and has never been documented outside of
+ CHANGES.
+
+2023-05-18: olly
+ #2591 Add new -U command line option to undefine a preprocessor
+ symbol.
+
+2023-05-18: olly
+ #1589 #2335 Support parsing arbitrary expression in decltype.
+
+ Use parser error recovery to skip to the closing matching `)` and
+ issue a warning that we can't deduce the decltype for the
+ expression (like we already do for any expression which isn't a
+ simple variable or similar).
+
+2023-05-12: mmomtchev, erezgeva
+ [Javascript] #2561 Support check typemaps for Javascript.
+
+2023-05-12: olly
+ [Java] #2556 Suppress Java removal warnings on finalize method.
+ SWIG will need to stop relying on finalize methods, but we know
+ that and meanwhile these warnings make the testsuite output very
+ noisy.
+
+2023-05-11: olly
+ #302 #2079 #2474 Parse storage class more flexibly.
+
+ Previously we had a hard-coded list of allowed combinations in the
+ grammar, but this suffers from combinatorial explosion, and results
+ in a vague `Syntax error in input` error for invalid (and missing)
+ combinations.
+
+ This means we now support a number of cases which are valid C++ but
+ weren't supported, including `friend constexpr` and `virtual
+ explicit`.
+
+2023-05-08: olly
+ #1567 Add support for std::string_view (new in C++17) for C#, Java,
+ Lua, Perl, PHP, Python, Ruby and Tcl.
+
+2023-05-08: olly
+ [PHP] #2544 Wrap overloaded method with both static and non-static
+ forms. We now wrap this as a non-static method in PHP, which means
+ the static form is only callable via an object.
+
+ Previously this case could end up wrapped as static or non-static
+ in PHP. If it was wrapped as static, attempting to call non-static
+ overloaded forms would crash with a segmentation fault.
+
+2023-05-06: mmomtchev, wsfulton
+ #2550 Fix typedef/using declarations to a typedef struct/class.
+
+2023-05-04: erezgeva
+ [D] #2538 Drop support for D1/Tango, which was discontinued in
+ 2012. Wrappers for D2/Phobos are now generated by default, though
+ the -d2 command line option is still accepted (and now ignored) for
+ backward compatibility.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-04-27: olly
+ #2502 Allow using snprintf() instead of sprintf() in wrappers.
+
+ We aim to produce code that works with C90 or C++98 so we can't
+ assume snprintf() is available, but it almost always is (even
+ on systems from before it was standardised) so having a way to
+ use it is helpful.
+
+ We enable this automatically if the compiler claims conformance
+ with at least C99 or C++11. It can also be enabled manually by
+ defining SWIG_HAVE_SNPRINTF. Define SWIG_NO_SNPRINTF to disable
+ completely.
+
+ The fallback is to call sprintf() without a buffer size check,
+ which is what we've done until now. Adding a check after the
+ call seems of limited benefit - if the buffer was overflowed
+ then it's too late to block it, and most of our uses either have a
+ fixed maximum possible size or dynamically allocate a buffer that's
+ large enough.
+
+2023-04-26: mmomtchev
+ [Javascript] Take into account numinputs when counting arguments.
+
+2023-04-24: olly
+ [PHP] Add throws typemaps for std:string* and const std::string*.
+
+2023-04-23: olly
+ [Javascript] #2453 The testsuite and examples now select which
+ Javascript engine to test based on what was detected by configure.
+ Previously they'd always test with node you specified a different
+ engine (e.g. with `ENGINE=jsc` on the make command line). Now you
+ only need to specify ENGINE if you have more than one engine
+ installed.
+
+2023-04-23: olly
+ [Javascript] Turn on C++ output when wrapping for node, like
+ we already do when wrapping for V8-without-node.
+
+ The testsuite was masking this bug by using SWIG options
+ `-v8 -DBUILDING_NODE_EXTENSION=1` rather than `-node` when testing
+ with nodejs, while the javascript examples were masking this by
+ all getting processed with -c++.
+
+ This shouldn't be an incompatible change for users, as if you're
+ wrapping a C API you'd have to be working around the problem before
+ this change (like our testsuite and examples were), and this change
+ shouldn't break your workaround - it just makes it unnecessary.
+
+2023-04-21: mmomtchev
+ [Javascript] Fix naming of internal C++ helper for wrapping
+ variables for node to use the "getter" naming scheme rather
+ than the function wrapping one. In practice this didn't actually
+ cause problems because Node wrappers are always compiled as C++
+ and the parameters are always different even if the names are
+ the same.
+
+2023-04-21: olly
+ [PHP] Support INPUT,INOUT,OUTPUT for std::string&.
+
+ By default SWIG/PHP wraps std::string& as a pass-by-reference PHP
+ string parameter, but sometimes such a parameter is only for input
+ or only for output, so add support for the named typemaps that other
+ target languages support.
+
+2023-04-21: degasus
+ #2519 Fix CanCastAsInteger range check to clear errno first to fix
+ bogus failures for valid inputs.if errno is set.
+
+2023-04-21: ZackerySpytz
+ [OCaml] #1439 Fix reference typemaps for std::string
+
+2023-04-21: olly
+ #2183 Fix #ifdef and #ifndef to work inside a %define. Previously
+ they were silently ignored in this context (but #if defined already
+ worked here if you need a workaround which works for older
+ versions).
+
+2023-04-20: erezgeva
+ [Go] #2533 Implement argcargv.i library for Go.
+
+2023-04-19: davidcl
+ [Scilab] Add support for Scilab 2023.x.
+ Introduce a new `-gatewayxml6` option to generate XML with full
+ function names.
+
+2023-04-19: mmomtchev
+ https://sourceforge.net/p/swig/bugs/1163/ #1882 #2525
+ Fix preprocessor expansion when a macro expands to the name of
+ another macro which takes parameters from the input following the
+ original macro expansion.
+
+2023-04-19: wildmaples
+ [Ruby] #2527 Fix "undefining the allocator of T_DATA" warning seen
+ with Ruby 3.2.
+
+2023-04-18: davidcl
+ [Scilab] #894 extract values with ":" for typemap (int* IN, int IN_SIZE)
+
+2023-04-14: olly
+ [PHP7] Support for PHP7 has been removed. PHP7 security support
+ ended 2022-11-28 so it doesn't make sense to include support for
+ it in the SWIG 4.2.x release series.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2023-04-05: wsfulton
+ [Python] #2515 Add support for all STL containers to be constructible from a Python set.
+
+ The previous implementation used the Python Sequence Protocol to convert from Python types
+ to STL containers. The new implementation uses the Python Iterator Protocol instead and
+ thereby can convert from a Python set too.
+
+2023-03-25: alatina
+ [Octave] #2512 Add support for Octave 8.1.
+
+2023-03-22: wsfulton
+ [C#] #2478 Minor enhancements to std::array wrappers in std_array.i.
+
+2023-03-13: wsfulton
+ Improved error checking when using %template to instantiate templates within
+ the correct scope.
+
+ 1. When a template is instantiated via %template and uses the unary scope
+ operator ::, an error occurs if the instantiation is attempted within a
+ namespace that does not enclose the instantiated template.
+ For example, the following will now error as ::test::max is not enclosed within test1:
+
+ Error: '::test::max' resolves to 'test::max' and was incorrectly instantiated in
+ scope 'test1' instead of within scope 'test'.
+ namespace test1 {
+ %template(maxchar) ::test::max<char>;
+ }
+
+ 2. SWIG previously failed to always detect a template did not exist when using
+ %template. In particular when instantiating a global template incorrectly within
+ namespace. The code below now correctly emits an error:
+
+ Error: Template 'test5::GlobalVector' undefined.
+ namespace test5 {
+ }
+ template<typename T> struct GlobalVector {};
+ %template(GVI) test5::GlobalVector<int>;
+
+2023-03-13: wsfulton
+ Error out if an attempt is made to define a class using the unary scope
+ operator ::. The following is not legal C++ and now results in an error:
+
+ Error: Using the unary scope operator :: in class definition '::Space2::B' is invalid.
+ namespace Space2 {
+ struct B;
+ }
+ struct ::Space2::B {};
+
+2023-03-08: wsfulton
+ Fix duplicate const in generated code when template instantiation type is const
+ and use of template parameter is also explicitly const, such as:
+
+ template <typename T> struct Conster {
+ void cccc1(T const& t) {}
+ };
+ %template(ConsterInt) Conster<const int>;
+
+ Above previously led to generated code:
+ (arg1)->cccc1((int const const &)*arg2);
+ instead of
+ (arg1)->cccc1((int const &)*arg2);
+
+2023-03-01: wsfulton
+ Partial template specialization fixes to support default arguments from the primary
+ template's parameter list.
+
+ template<class Y, class T=int> struct X { void primary() {} };
+ // Previously the specialization below resulted in:
+ // Error: Inconsistent argument count in template partial specialization. 1 2
+ template<class YY> struct X<YY*> { void special(YY*) {} };
+
+ // Both of these correctly wrap the partially specialized template
+ %template(StringPtr) X<const char *>;
+ %template(ShortPtr) X<short *, int>;
+
+2023-02-15: wsfulton
+ #1300 Further partial template specialization fixes.
+ Fixes when templates are used as a template parameter in a partially specialized
+ instantiation such as:
+
+ template<typename V> struct Vect {};
+ template<class T, typename TT> class Foo { ... };
+ template<class TS, typename TTS> class Foo<Vect<TS>, TTS> { ... };
+ %template(VectInt) Vect<int>;
+ %template(FooVectIntDouble) Foo<Vect<int>, double>; // was previously attempting to use primary template
+
+ Also fixes partial specialization where the same template parameter name is used twice,
+ for example:
+
+ template<typename X, typename Y> struct H { ... };
+ template<typename T> struct H<T, T> { ... };
+ %template(HInts) H<int, int>; // was previously attempting to use primary template
+
+2023-01-27: jschueller
+ #2492 [python] Fix unused parameter warnings for self parameter in
+ generated C/C++ wrapper code.
+
+2023-01-14: wsfulton
+ Fix deduction of partially specialized template parameters when the specialized
+ parameter is non-trivial, used in a wrapped method and the type to %template uses
+ typedefs. For example:
+
+ typedef double & DoubleRef;
+ template <typename T> struct XX {};
+ template <typename T> struct XX<T &> { void fn(T t) {} };
+ %template(XXD) XX<DoubleRef>;
+
+ The type of the parameter in the instantiated template for fn is now correctly deduced
+ as double.
+
+2023-01-03: wsfulton
+ #983 Fix seg fault when instantiating templates with parameters that are function
+ parameters containing templates, such as:
+
+ %template(MyC) C<int(std::vector<int>)>;
+
+2023-01-03: wsfulton
+ Complete support for C++11 variadic function templates. Support was previously limited
+ to just one template parameter. Now zero or more template parameters are supported
+ in the %template instantiation.
+
+2022-12-29: wsfulton
+ #1863 Syntax error fixes parsing more elaborate parameter pack arguments that are
+ used in function pointers, member function pointers:
+
+ template <typename... V> struct VariadicParms {
+ void ParmsFuncPtrPtr(int (*)(V*...)) {}
+ void ParmsFuncPtrPtrRef(int (*)(V*&...)) {}
+ void ParmsFuncPtrPtrRValueRef(int (*)(V*&&...)) {}
+ void ParmsFuncPtrRef(int (*)(V&...)) {}
+ void ParmsFuncPtrRValueRef(int (*)(V&&...)) {}
+
+ void ParmsMemFuncPtrPtr(int (KlassMemFuncs::*)(V*...)) {}
+ void ParmsMemFuncPtrPtrRef(int (KlassMemFuncs::*)(V*&...)) {}
+ void ParmsMemFuncPtrPtrRValueRef(int (KlassMemFuncs::*)(V*&&...)) {}
+ void ParmsMemFuncPtrRef(int (KlassMemFuncs::*)(V&...)) {}
+ void ParmsMemFuncPtrRValueRef(int (KlassMemFuncs::*)(V&&...)) {}
+ };
+
+ %template(VariadicParms0) VariadicParms<>;
+ %template(VariadicParms1) VariadicParms<A>;
+
+ Also in various other places such as within noexcept specifiers:
+
+ template<typename T, typename... Args>
+ void emplace(Args &&... args) noexcept(
+ std::is_nothrow_constructible<T, Args &&...>::value);
+
+2022-12-27: wsfulton
+ Fix instantiation of variadic class templates containing parameter pack arguments that
+ are function pointers.
+
+ template <typename... V> struct VariadicParms {
+ void ParmsFuncPtrVal(int (*)(V...)) {}
+ };
+
+ %template(VariadicParms0) VariadicParms<>;
+ %template(VariadicParms1) VariadicParms<A>;
+
+2022-12-23: wsfulton
+ #1863 Fix syntax error parsing variadic templates containing parameter pack arguments that
+ are function pointers.
+
+2022-12-22: wsfulton
+ Complete support for C++11 variadic class templates. Support was previously limited
+ to just one template parameter. Now zero or more template parameters are supported.
+
+2022-12-06: wsfulton
+ #1636 Fix syntax error for misplaced Doxygen comment after struct/class member.
+ Fix syntax error using Doxygen member groups syntax, "///*}", when used after
+ final struct/class member.
+
+2022-12-05: wsfulton
+ #2023 Fix garbled Doxygen post comments in parameter lists.
+ Fix syntax error parsing a trailing Doxygen comment in parameter lists.
+
+2022-12-03: wsfulton
+ #1609 Fix syntax error parsing of Doxygen comments after last enum item.
+
+2022-12-03: wsfulton
+ #1715 Fix syntax error parsing of unconventionally placed Doxygen post
+ comments for enum items.
+
+2022-12-02: wsfulton
+ #624 #1021 Improved template template parameters support. Previously, specifying more
+ than one simple template template parameter resulted in a parse error. Now
+ multiple template template parameters are working including instantiation with
+ %template. Example:
+
+ template <template<template<class> class, class> class Op, template<class> class X, class Y>
+ class C { ... };
+
+2022-11-26: wsfulton
+ #1589 #1590 Slightly better decltype() support for expressions, such as:
+
+ int i;
+ ... decltype(&i) ...
+
+ These result in a warning for non-trivial expressions which SWIG cannot evaluate:
+
+ Warning 344: Unable to deduce decltype for '&i'.
+
+ See 'Type Inference' in CPlusPlus.html for workarounds.
+
+2022-11-22: wsfulton
+ #366 #1037 Fix seg fault handling template parameter expressions
+ containing '<=' or '>='.
+
+2022-11-18: wsfulton
+ Duplicate class template instantiations via %template now issue a warning and are ignored.
+
+ %template(Aint) A<int>;
+ %template(Aint2) A<int>; // Now ignored and issues a warning
+
+ example.i:7: Warning 404: Duplicate template instantiation of 'A< int >' with name 'Aint2' ignored,
+ example.i:6: Warning 404: previous instantiation of 'A< int >' with name 'Aint'.
+
+ A single empty template instantiation before a named instantiation is the one exception
+ for allowing duplicate template instantiations as the empty template instantiation does not
+ create a wrapper for the template, it merely adds the instantiation into SWIG's internal
+ type system.
+ Duplicate empty template instantiations are quietly ignored.
+
+ %template() B<int>;
+ %template(Bint) B<int>; // OK
+
+ %template() C<int>;
+ %template() C<int>; // Quietly ignored now
+ %template(Cint) C<int>; // OK
+
+ Note that default template parameters are considered when looking for duplicates such as:
+
+ template <typename T, typename U = short> struct D {};
+ %template(Dint) D<int>;
+ %template(Dintshort) D<int, short>;
+
+ example.i:7: Warning 404: Duplicate template instantiation of 'D< int,short >' with name 'Dintshort' ignored,
+ example.i:6: Warning 404: previous instantiation of 'D< int >' with name 'Dint'.
+
+ Note that the following always was ignored, but that was because the chosen name was a
+ duplicate rather than the template being a duplicate:
+
+ %template(Eint) E<int>;
+ %template(Eint) E<int>; // Always has been ignored as a redefined identifier
+
+ The old warning was:
+
+ example.i:7: Warning 302: Identifier 'Eint' redefined (ignored) (Renamed from 'E< int >'),
+ example.i:6: Warning 302: previous definition of 'Eint' (Renamed from 'E< int >').
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+Version 4.1.1 (30 Nov 2022)
+===========================
+
+2022-11-29: bero
+ Fix mismatch between #pragma GCC diagnostic push and pop statements
+
+2022-11-26: wsfulton
+ #2449 Fix undefined behaviour in ccache-swig calculating md4 hashes and possibly
+ also handling errors when CCACHE_CPP2 is set.
+
+2022-11-25: wsfulton
+ #961 Fix syntax error parsing unnamed template parameters with a default value.
+
+2022-11-25: olly
+ #2447 Fix undefined behaviour in swig's parser when handling
+ default parameter expressions containing method calls.
+
+2022-11-13: olly
+ [PHP] #2419 Update the documentation to reflect that SWIG 4.1.0
+ dropped support for -noproxy when generating PHP wrappers.
+
+2022-11-05: wsfulton
+ #2417 Fix -swiglib for Windows when building with CMake.
+
+2022-11-02: wsfulton
+ #2418 Fix infinite loop handling non-type template parameters.
+
+ Fixes infinite loop due to () brackets in a non-type template
+ parameter containing an expression.
+
+2022-10-28: wsfulton
+ [R] R rtypecheck typemaps
+
+ Further switch to use rtypecheck typemaps instead of hard coded logic.
+ The full switch to typemaps is deferred until swig-4.2 as it can't be fully
+ backwards compatible. For now a warning is provided to help the
+ transition. It provides the full typemap that should be placed into
+ a user's interface file, for example:
+
+ %typemap("rtype") int32_t * "integer"
+ void testmethod(int32_t * i);
+ void testmethod();
+
+ If there is no rtypecheck typemap for int32_t *, the warning shown is:
+
+ example.i:7: Warning 750: Optional rtypecheck code is deprecated. Add the
+ following typemap to fix as the next version of SWIG will not work without it:
+ %typemap("rtypecheck") int32_t * %{ (is.integer($arg) || is.numeric($arg)) %}
+
+ The warning is shown for any code that previously used "numeric", "integer" or
+ "character" for the rtype typemap. Copying the rtypecheck typemap as
+ shown into the user interface file will provide the appropriate fix and
+ the warning will disappear. This is important to do as swig-4.2 will
+ not be able to provide this helpful warning.
+
+2022-10-27: wsfulton
+ [R] Allow NULL to be used in overloaded functions taking shared_ptr.
+ Also fixes special variable $argtype expansion in rtypecheck typemaps.
+
+2022-10-26: wsfulton
+ [R] Improve R wrapper error message when calling overloaded methods
+ when incorrect types passed are passed to the overloaded methods.
+
+ Old unhelpful error message:
+ Error in f(...) : could not find function "f"
+
+ Example of new improved error message:
+ Error in use_count(k) :
+ cannot find overloaded function for use_count with argtypes (NULL)
+
+2022-10-26: wsfulton
+ [R] #2386 Fix memory leak in R shared_ptr wrappers.
+ Fix leak when a cast up a class inheritance chain is required.
+
+Version 4.1.0 (24 Oct 2022)
+===========================
+
+2022-10-24: wsfulton, AndLLA
+ [R] #2386 Fix problems in shared_ptr wrappers where the class names
+ were not consistent when using the shared_ptr template or the actual
+ underlying type.
+
+2022-10-24: wsfulton
+ [R] Add support for special variable replacement in the $typemap()
+ special variable macro for R specific typemaps (rtype, rtypecheck,
+ scoercein, scoereout).
+
+2022-10-24: wsfulton
+ [R] Polymorphism in the wrappers was only working for C++ classes,
+ now this works for C++ structs too.
+
+2022-10-19: olly
+ [Lua] #2126 Fix type resolution between multiple SWIG-wrapped
+ modules.
+
+2022-10-17: wsfulton
+ [R] #2385 Add support for std::vector<std::vector<std::string>>.
+
+2022-10-14: murillo128
+ [Javascript] #2109 Tweak unsigned long and unsigned long long typemaps
+ to create a v8::Number instead of v8::Integer if the value exceeds
+ the size of v8::Integer. Note that the v8::Number value will be
+ imprecise if the value is > MAX_SAFE_INTEGER.
+
+2022-10-14: olly
+ [R] Arrange that destructors of local C++ objects in the wrapper
+ function get run on SWIG_fail (which calls Rf_error() which calls
+ longjmp()).
+
+2022-10-14: olly
+ [Lua] Arrange that destructors of local C++ objects in the wrapper
+ function get run on SWIG_fail (which calls lua_error() which calls
+ longjmp()).
+
+2022-10-13: wsfulton
+ [R] Add missing SWIGTYPE *const& typemaps for supporting pointers
+ by const reference.
+
+2022-10-10: wsfulton
+ #2160 Fix compile error when using templates with more than one template
+ parameter and used as an input parameter in a virtual method in a
+ director class (problem affecting most of the scripting languages).
+
+2022-10-10: treitmayr, wsfulton
+ [Python, Ruby] #1811 #1823 Fix invalid code generated in some cases when
+ returning a pointer or reference to a director-enabled class instance.
+ This previously only worked in very simple cases, now return types are
+ resolved to fix. A bug in template instantiations using pointers also
+ works now.
+
+2022-10-06: wsfulton
+ [CFFI] #1966 #2200 Remove code for Common Lisp CFFI. We dropped support
+ for it in SWIG 4.0.0 by disabling it as the first stage. This is the
+ final stage for complete removal as there has been no meaningful
+ progress to revive it to the status of experimental language.
+
+2022-10-06: olly
+ [Python] #2390 Remove deprecated and apparently useless defarg.swg
+
+ The only documentation is in the file itself and describes a Python
+ wrapper around the C function defined here, but digging though the
+ git history this Python wrapper doesn't seem to have ever actually
+ been generated by SWIG.
+
+ This file was also marked as deprecated in 2005.
+
+2022-10-06: wsfulton
+ [Java] #2048 Fix quoting for doxygen \image command to quote the output
+ file name generated into the html src attribute.
+
+2022-10-05: benjamin-sch
+ [Python] added an interpreter counter to fix deinitialization
+ issues if multiple subinterpreters are used
+
+2022-10-05: olly, wsfulton
+ #672 Add support for parsing C++11 final classes such as:
+
+ class X final {};
+
+ This no longer gives a syntax error.
+
+2022-10-05: wsfulton
+ [OCaml] Fix %rename for enum items. Previously the rename had no effect.
+
+2022-10-05: olly
+ #1465 Report errors in preprocessor expressions by default
+
+ Until now SWIG quietly ignored such errors unless -Wextra (or -Wall
+ which implies -Wextra) was passed, but this is unhelpful as it tends
+ to hide genuine problems. To illustrate this point, enabling this
+ warning by default revealed a typo in the preproc_defined.i
+ testcase in SWIG's own testsuite.
+
+ If you really don't want to see this warning, you can suppress it
+ with command line option -w202 or by using this in your interface
+ file:
+
+ %warnfilter(SWIGWARN_PP_EVALUATION);
+
+ Both will work with older versions of SWIG too.
+
+2022-10-04: olly
+ #1050 Consistently define SWIG_VERSION both at SWIG-time and in
+ the generated wrapper. Best practice remains to check at SWIG-time
+ where possible because that results in smaller generated wrapper
+ sources.
+
+ SWIGGO and SWIGJAVASCRIPT are now defined in the generated wrappers
+ to match behaviour for all other target languages.
+
+ The undocumented SWIGVERSION macro is no longer defined.
+
+2022-09-29: olly
+ #2303 SWIG's internal hash tables now use a better hash function.
+
+ The old hash function only considerd the last five characters
+ plus the least significant bit of the last-but-sixth character,
+ which as you might guess generated a lot of many-way collisions.
+
+ This change seems to give about a 4% reduction in wallclock time
+ for processing li_std_list_wrap.i from the testsuite for Python.
+ The hash collision rate for this example drops from 39% to 0!
+
+2022-09-29: wsfulton
+ #2303 Type tables are now output in a fixed order whereas previously
+ the order may change with any minor input code change. This shouldn't
+ affect users except SWIG_TypePrettyName may output a different C/C++
+ typedef to a type - it's used mostly for showing errors when the type
+ passed to a function is wrong.
+
+2022-09-29: olly
+ [PHP] Dynamic class properties are no longer supported by default.
+
+ Historically PHP has supported dynamic class properties and SWIG
+ has implemented them too (because we implement the magic __get(),
+ __set() and __isset() methods we need to include explicit
+ handling).
+
+ PHP 8.2 deprecates dynamic class properties - initially they'll
+ warn, and apparently they'll not work by default in PHP 9.0:
+ https://wiki.php.net/rfc/deprecate_dynamic_properties
+
+ In PHP code dynamic properties can be enabled for a class by
+ marking that class with the attribute `#[AllowDynamicProperties]`.
+
+ To follow this PHP change, in SWIG you now need to specify
+ `%feature("php:allowdynamicproperties", 1) Foo;` (or
+ `%feature("php:allowdynamicproperties", 1)` to enable it for
+ all wrapped classes). Unknown features are ignored, so you can add
+ it unconditionally and it'll work with older SWIG too.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-09-19: wsfulton
+ #1484 Fixes for class inheritance with the same name in different namespaces
+ such as:
+
+ namespace A { class Bar {}; }
+ namespace B { template<typename T, typename U> class Bar : public A::Bar {}; }
+
+2022-09-19: wsfulton
+ #2316 Remove swig.spec file and srcrpm makefile target. These are very out of date
+ and don't seem to be used by RPM based Linux distributions which have their
+ own version of swig.spec.
+
+2022-09-17: wsfulton
+ [Go, Guile, Racket, Scilab] Add throws typemaps for std::string so that thrown
+ string exception messages can be seen.
+
+2022-09-17: wsfulton
+ [Racket] Add throws typemaps for char * so that thrown string exception
+ messages can be seen from Racket.
+
+2022-09-17: wsfulton
+ [Javascript, Octave, R] Improve exceptions for %catches and exception
+ specifications for native types. String exception messages are shown as
+ the exception message instead of just the type of the exception.
+
+2022-09-17: wsfulton
+ Add missing typecheck typemaps for std::auto_ptr and std::unique_ptr to
+ fix overloading when using these types.
+
+2022-09-17: wsfulton
+ [Guile] Add error checking to SWIGTYPE and SWIGTYPE & in typemaps to prevent
+ seg faults when passing #nil to these parameter types.
+
+2022-09-16: wsfulton
+ #999 Provide SWIGTYPE MOVE typemaps in swigmove.i for implementing full
+ move semantics when passing parameters by value.
+
+2022-08-31: wsfulton
+ #999 Improve move semantics when using rvalue references.
+ The SWIGTYPE && input typemaps now assume the object has been moved.
+
+ These typemaps have been changed assuming that after the function call,
+ the rvalue reference parameter has been moved. The parameter's proxy class
+ that owns the C++ object thus has the underlying pointer set to null
+ so that the (moved from, but still valid) C++ object cannot be used again
+ and the object is additionally deleted.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-08-28: wsfulton
+ [Octave] SWIG now marshals a C/C++ NULL pointer into the null matrix, [].
+ SWIG has always marshalled the null matrix into a NULL pointer; this remains
+ and now we have consistency in representing a NULL pointer.
+
+2022-08-26: wsfulton
+ [Racket] SWIG now marshals a C/C++ NULL pointer into a null value by calling
+ scheme_make_null(), so that scheme's null? is true for a NULL C/C++ pointer value.
+
+2022-08-18: wsfulton
+ [Racket] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-08-13: wsfulton
+ [Guile] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-08-11: wsfulton
+ [Lua] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-08-05: wsfulton
+ [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly
+ when using virtual inheritance as the pointers weren't correctly upcast from derived
+ class to base class when stored in the base's proxy class.
+
+2022-08-05: wsfulton
+ [D] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-08-03: wsfulton
+ [Javascript] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-08-02: wsfulton
+ [Octave] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-08-01: wsfulton
+ [Python] Add initialisers for additional members in PyHeapTypeObject
+ (builtin mode) for Python-3.11 - _ht_tpname, _spec_cache.
+
+2022-07-30: wsfulton
+ C++20 has deprecated std::basic_string<>::reserve() and the C++11 method
+ std::basic_string<>::shrink_to_fit() is a replacement that can be used.
+ std_string.i and std_wstring.i provided wrappers for reserve with the following
+ template instantiations:
+
+ %template(string) std::basic_string<char>;
+ %template(wstring) std::basic_string<wchar_t>;
+
+ The reserve method is no longer wrapped, however the shrink_to_fit() method
+ can be used as an alternative from the target language (the generated wrappers
+ call reserve() instead if C++<=20).
+
+ Note that std::basic_string<>::reserve(size_t n) is still wrapped unchanged.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-07-30: wsfulton
+ [Tcl] Add support for std::unique_ptr in std_unique_ptr.i.
+ Add support for std::auto_ptr in std_auto_ptr.i.
+
+2022-07-27: ZackerySpytz, olly
+ #1678 Support parsing C++20 templated lambdas.
+
+2022-07-27: ZackerySpytz, olly
+ #1622 Add support for the C++20 spaceship operator (<=>).
+
+2022-07-26: olly
+ [Tcl] https://sourceforge.net/p/swig/bugs/977/
+ Fix handling of long long on 32-bit platforms. This fix raises
+ SWIG's minimum supported Tcl version to 8.4.0 (which was released
+ just under 20 years ago).
+
+2022-07-26: olly
+ Fix incorrect operator precedence in preprocessor expressions.
+
+2022-07-25: olly
+ Support for C++14 binary integer literals in preprocessor expressions.
+
+2022-07-20: wsfulton
+ [C#, Java] Ensure the order of interfaces generated in proxy interfaces for the
+ %interface family of macros is the same as that parsed from the bases in C++.
+
+2022-07-20: jicks, Ingener74, olly
+ #422 [Python] Fix mishandling of a Python class inheriting from
+ multiple SWIG-wrapped director classes.
+
+2022-07-19: wsfulton
+ #692 [C#, Java, Perl, Python, Ruby] std::unique_ptr and std::auto_ptr typemaps
+ provided for inputs types in std_unique_ptr.i and std_auto_ptr.i.
+
+ Now these smart pointers can be used as input parameters to functions. A proxy
+ class instance transfers memory ownership of the underlying C++ object from the
+ proxy class to a smart pointer instance passed to the wrapped function.
+
+2022-07-19: jschueller
+ [Python] #2314 Drop support for Python 3.2.
+
+2022-07-19: olly
+ Remove remaining support code for classic macos, which has not been
+ supported by Apple for over 20 years now.
+
+2022-07-12: wsfulton
+ #999 Performance optimisation for parameters passed by value that are C++11 movable.
+ The C++ wrappers create a temporary variable for a parameter to be passed to a
+ function. This is initially default constructed and then copy assigned from the
+ instance being passed in from the target language. This is unchanged, however,
+ when the temporary variable is passed to the wrapped function, it is now done using
+ std::move. If the type is move constructible, the move constructor will be used
+ instead of the copy constructor.
+
+2022-07-12: wsfulton
+ [Perl] Add std::auto_ptr support in std_auto_ptr.i library file.
+
+2022-07-12: erezgeva
+ [Perl] Add std::unique_ptr support in std_unique_ptr.i library file.
+
+2022-07-07: jmarrec
+ #1158 #2286 Add basic support for C++11 attributes. These are now
+ crudely ignored by SWIG's parser's tokeniser, which is better than
+ failing with a parse error.
+
+2022-07-05: ianlancetaylor
+ [Go] #2245 Handle NULL pointers for string* conversions.
+ Rearrange generation of director methods and rename
+ receiver argument from p to swig_p.
+
+2022-07-03: wsfulton
+ #999 Performance optimisation for directors for classes passed by value. The directorin
+ typemaps in the director methods now use std::move on the input parameter when
+ copying the object from the stack to the heap prior to the callback into the target
+ language, thereby taking advantage of move semantics if available.
+
+2022-07-02: wsfulton
+ #1722 [C#, Java, Python, Ruby] Add std::unique_ptr support. Ported from std::auto_ptr.
+ Use the %unique_ptr(T) macro as follows for usage std::unique_ptr<T>. For example, for
+ a class called Klass:
+
+ %include "std_unique_ptr.i"
+ %unique_ptr(Klass)
+
+ Support is currently limited to only returning a std::unique_ptr from a function.
+
+2022-06-29: wsfulton
+ #999 #1044 Enhance SWIGTYPE "out" typemaps to use std::move when copying
+ objects, thereby making use of move semantics when wrapping a function returning
+ by value if the returned type supports move semantics.
+
+ Wrapping functions that return move only types 'by value' now work out the box
+ without having to provide custom typemaps.
+
+ The implementation removed all casts in the "out" typemaps to allow the compiler to
+ appropriately choose calling a move constructor, where possible, otherwise a copy
+ constructor. The implementation also required modifying SwigValueWrapper to
+ change a cast operator from:
+
+ SwigValueWrapper::operator T&() const;
+
+ to
+
+ #if __cplusplus >=201103L
+ SwigValueWrapper::operator T&&() const;
+ #else
+ SwigValueWrapper::operator T&() const;
+ #endif
+
+ This is not backwards compatible for C++11 and later when using the valuewrapper feature
+ if a cast is explicitly being made in user supplied "out" typemaps. Suggested change
+ in custom "out" typemaps for C++11 and later code:
+
+ 1. Try remove the cast altogether to let the compiler use an appropriate implicit cast.
+ 2. Change the cast, for example, from static_cast<X &> to static_cast<X &&>, using the
+ __cplusplus macro if all versions of C++ need to be supported.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-06-15: wsfulton
+ #2039 Add move assignment operator to SwigValueWrapper used by the
+ valuewrapper feature.
+
+2022-06-04: sethrj
+ Enhance $typemap to support typemap attributes.
+
+ $typemap(method:attribute, typepattern)
+
+ For example:
+
+ %typemap(cstype, out="object") XClass "XClass"
+ %typemap(cscode) BarClass %{
+ $typemap(cstype:out, XClass) bar() {
+ return null;
+ }
+
+ which expands to
+
+ object bar() {
+ return null;
+ }
+
+2022-05-30: wsfulton
+ [C#, D] Add new special variable expansion: $imfuncname.
+ Expands to the function name called in the intermediary class.
+
+2022-05-30: LindleyF
+ [Java] #2042 Add new special variable expansion: $imfuncname.
+ Expands to the function name called in the intermediary class.
+
+2022-05-28: jkuebart
+ [Java] On some versions of Android, specifically Android 6,
+ detaching the current thread from the JVM after every invocation
+ causes a memory leak.
+
+ Offer SWIG_JAVA_DETACH_ON_THREAD_END to configure a behaviour
+ where the JVM is only detached in the thread destructor.
+
+ See https://developer.android.com/training/articles/perf-jni#threads.
+
+2022-05-27: xypron
+ [Python] #2277 Define PY_SSIZE_T_CLEAN macro before #include "Python.h" as
+ recommended in Python 3.7 and later.
+
+ To avoid this macro definition, add the following to your interface file so
+ that SWIG_NO_PY_SSIZE_T_CLEAN is defined at the beginning of the C++ wrappers:
+
+ %begin %{
+ #define SWIG_NO_PY_SSIZE_T_CLEAN
+ %}
+
+2022-05-26: rokups
+ [C#] #1323 Modify SwigDerivedClassHasMethod for a more efficient director
+ implementation when calling virtual methods that are not overridden.
+
+2022-05-15: erezgeva, eiselekd
+ [Lua, Perl, Octave, PHP, Tcl] #2275 #2276 #2283 Add argcargv.i library containing
+ (int ARGC, char **ARGV) multi-argument typemaps.
+
+ Document this library in Typemaps.html.
+
+2022-05-07: KrisThielemans
+ [Python] Fix "too many initializers for 'PyHeapTypeObject'" errors
+ using PyPy 3.8 and later.
+
+2022-05-04: wsfulton
+ [C#] Add C# wchar_t * director typemaps
+
+2022-04-20: cminyard
+ Fix an issue where newlines were not properly generated
+ for godirectorin typemaps. If you have a virtual function
+ not assigned to zero, in some cases it won't generate a
+ newline and you will see errors:
+ example.go:1508:3: expected ';', found swig_r
+ when compiling the go code.
+
+ Also add an example of using goin and godirectorin and add
+ a test for this situation.
+
+2022-04-29: jason-daly, JerryJoyce, wsfulton
+ [C#] #1233 Add wchar_t * and std::wstring Unicode string support on Linux.
+
+2022-04-11: robinst
+ #2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA
+ class swig_runtime_data".
+
+2022-04-07: olly
+ #1750 SWIG now recognises and ignores Doxygen group commands `@{` and `@}`.
+
+2022-04-06: wsfulton
+ ./configure now enables C++11 and later C++ standards testing by default (when
+ running: 'make check').
+
+ The options to control this testing are the same:
+
+ ./configure --enable-cpp11-testing
+ ./configure --disable-cpp11-testing
+
+ But the former is now the default and the latter can be used to turn off C++11 and
+ later C++ standards testing.
+
+2022-04-06: wsfulton
+ [Python] #1635 The "autodoc" feature no longer overrides Doxygen comments
+ in the generated docstring.
+
+ If a "docstring" feature is present it will still override a Doxygen comment.
+ If the "autodoc" feature is also present, the combined "autodoc" and "docstring"
+ will override the Doxygen comment. If no "docstring" is present then the
+ "autodoc" feature will not be generated when there is a Doxygen comment.
+
+ This way the "autodoc" feature can be specified and used to provide documentation
+ for 'missing' Doxygen comments.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-04-01: olly
+ Remove undocumented and non-functional -browse command line option.
+
+2022-03-26: eltoder
+ [Python] #1684 Use different capsule names with and without -builtin
+
+ Types generated with and without -builtin are not compatible. Mixing
+ them in a common type list leads to crashes. Avoid this by using
+ different capsule names: "type_pointer_capsule" without -builtin and
+ "type_pointer_capsule_builtin" with.
+
+2022-03-25: wsfulton
+ The debug command line options that display parse tree nodes
+ (-debug-module, -debug-top, -debug-symtabs) now display previously hidden
+ linked list pointers which are useful for debugging parse trees.
+
+ Added new command line option -debug-quiet. This suppresses the display
+ of most linked list pointers and symbol table pointers in the parse tree nodes.
+
+ The keys in the parse tree node are now shown in alphabetical order.
+
+2022-03-24: wsfulton
+ #2244 Fix using declaration in derived class bugs when all the base
+ class's overloaded methods were overridden in the derived class -
+ fixes "multiply defined" errors.
+
+2022-03-23: wsfulton
+ [Python] #1779 The -py3 option is deprecated and now has no effect on the
+ code generated. Use of this option results in a deprecated warning.
+ The related SWIGPYTHON_PY3 macro that this option defined is no longer generated.
+
+ Note that %pythonnondynamic feature generates a metaclass that works on both
+ Python 2 and Python 3.
+
+2022-03-21: wsfulton
+ [Python] #1779 pyabc.i for abstract base classes now supports versions of
+ Python prior to 3.3 by using the collection module for these older versions.
+ Python-3.3 and later continue to use the collections.abc module.
+ The -py3 option no longer has any effect on the %pythonabc feature.
+
+2022-03-21: jschueller, jim-easterbrook, wsfulton
+ [Python] #2137 C++ static member functions no longer generate a "flattened"
+ name in the Python module. For example:
+
+ s = example.Spam()
+ s.foo() # Spam::foo() via an instance
+ example.Spam.foo() # Spam::foo() using class method
+ example.Spam_foo() # Spam::foo() "flattened" name
+
+ The "flattened" name is no longer generated, but can be generated
+ by using the new -flatstaticmethod option.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-03-18: ianlancetaylor
+ [Go] #337 Implement %extend base methods in child classes.
+
+2022-03-17: olly
+ [Python] #1779 SWIG's Python test-suite and examples are now
+ run with Python 3 by default. To run them with Python 2, set
+ PY2 to a non-empty value, e.g.:
+
+ make check-python-test-suite PY2=1
+
+2022-03-16: olly
+ [Go] #683 -intgosize is now optional - if not specified the
+ generated C/C++ wrapper code will use ptrdiff_t for intgo and
+ size_t for uintgo.
+
+2022-03-15: ianlancetaylor
+ [Go] Add typemaps for std::string*.
+
+2022-03-15: ianlancetaylor
+ [Go] Don't convert arrays to pointers if there is a "gotype"
+ typemap entry.
+
+2022-03-15: ianlancetaylor
+ [Go] Add documentation note about Go and C++ exceptions.
+
+2022-03-12: wsfulton
+ #1524 %interface family of macros no longer contain the getter/setter
+ methods for wrapping variables. The interface only contains
+ virtual and non-virtual instance methods, that is, no static methods.
+ Enums are also no longer added to the interface (affects Java only where
+ they were missing from the proxy class, C# never had them in the interface).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-03-12: wsfulton
+ #1277 Fixes for the family of %interface macros, %interface,
+ %interface_impl and %interface_custom fixes for overloaded methods
+ in an inheritance chain.
+
+ When C++ methods are not able to be overloaded in a derived class,
+ such as when they differ by just const, or the target language
+ parameters types are identical even when the C++ parameter types
+ are different, SWIG will ignore one of the overloaded methods with
+ a warning. A %ignore is required to explicitly ignore one of the
+ overloaded methods to avoid the warning message. Methods added
+ in the derived classes due to one of the %interface macros are now
+ similarly ignored/not added to the derived class.
+
+ The methods added to the derived classes can now also be modified
+ via %feature and %rename.
+
+2022-03-08: ianlancetaylor
+ [Go] Treat a nil argument as a NULL pointer.
+
+2022-03-08: ianlancetaylor
+ [Go] Add documentation notes about thread local storage.
+
+2022-03-08: olly
+ #1006 SWIG now copes with an interface filename specified on the
+ command line which contains a closing parenthesis `)`, and more
+ generally with attributes to `%include` and `%import` which
+ are quoted and contain parentheses.
+
+2022-03-07: Omar Medina
+ [Tcl] https://sourceforge.net/p/swig/bugs/1290/
+ Fix SWIG_AsWCharPtrAndSize() to actually assign to result
+ variable. It looks like SWIG/Tcl wide character handling is
+ currently fundamentally broken except on systems which use wide
+ characters as the system encoding, but this should fix wrapping
+ functions which take a wide string as a parameter on Microsoft
+ Windows.
+
+2022-03-07: olly
+ [Javascript] #682 Fix handling of functions which take void*.
+
+2022-03-06: olly
+ SWIG should now reliably exit with status 0 if the run was
+ successful and status 1 if there was an error (or a warning and
+ -Werror was in effect).
+
+ Previously in some situations SWIG would try to exit with the
+ status set to the number of errors encountered, but that's
+ problematic - for example if there were 256 errors this would
+ result in exit status 0 on most platforms. Also some error
+ statuses have special meanings e.g. those defined by <sysexits.h>.
+ Also SWIG/Javascript tried to exit with status -1 in a few places
+ (which typically results in exit status 255).
+
+2022-03-05: wsfulton
+ #1441 Fix using declaration in derived class incorrectly introducing a method
+ from a base class when the using declaration is declared before the method
+ declaration. Problem occurred when within a namespace and the parameter types
+ in the method signatures were not fully qualified.
+
+2022-03-05: ianlancetaylor
+ [Go] Treat non-const references as pointers.
+
+2022-03-05: ianlancetaylor
+ In SWIG Go testsuite, fail test if "go build" fails.
+
+2022-03-03: olly
+ #1901 #2223 SWIG should now always exit cleanly if memory
+ allocation fails, including removing any output files created
+ during the current run.
+
+ Previously most places in the code didn't check for a NULL return
+ from malloc()/realloc()/calloc() at all, typically resulting in
+ undefined behaviour; some places used assert() to check for a NULL
+ return (which is a misuse of assert() and such checks disappear if
+ built with NDEBUG defined leaving us back with undefined
+ behaviour).
+
+2022-03-03: olly
+ #891 Report errors for typemap attributes without a value
+ (previously SWIG segfaulted) and for typemap types with a value
+ (previously the value was quietly ignored).
+
+ The old way of specifying a language name in the typemap attributes
+ is no longer supported (it has been deprecated for 16 years).
+
+2022-03-02: geographika, wsfulton
+ [Python] #1951 Add Python variable annotations support.
+
+ Both function annotations and variable annotations are turned on using the
+ "python:annotations" feature. Example:
+
+ %feature("python:annotations", "c");
+
+ struct V {
+ float val;
+ };
+
+ The generated code contains a variable annotation containing the C float type:
+
+ class V(object):
+ val: "float" = property(_example.V_val_get, _example.V_val_set)
+ ...
+
+ Python 3.5 and earlier do not support variable annotations, so variable
+ annotations can be turned off with a "python:annotations:novar" feature flag.
+ Example turning on function annotations but not variable annotations globally:
+
+ %feature("python:annotations", "c");
+ %feature("python:annotations:novar");
+
+ or via the command line:
+
+ -features python:annotations=c,python:annotations:novar
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-02-27: wsfulton
+ [Python] #735 #1561 Function annotations containing C/C++ types are no longer
+ generated when using the -py3 option. Function annotations support has been
+ moved to a feature to provide finer grained control. It can be turned on
+ globally by adding:
+
+ %feature("python:annotations", "c");
+
+ or by using the command line argument:
+
+ -features python:annotations=c
+
+ Also see entry dated 2022-03-02, regarding variable annotations.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-02-26: wsfulton
+ #655 #1840 Add new warning WARN_LANG_USING_NAME_DIFFERENT to warn when a
+ method introduced by a using declaration in a derived class cannot
+ be used due to a conflict in names.
+
+2022-02-24: olly
+ #1465 An invalid preprocessor expression is reported as a pair of
+ warnings with the second giving a more detailed message from the
+ expression evaluator. Previously SWIG prefixed the second message
+ with "Error:" - that was confusing as it's actually only a warning
+ by default so we've now dropped this prefix.
+
+ Before:
+
+ x.i:1: Warning 202: Could not evaluate expression '1.2'
+ x.i:1: Warning 202: Error: 'Floating point constant in preprocessor expression'
+
+ Now:
+
+ x.i:1: Warning 202: Could not evaluate expression '1.2'
+ x.i:1: Warning 202: Floating point constant in preprocessor expression
+
+2022-02-23: olly
+ #1384 Fix a preprocessor expression evaluation bug. A
+ subexpression in parentheses lost its string/int type flag and
+ instead used whatever type was left in the stack entry from
+ previous use. In practice we mostly got away with this because
+ most preprocessor expressions are integer, but it could have
+ resulted in a preprocessor expression incorrectly evaluating as
+ zero. If -Wextra was in use you got a warning:
+
+ Warning 202: Error: 'Can't mix strings and integers in expression'
+
+2022-02-21: davidcl
+ [Scilab] Improve 5.5.2, 6.0.0 and 6.1.0 support.
+
+ For Scilab 5, long names are reduced to small names preserving the
+ class prefix and accessor suffix (get or set).
+
+ For Scilab 6, long names with the class prefix and accessor suffix
+ should be used on the user code.
+
+ The `-targetversion` option has been removed as the generated code
+ now detects the Scilab version in loader.sce or builder.sce.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-02-20: wsfulton
+ Fix %warnfilter warning suppress for warning 315 SWIGWARN_PARSE_USING_UNDEF.
+
+2022-02-17: olly
+ [PHP] https://sourceforge.net/p/swig/bugs/1211/
+ Fix to call cleanup code in exception situations and not to invoke
+ the freearg typemap twice in certain situations.
+
+2022-02-15: olly
+ #300 #368 Improve parser handling of % followed immediately by
+ an identifier. If it's not a recognised directive the scanner
+ now emits MODULO and then rescans what follows, and if the parser
+ then gives a syntax error we report it as an unknown directive.
+ This means that `a%b` is now allowed in an expression, and that
+ things like `%std::vector<std::string>` now give an error rather
+ than being quietly ignored.
+
+2022-02-11: adr26
+ [Python] #2154 Fix memory leak.
+
+ SWIG python objects were being freed after the corresponding SWIG
+ module information was destroyed in Python 3, causing leaks when as
+ a result the object destructor could not be invoked. To prevent this
+ misordering, SWIG python objects now obtain a reference to the
+ Python capsule wrapping the module information, so that the module
+ information is correctly destroyed after all SWIG python objects
+ have been freed (and corresponding destructors invoked).
+
+2022-02-10: olly
+ [Tcl] https://sourceforge.net/p/swig/bugs/1207/
+ https://sourceforge.net/p/swig/bugs/1213/
+
+ Fix Tcl generic input typemap for std::vector.
+
+2022-02-07: sethrj
+ #2196 Add alternative syntax for specifying fragments in typemaps.
+
+ New syntax:
+ %typemap("in", fragment="frag1", fragment="frag2", fragment="frag3") {...}
+ which is equivalent to:
+ %typemap(in, fragment="frag1,frag2,frag3") {...}
+
+
+2022-02-07: olly
+ #1806 Remove support for the "command" encoder, which was mostly
+ intended for use in `%rename` - most uses can be achieved using
+ the "regex" encoder, so we recommend using that instead.
+
+ The "command" encoder suffers from a number of issues - as the
+ documentation for it admitted, "[it] is extremely slow compared to
+ all the other [encoders] as it involves spawning a separate process
+ and using it for many declarations is not recommended" and that it
+ "should generally be avoided because of performance
+ considerations".
+
+ But it's also not portable. The design assumes that `/bin/sh`
+ supports `<<<` but that's a bash-specific feature so it doesn't
+ work on platforms where `/bin/sh` is not bash - it fails on
+ Debian, Ubuntu and probably some other Linux distros, plus most
+ non-Linux platforms. Microsoft Windows doesn't even have a
+ /bin/sh as standard.
+
+ Finally, no escaping of the passed string is done, so it has
+ potential security issues (though at least with %rename the input
+ is limited to valid C/C++ symbol names).
+
+2022-02-06: olly
+ #2193 -DFOO on the SWIG command line now sets FOO to 1 for
+ consistency with C/C++ compiler preprocessors. Previously
+ SWIG set FOO to an empty value.
+
+ Existing invocations of SWIG with `-DFOO` where the empty value
+ matters can be updated to `-DFOO=` which should work with both
+ old and new releases of SWIG.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2022-02-06: sethrj
+ #2194 Classes that are non-assignable due to const data or const
+ reference members are now automatically detected.
+
+2022-02-04: friedrichatgc
+ [Octave] #1672 Fix for isobject for Octave 4.4 - 6.0.
+
+2022-02-03: olly
+ [C#] #283 #998 Fix memory leak in directorin typemap for
+ std::string.
+
+2022-02-03: olly
+ [Python] #967 Make `self` parameter available to user typemaps.
+
+2022-02-03: teythoon
+ [Python] #801 Fix -Wunused-parameter warnings with builtin,
+
+2022-02-03: teythoon
+ #801 Fix -Wstrict-prototypes warnings in generated pointer
+ functions.
+
+2022-02-03: olly
+ #660 https://sourceforge.net/p/swig/bugs/1081/
+ Default parameter values containing method calls are now parsed and
+ handled - e.g. `x->foo(3,4)` and `y.z()`.
+
+2022-02-02: olly
+ [Ruby] https://sourceforge.net/p/swig/bugs/1136/ Fix remove of prefix
+ from method name to only remove it at the start.
+
+2022-02-01: olly
+ #231 Handle returning an object by reference in a C++ trailing
+ return type.
+
+2022-02-01: davidcl
+ [Scilab] #745 use SWIG_<module>_Init() as a C module init function.
+
+2022-02-01: olly
+ [OCaml] #2083 Fix to work when CAML_SAFE_STRING is on, which it is
+ by default in recent Ocaml releases.
+
+2022-01-31: mreeez
+ https://sourceforge.net/p/swig/bugs/1147/
+ Fix copyToR() generated for a struct in a namespace.
+
+2022-01-29: fschlimb
+ #655 Better handling of using declarations.
+
+2022-01-29: dontpanic92
+ [Go] #676 Fix code generated for a C++ class with a non-capitalised
+ name.
+
+2022-01-26: trex58
+ #1919 #1921 #1923 Various fixes for AIX portability.
+
+2022-01-26: olly
+ #1935 Don't crash on an unclosed HTML tag in a doxygen comment
+ when -doxygen is specified.
+
+2022-01-25: olly
+ Constant expressions now support member access with `.` such as
+ `foo.bar`. Previous this only worked in a case like `x->foo.bar`.
+
+2022-01-25: olly
+ #2091 Support most cases of `sizeof` applied to an expression
+ in constant expressions. Previously there was only support for
+ `sizeof(<type>)` and expressions which syntactically look like a
+ type (such as `sizeof(foo)`).
+
+2022-01-25: olly
+ #80 #635 https://sourceforge.net/p/swig/bugs/1139/
+ Add support for parsing common cases of `<` and `>` comparisons
+ in constant expressions. Adding full support for these seems hard
+ to do without introducing conflicts into the parser grammar, but in
+ fact all reported cases have had parentheses around the comparison
+ and we can support that with a few restrictions on the left side of
+ `<`.
+
+2022-01-25: wsfulton
+ New warning 327 for extern templates, eg:
+
+ extern template class std::vector<int>;
+ extern template void Func<int>();
+
+ results in warning
+
+ example.i:3: Warning 327: Extern template ignored.
+ example.i:4: Warning 327: Extern template ignored.
+
+ Extern template classes previously resulted in warning 320.
+
+2022-01-24: romintomasetti
+ #2131 #2157 C++11 extern function template parsing error fix.
+
+2022-01-21: wsfulton
+ #2120 #2138 Replace legacy PCRE dependency with PCRE2.
+ This requires changes for building SWIG from source. See updated
+ html documentation in Preface.html and Windows.html. Updated
+ instructions are also shown when running ./configure if PCRE2 is not
+ found. Note that debian based systems can install PCRE2 using:
+
+ apt install libpcre2-dev
+
+ Note that https://github.com/swig/swig/wiki/Getting-Started also has
+ updated information for building from source.
+
+2022-01-19: olly
+ [PHP] #2027 Automatically generate PHP type declarations for PHP 8.
+ The generate code still compiles for PHP 7.x, but without type
+ declarations since PHP 7.x has much more limited type declaration
+ support.
+
+2022-01-18: olly
+ [Perl] #1629 Perl 5.8.0 is now the oldest version we aim to support.
+
+2022-01-14: wsfulton
+ [Python] Fix %callback and specifying the callback function as a
+ static member function using Python staticmethod syntax, such as
+ Klass.memberfunction instead of Klass_memberfunction when using
+ -builtin and -fastproxy.
+
+2022-01-11: wsfulton
+ [Python] Accept keyword arguments accessing static member functions when
+ using -builtin and kwargs feature and Python class staticmethod syntax.
+ The missing keyword argument support was only when using the
+ class staticmethod syntax, such as Klass.memberfunction, and not when
+ using the flat static method syntax, such as Klass_memberfunction.
+
+2022-01-04: juierror
+ [Go] #2045 Add support for std::array in std_array.i.
+
+2021-12-18: olly
+ [PHP] Add PHP keyword 'readonly' (added in 8.1) to the list SWIG
+ knows to automatically rename. This keyword is special in that PHP
+ allows it to be used as a function (or method) name.
+
+2021-12-07: vstinner
+ [Python] #2116 Python 3.11 support: use Py_SET_TYPE()
+
+2021-12-05: rwf1
+ [Octave] #2020 #1893 Add support for Octave 6 up to and including 6.4.
+ Also add support for compiling with -Bsymbolic which is used by default
+ by mkoctfile.
+
+2021-12-02: jsenn
+ [Python] #2102 Fixed crashes when using embedded Python interpreters.
+
+2021-11-12: wsfulton
+ [Javascript] v8 and node only. Fix mismatched new char[] and free()
+ when wrapping C code char arrays. Now calloc is now used instead of
+ new char[] in SWIG_AsCharPtrAndSize.
+
+2021-10-03: ajrh1
+ [Perl] #2074: Avoid -Wmisleading-indentation in generated code
+ when using gcc11.
+
+2021-10-03: jschueller
+ [CMake] #2065: Add option to enable or disable PCRE support.
+
+2021-09-16: ianlancetaylor
+ [Go] Improved _cgo_panic implementation.
+
+2021-09-16: ianlancetaylor
+ [Go] Don't use crosscall2 for panicking. Instead rely on documented
+ and exported interfaces.
+
+2021-09-14: ianlancetaylor
+ [Go] Remove -no-cgo option (long unsupported in Go)
+
+2021-05-04: olly
+ [PHP] #2014 Throw PHP exceptions instead of using PHP errors
+
+ PHP exceptions can be caught and handled if desired, but if they
+ aren't caught then PHP exits in much the same way as it does for a
+ PHP error.
+
+ In particular this means parameter type errors and some other cases
+ in SWIG-generated wrappers now throw a PHP exception, which matches
+ how PHP's native parameter handling deals with similar situations.
+
+ `SWIG_ErrorCode()`, `SWIG_ErrorMsg()`, `SWIG_FAIL()` and `goto thrown;`
+ are no longer supported (these are really all internal implementation
+ details and none are documented aside from brief mentions in CHANGES
+ for the first three). I wasn't able to find any uses in user interface
+ files at least in FOSS code via code search tools.
+
+ If you are using these:
+
+ Use `SWIG_PHP_Error(code,msg);` instead of `SWIG_ErrorCode(code);
+ SWIG_ErrorMsg(msg);` (which will throw a PHP exception in SWIG >= 4.1
+ and do the same as the individual calls in older SWIG).
+
+ `SWIG_FAIL();` and `goto thrown;` can typically be replaced with
+ `SWIG_fail;`. This will probably also work with older SWIG, but
+ please test with your wrappers if this is important to you.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2021-05-17: adr26
+ [Python] #1985 Fix memory leaks:
+
+ 1. Python object references were being incorrectly retained by
+ SwigPyClientData, causing swig_varlink_dealloc() never to run / free
+ memory. SwigPyClientData_New() / SwigPyClientData_Del() were updated
+ to fix the object reference counting, causing swig_varlink_dealloc()
+ to run and the memory swig_varlink owns to be freed.
+
+ 2. SwigPyClientData itself was not freed by SwigPyClientData_Del(),
+ causing another heap leak. The required free() was added to
+ SwigPyClientData_Del()
+
+ 3. Fix reference counting/leak of python cached type query
+
+ 4. Fix reference counting/leak of SwigPyObject dict (-builtin)
+
+ 5. Python object reference counting fixes for out-of-memory
+ scenarios were added to: SWIG_Python_RaiseOrModifyTypeError(),
+ SWIG_Python_AppendOutput(), SwigPyClientData_New(),
+ SwigPyObject_get___dict__() and SwigPyObject_format()
+
+ 6. Add error handling for PyModule_AddObject() to
+ SWIG_Python_SetModule() (failure could be caused by OOM or a name
+ clash caused by malicious code)
+
+2021-05-13: olly
+ [UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support
+ for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
+ over 2 years.
+
+2021-05-13: olly
+ [S-EXP] #2009 Remove code for Common Lisp S-Exp. We dropped
+ support for it in SWIG 4.0.0 and nobody has stepped forward to
+ revive it in over 2 years.
+
+2021-05-13: olly
+ [Pike] #2009 Remove code for Pike. We dropped support for it in
+ SWIG 4.0.0 and nobody has stepped forward to revive it in over 2
+ years.
+
+2021-05-13: olly
+ [Modula3] #2009 Remove code for Modula3. We dropped support for it
+ in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2
+ years.
+
+2021-05-13: olly
+ [CLISP] #2009 Remove code for GNU Common Lisp. We dropped support
+ for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
+ over 2 years.
+
+2021-05-13: olly
+ [Chicken] #2009 Remove code for Chicken. We dropped support for it
+ in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2
+ years.
+
+2021-05-13: olly
+ [Allegrocl] #2009 Remove code for Allegro Common Lisp. We dropped
+ support for it in SWIG 4.0.0 and nobody has stepped forward to
+ revive it in over 2 years.
+
+2021-05-04: olly
+ [PHP] #1982 #1457 https://sourceforge.net/p/swig/bugs/1339/
+ SWIG now only use PHP's C API to implement its wrappers, and no
+ longer generates PHP code to define classes. The wrappers should
+ be almost entirely compatible with those generated before, but
+ faster and without some previously hard-to-fix bugs.
+
+ The main notable difference is SWIG no longer generates a .php
+ wrapper at all by default (only if %pragma(php) code=... or
+ %pragma(php) include=... are specified in the interface file).
+ This also means you need to load the module via extension=...
+ in php.ini, rather than letting the dl() in the generated
+ .php wrapper load it (but dl() has only worked for command-line
+ PHP for some years now).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2021-04-30: olly
+ #1984 Remove support for $source and $target.
+ These were officially deprecated in 2001, and attempts to use them have
+ resulted in a warning (including a pointer to what to update them to)
+ for most if not all of that time.
+
+2021-04-27: wsfulton
+ #1987 [Java] Fix %interface family of macros for returning by const
+ pointer reference.
+
+2021-04-19: olly
+ Fix use of uninitialised variable in the generated code for an
+ empty typecheck typemap, such as the dummy one we include for
+ std::initializer_list.
+
+2021-04-12: olly
+ #1777 [Python] Specifying -py3 now generates a check for Python
+ version >= 3.0.
+
+2021-03-26: olly
+ [PHP] Add PHP keywords 'fn' (added in 7.4) and 'match' (added in
+ 8.0) to the list SWIG knows to automatically rename.
+
+2021-03-23: wsfulton
+ #1942 [Python] Fix compilation error in wrappers when using -builtin
+ and wrapping varargs in constructors.
+
+2021-03-22: goto40
+ #1977 Fix handling of template template parameters.
+
+2021-03-21: olly
+ #1929, #1978 [PHP] Add support for PHP 8.
+
+2021-03-19: wsfulton
+ #1610 Remove -ansi from default compilation flags.
+
+2021-03-19: dot-asm
+ #1934 [Java] Clean up typemaps for long long arrays.
+
+2021-03-19: olly
+ #1527 [PHP] Improve PHP object creation in directorin case.
+ Reportedly the code we were using in this case gave segfaults in
+ PHP 7.2 and later - we've been unable to reproduce these, but the
+ new approach is also simpler and should be bit faster too.
+
+2021-03-18: olly
+ #1655 [PHP] Fix char* typecheck typemap to accept PHP Null like the
+ corresponding in typemap does.
+
+2021-03-18: olly
+ #1900, #1905 [PHP] Fix wrapping of overloaded directed methods with
+ non-void return.
+
+2021-03-11: murillo128
+ #1498 [Javascript] Support type conversion.
+
+2021-03-06: nshmyrev
+ #872 [Javascript] Various typemap issues in arrays_javascript.i fixed.
+
+2021-03-03: vaughamhong
+ #577 [Javascript] Implemented SetModule/GetModule for JSC to allow type sharing
+ across modules.
+
+2021-03-01: xantares, Oliver Buchtala, geographika
+ #1040 Add support for building SWIG with CMake. See documentation in Windows.html.
+
+2021-03-01: vadz
+ #1952 Fix incorrect warning "Unknown Doxygen command: ."
+
+2021-02-28: p2k
+ #969 [Javascript] v8/node - prevent crash calling a constructor without new keyword.
+
+2021-02-28: alecmev
+ #405 #1121 [Javascript] Fix OUTPUT typemaps on methods that don't return void.
+ The output value is appended to the return value.
+
+2021-02-26: murillo128, wsfulton
+ #1269 [Javascript] Fix handling of large positive unsigned long and
+ unsigned long long values.
+
+2021-02-24: tomleavy, yegorich, tungntpham
+ #1746 [Javascript] Add support for Node v12, v14 and v16.
+ SWIG support for Node is now for v6 and later only.
+
+2020-02-09: ZackerySpytz
+ #1872 Fix typos in attribute2ref macros.
+
+2020-10-10: wsfulton
+ [Javascript] Fix so that ccomplex.i interface to file can be used.
+
+2020-10-10: wsfulton
+ #252 complex can now be used as a C identifier and doesn't give a syntax error.
+
+2020-10-10: lpsinger
+ #1770 Correct C complex support.
+ _Complex is now parsed as a keyword rather than complex as per the C99 standard.
+ The complex macro is available in the ccomplex.i library file along with other
+ complex number handling provided by the complex.h header.
+
+2020-10-07: ZackerySpytz
+ [Python] #1812 Fix the error handling for the PyObject_GetBuffer() calls in
+ pybuffer.i.
+
+2020-10-07: treitmayr
+ #1824 Add missing space in director method declaration returning
+ const pointer.
+
+2020-10-07: adelva1984
+ #1859 Remove all (two) exceptions from SWIG executable.
+
+2020-09-25: wsfulton
+ [C#, Java] #1874 Add ability to change the modifiers for the interface
+ generated when using the %interface macros.
+
+ For C# use the 'csinterfacemodifiers' typemap.
+ For Java use the 'javainterfacemodifiers' typemap.
+
+ For example:
+
+ %typemap(csinterfacemodifiers) X "internal interface"
+
+2020-09-24: geefr
+ [C#] #1868 Fix wchar_t* csvarout typemap for member variable wrappers.
+
+2020-08-28: wsfulton
+ [Java] #1862 Fix crashes in swig_connect_director during director class construction
+ when using the director class from multiple threads - a race condition initialising
+ block scope static variables. The fix is guaranteed when using C++11, but most
+ compilers also fix it when using C++03/C++98.
+
+2020-08-16: wsfulton
+ [Python] Add missing initializer for member '_heaptypeobject::ht_module' when using
+ -builtin to complete Python 3.9 support.
+
+2020-08-16: wsfulton
+ [Python] Remove PyEval_InitThreads() call for Python 3.7 and later as Python calls
+ it automatically now. This removes a deprecation warning when using Python 3.9.
+
+2020-08-15: wsfulton
+ [Python] All Python examples and tests are written to be Python 2 and Python 3
+ compatible, removing the need for 2to3 to run the examples or test-suite.
+
+2020-08-13: wsfulton
+ [C#] Add support for void *VOID_INT_PTR for member variables.
+
+2020-07-29: chrisburr
+ #1843 [Python] Compilation error fix in SwigPyBuiltin_SetMetaType when using PyPy.
+
+2020-06-14: ZackerySpytz
+ #1642 #1809 Fix virtual comparison operators in director classes by removing an
+ incorrect space in the function name (for example, operator= = is now operator==).
+
+Version 4.0.2 (8 Jun 2020)
+==========================
+
+2020-06-07 vigsterkr
+ [Ruby] #1717 Nil fix mangling strings
+
+2020-06-07 vadz
+ #1748 Fix doxygen comments quoting issue
+
+2020-06-07 munoah
+ #1800 Escape spaces in file paths for dependencies (-M -MM etc)
+
+2020-06-06 andreas-schwab
+ [Ruby] #1801 Fix encoding on big endian systems when wrapping std::wstring.
+
+2020-05-31 kwwette
+ [Octave] #1789 error handling improvements and return error code on exit for SWIG wrapped modules.
+
+2020-05-30 msteinbeck
+ [D] #1593 Replace broken imports when using newer versions of D.
+
+2020-05-29: ZackerySpytz
+ [Python] #1716 Performance improvements when converting strings when using Python >= 3.3.
+
+2020-05-28: ZackerySpytz
+ #1776 Quite dramatically decrease run times when generating very large interface files by changing
+ some internal memory pool sizes.
+
+2020-05-28: mcfarljm
+ #1788 Fix handling of Doxygen \endlink command.
+
+2020-05-24: vapier
+ [Javascript] #1796 Fix pkg-config invocation in configure.
+
+2020-04-30: kwwette
+ [Octave] Fix exception raising for newer Octave versions
+ Since (at least) Octave 5.1.0, the Octave error() function now raises a C++ exception,
+ which if uncaught immediately exits a SWIG wrapper function, bypassing any cleanup code
+ that may appear after a "fail:" label. This patch adds a "try { ... } catch(...) { }"
+ block around the contents of SWIG wrapper functions to first execute the cleanup code
+ before rethrowing any exception raised. It is backward compatible with earlier versions
+ of Octave where error() does not raise an exception, which will still branch to the
+ "fail:" block to execute cleanup code if an error is encountered.
+
+ Note that the new "try { ... } catch(...) { }" block will localise any local variables
+ used in typemaps that were NOT declared through SWIG's %typemap(...) syntax, so it's
+ possible this could break existing SWIG wrappers which were implicitly sharing local
+ variables between typemaps. This can be fixed, however, by declaring local variables
+ which need to be shared between typemaps through SWIG's %typemap(...) syntax.
+
+2020-02-18: ryannevell
+ [Lua] #1728 Add support for LUA lightuserdata to SWIG_Lua_ConvertPtr.
+
+2020-02-18: dmach
+ [Ruby] #1725 Fix gcc -Wcatch-value warnings.
+
+2020-02-14: treitmayr
+ #1724 Fix wrapping of abstract user-defined conversion operators.
+
+2020-02-13: ddurham2
+ [Python] #1512 Fix memleak when using STL containers of shared_ptr objects.
+
+2020-02-06: wsfulton
+ [Python] #1673 #1674 Fix setting 'this' when extending a proxy class with __slots__.
+
+2020-01-31: vadz
+ [Ruby] #1651 Add std::auto_ptr<> typemaps.
+
+2020-01-31: ZackerySpytz
+ [Python] #1700 The Python C API functions PyBytes_AsStringAndSize() and
+ PyString_AsStringAndSize() are now checked for failure.
+
+2020-01-31: vadz
+ [Python] #1710 Fix crash parsing empty docstrings.
+
+2020-01-30: Alzathar
+ [R] #910 #914 Fix R memory leak on exception.
+
+2020-01-30: richardbeare
+ [R] #1511 Fix bug wrapping functions. These were previously incorrectly wrapped as if
+ they were variables. This happened when 'get' or 'set' was in the name of the function
+ or method, but sometimes also in some other circumstances. If you were using R
+ attribute syntax to access these methods, you'll need to switch to calling them as R
+ methods.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2020-01-24: etse-dignitas, wsfulton
+ [C#, D, Java] #1533 Fix upcasting for shared_ptr's of templated types.
+
+2020-01-16: mcfarljm
+ #1643 #1654 When using -doxygen, fix segfault when nameless parameters or vararg parameters
+ are used.
+
+2020-01-16: mcfarljm
+ #1632 #1659 Fix newline handling for doxygen "///" comments.
+
+2020-01-14: mcfarljm
+ #1647 #1656 Fix crash handling empty doxygen comments.
+
+2020-01-14: mcfarljm
+ #1608 Improve doxygen support.
+ - Add support for \param[] commands such as: \param[in].
+ - Optional arguments are marked as 'optional' in pydoc.
+ - Improve support for \code commands so that other languages are supported as code blocks.
+ Support added for java, c and py. For example Python: \code{.py} ... \endcode
+ - Fix doxygen handling of \em and \p tags for Python.
+
+2020-01-13: wsfulton
+ [Python] #1595 Python -builtin constructors silently ignored keyword arguments.
+ Instead of silently ignoring them, now a "TypeError: f() takes no keyword arguments"
+ exception is thrown if keyword arguments are used. Hence constructors and normal methods/
+ functions behave in the same way. Note, -keyword should be used with -builtin to obtain
+ keyword argument support.
+
+2020-01-05: jschueller shadchin
+ [Python] #1670 #1696 Add missing field initializers introduced in python 3.8:
+ tp_vectorcall and tp_print.
+
+2020-01-05: friedrichatgc
+ [Octave] #1688 Change swig_this() to use size_t instead of long for compatibility
+ with Windows 64 bit.
+
+2020-01-05: treitmayr
+ [Ruby] #1692 #1689 Add support for Ruby 2.7
+
+2019-12-30: treitmayr
+ [Ruby] #1653 #1668 Fix code generated when using -globalmodule option.
+
+2019-12-29: ZackerySpytz
+ [OCaml] #1686 Fix compilation errors with OCaml 4.09.0.
+
+2019-12-10: wsfulton
+ #1679 Fix parsing of C++11 identifiers with special meaning (final and override) when
+ they are used as part of the scope name of an identifier, such as a namespace name.
+
+2019-11-26: wsfulton
+ [C#] #1628 'out' or 'ref' used in a cstype typemap was not always stripped out in parts
+ of director code generation.
+
+2019-11-01: wsfulton
+ [Python] #1595 Fix bug in support for keyword arguments (kwargs feature or -keyword)
+ when using -builtin. The fix is in the argument error checking when wrapping zero
+ argument constructors only.
+
+Version 4.0.1 (21 Aug 2019)
+===========================
+
+2019-08-20: TekuConcept
+ [Javascript] #1535 Add %native support to Javascript.
+
+2019-08-20: bkotzz
+ [Java] #1616 Add SWIG_JavaIllegalStateException to support throwing
+ java.lang.IllegalStateException from JNI code.
+
+2019-08-19: sjml
+ [Lua] #1596 tostring output changes to show the underlying C/C++ pointer.
+
+2019-08-08: rokups
+ [C#, Java] #1601 Fix invalid code generated for "%constant enum EnumType.
+
+2019-08-07: wsfulton
+ [Python] Fix method overloading of methods that take STL containers of different
+ types. The following usage (using std::vector) would fail when using -builtin:
+
+ %include <std_string.i>
+ %include <std_vector.i>
+
+ %inline %{
+ struct X {};
+ %}
+
+ %template(VectorX) std::vector<X>;
+ %template(VectorInt) std::vector<int>;
+
+ %inline %{
+ using namespace std;
+ string VectorOverload(vector<X> v);
+ string VectorOverload(vector<int> v);
+ %}
+
+ The following would incorrectly fail:
+
+ s = VectorOverload([1, 2, 3])
+
+ With:
+
+ Traceback (most recent call last):
+ File "runme3.py", line 20, in <module>
+ ret = VectorOverload([1, 2, 3])
+ TypeError: Wrong number or type of arguments for overloaded function 'VectorOverload'.
+ Possible C/C++ prototypes are:
+ VectorOverload(std::vector< Number,std::allocator< Number > >)
+ VectorOverload(std::vector< int,std::allocator< int > >)
+
+ The problem was due to some error handling that was not cleared during typechecking.
+ In this case an error was not cleared when the elements in the list failed the
+ typecheck for converting to X. Only occurs in Python 3+.
+
+ In some combinations of overloaded methods, the following type of error message would
+ occur:
+
+ RuntimeError: in sequence element 0
+
+ The above exception was the direct cause of the following exception:
+
+ Traceback (most recent call last):
+ File "runme3.py", line 23, in <module>
+ check(VectorOverload(v), "vector<X>")
+ SystemError: <built-in function VectorOverload> returned a result with an error set
+
+2019-08-01: wsfulton
+ #1602 Fix regression in 4.0.0 where a template function containing a parameter
+ with the same name as the function name led to the parameter name used in the
+ target language being incorrectly modified.
+
+2019-07-29: wsfulton
+ Remove all generated files on error. Previously generated files were not removed,
+ potentially breaking Makefiles using file dependencies, especially when -Werror
+ (warnings as errors) was used.
+
+2019-07-23: smithx
+ [C#] #1530 #1532 Fix marshalling of std::wstring to C#.
+
+2019-07-18: gicmo
+ [Python] #1587 Python 3.8 support - remove use of deprecated PyObject_GC_UnTrack.
+
+2019-07-18: cher-nov
+ [Python] #1573 Generated Python code uses consistent string quoting style - double
+ quotes.
+
+2019-07-16: geefr
+ [C#] #616 #1576 Fix C# bool INPUT[], bool OUTPUT[], bool INOUT[] typemaps to marshall
+ as 1-byte.
+
+2019-07-12: vadz
+ [C#, Java] #1568 #1583 Fix std::set<> typemaps for primitive types.
+
+2019-07-12: vadz
+ #1566 #1584 Regression in 4.0.0 - fix missing value for first item of enums with
+ trailing comma.
+
+2019-07-11: mcfarljm
+ #1548 #1578 Fix segfault in Doxygen parser parsing empty lines in some commands like
+ \code.
+
+2019-07-09: IsaacPascual
+ [C#, Java] #1570 Fix name of generated C#/Java classes for %interface macros
+ in swiginterface.i when wrapping nested C++ classes.
+
+2019-07-05: wsfulton
+ [Python] #1547 Whitespace fixes in Doxygen translated comments into pydoc comments
+ for Sphinx compatibility.
+
+2019-06-28: wsfulton
+ [MzScheme, OCaml] #1559 $arg and $input were incorrectly substituted in the
+ argout typemap when two or more arguments were present.
+
+2019-06-24: wsfulton
+ [Python, Ruby] #1538 Remove the UnknownExceptionHandler class in order to be
+ C++17 compliant as it uses std::unexpected_handler which was removed in C++17.
+ This class was intended for director exception handling but was never used by
+ SWIG and was never documented.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2019-06-06: bkotzz
+ [Java] #1552 Improve performance in Java std::vector constructor wrapper that takes
+ a native Java array as input.
+
+2019-06-03: olly
+ [Python] Fix regression in implicit_conv handling of tuples,
+ introduced in SWIG 4.0.0. Fixes #1553, reported by Alexandre
+ Duret-Lutz.
+
+2019-05-24: wsfulton
+ [Octave] Fix detection of Octave on MacOS.
+
+2019-05-24: opoplawski
+ [Octave] #1522 Adapt OCTAVE_LDFLAGS for Octave 5.1.
+
+2019-05-22: ferdynator
+ [PHP] #1528 Don't add a closing '?>' PHP tag to generated files.
+ PSR-2 says it MUST be omitted for files containing only PHP.
+
+Version 4.0.0 (27 Apr 2019)
+===========================
+
+2019-04-24: vadz
+ #1517 Fix crash if "@return" Doxygen tag was used on a node without any return type.
+
+2019-04-24: vadz
+ #1515 Fix parsing of enums with trailing comma when using -doxygen.
+
+2019-04-19: ianlancetaylor
+ [Go] #1055 When generating Go code, make -cgo the default. Add new -no-cgo option
+ to disable the default.
+
+2019-04-19: pbecherer
+ [Tcl] #1508 Fix Visual Studio 2015 and later compilation errors due to snprintf macro
+ definition.
+
+2019-04-09: wsfulton
+ [C#] Fix FxCop warning CA2002 in SWIGPendingException - a lock on a reference of
+ type 'Type'.
+
+2019-03-30: wsfulton
+ [Java, D] Add the parameters typemap attribute to the javadestruct,
+ javadestruct_derived, ddispose, ddispose_derived typemaps to mirror enhanced
+ flexibility in the csdisposing and csdisposing_derived (C#) typemaps. If provided
+ the contents are generated as the delete/dispose method's parameters declaration.
+
+2019-03-30: wsfulton
+ [C#] #421 Fix FxCop warning CA1063 by implementing the recommended Dispose methods for
+ the IDisposable interface. Previously just the Dispose() method was generated.
+ Now the Dispose() and Dispose(bool disposing) methods are generated.
+ Changes are required if custom "csfinalize", "csdestruct" or "csdestruct_derived"
+ typemaps are being used. Details in #421 on Github. SWIG will error out if one of
+ the "csfinalize, "csdestruct" or "csdestruct_derived" typemaps are found. Example
+ error message:
+
+ foo.h:60: Error: A deprecated csfinalize typemap was found for Foo, please remove
+ it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the
+ csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2019-03-25: Liryna
+ [C#] #1143 Add std_list.i for std::list support.
+ The C# std::list<T> wrappers are made to look and feel like a C#
+ System.Collections.Generic.LinkedList<> collection.
+ The IEnumerable<> interface is implemented in the proxy class.
+ The ICollection<> interface can also be implemented to provide enhanced functionality
+ whenever a C++ operator== is available. This is the case for when T is a
+ primitive type or a pointer. If T does define an operator==, then use the
+ SWIG_STD_LIST_ENHANCED macro to obtain this enhanced functionality, for example:
+
+ SWIG_STD_LIST_ENHANCED(SomeNamespace::Klass)
+ %template(ListKlass) std::list<SomeNamespace::Klass>;
+
+2019-03-18: richardbeare
+ [R] #1328 Non-trivial enums are working now. The enum values are now obtained from
+ the C/C++ layer. const reference enums and C++11 enum classes are also now working.
+
+2019-03-14: mochizk
+ [Javascript] #1500 Fix compilation errors due to deprecating V8 API in Node.js.
+ New V8 API is used if node.js >= v10.12, or if V8 >= v7.0.
+
+2019-03-12: vadz
+ [C#] #1495 Add std_set.i for std::set support.
+
+2019-03-11: dirteat,opoplawski
+ [Octave] Fix compilation errors in Octave 5.1.
+
+ error: format not a string literal and no format arguments [-Werror=format-security]
+
+2019-02-28: wsfulton
+ [Java] std::vector improvements for types that do not have a default constructor.
+
+ The std::vector wrappers have been changed to work by default for elements that are
+ not default insertable, i.e. have no default constructor. This has been achieved by
+ not wrapping:
+
+ vector(size_type n);
+
+ Previously the above had to be ignored via %ignore.
+
+ If the above constructor is still required it can be added back in again via %extend:
+
+ %extend std::vector {
+ vector(size_type count) { return new std::vector< T >(count); }
+ }
+
+ Alternatively, the following wrapped constructor could be used as it provides near-enough
+ equivalent functionality:
+
+ vector(jint count, const value_type& value);
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2019-02-25: wsfulton
+ [Python] Fix compile errors wrapping overloaded functions/constructors where a vararg
+ function is declared after a non-vararg function.
+
+2019-02-23: zphensley42
+ Use fully qualified name 'java.lang.Object' instead of 'Object' in generated code to
+ avoid clashes with wrapped C++ classes called 'Object'.
+
+2019-02-23: gtbX
+ [Java] #1035 Add (const char *STRING, size_t LENGTH) typemaps in addition to the non-const
+ typemaps (char *STRING, size_t LENGTH) which does not attempt to write back to the const
+ string.
+
+2019-02-22: tamuratak
+ [Ruby] #984 Add support for RTypedData introduced in Ruby 1.9.3.
+
+2019-02-22: ZackerySpytz
+ #1483 Fix compilation failures when a director class has final methods.
+
+2019-02-21: wsfulton
+ [Java] #1240 Suppress Java 9 deprecation warnings on finalize method.
+
+2019-02-21: ZackerySpytz
+ #1480 Fix some rejections of valid floating-point literals.
+
+2019-02-19: wsfulton
+ #1475 Fix regression parsing gcc preprocessor linemarkers in the form:
+
+ # linenum filename flags
+
+2019-02-18: jakecobb
+ [Python] #945 #1234 Elements in std::vector memory access fix.
+
+ Accessing an element in a std::vector obtains a reference to the element via an
+ iterator pointing to the element in the container. If the vector is garbage collected,
+ the SWIG wrapper containing the pointer to the element becomes invalid. The fix is
+ to obtain a back-reference to the container by the wrapper to the element in the Python
+ layer to prevent the garbage collector from destroying the underlying container.
+
+2019-02-17: wsfulton
+ Fix typemap matching to expand template parameters when the name contains
+ template parameters. In the %typemap below the type is T and the name is X<T>::make
+ and the name now expands correctly to X< int >::make
+
+ template<typename T> struct X {
+ %typemap(out) T X<T>::make "..."
+ T make();
+ };
+
+ %template(Xint) X<int>;
+
+2019-02-16: wsfulton
+ Fix parser error containing multiple #define statements inside an enum.
+
+ The second #define fails to parse:
+
+ enum FooEnum {
+ ENUM1 = 0,
+ ENUM2 = 1,
+
+ #define MACRO_DEF1 "Hello"
+ #define MACRO_DEF2 "World!"
+
+ ENUM3 = 2,
+ ENUM4 = 3,
+ };
+
+ Bug mentioned at https://sourceforge.net/p/swig/patches/333/
+
+2019-02-14: wsfulton
+ Add some missing copy constructors into STL containers.
+
+2019-02-14: bkotzz
+ [Java] #1356 Add STL containers:
+ std::unordered_map
+ std::unordered_set
+ std::set
+
+2019-02-14: bkotzz
+ [Java] #1356 std::map wrappers have been modified. Now the Java proxy class
+ extends java.util.AbstractMap. The std::map container looks and feels much like
+ a java.util.HashMap from Java.
+
+ A few members have changed their names. If the old method signatures are needed,
+ then copy std_map.i from swig-3.0.12 and use that instead. Alternatively,
+ add the old missing methods to the new methods by using the following %proxycode:
+
+ %extend std::map {
+ %proxycode %{
+ // Old API
+ public boolean empty() {
+ return isEmpty();
+ }
+ public void set($typemap(jboxtype, K) key, $typemap(jboxtype, T) x) {
+ put(key, x);
+ }
+ public void del($typemap(jboxtype, K) key) {
+ remove(key);
+ }
+ public boolean has_key($typemap(jboxtype, K) key) {
+ return containsKey(key);
+ }
+ %}
+ }
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2019-02-13: ZackerySpytz
+ #1469 Add support for C++17 hexadecimal floating literals.
+
+2019-02-11: wsfulton
+ [OCaml] #1437 OCaml has been give the 'Experimental' language status. The examples work
+ and most of the test-suite is also working, so it is quite close to being a 'Supported' language.
+
+2019-02-10: ZackerySpytz
+ #1464 Add support for C++14 binary integer literals.
+
+2019-02-10: ZackerySpytz
+ #1450 Add support for C++11 UCS-2 and UCS-4 character literals. Also, add support for
+ C++17 UTF-8 character literals.
+
+2019-02-10: wsfulton
+ [MzScheme] #1437 MzScheme/Racket is now an 'Experimental' language. The examples work
+ and a large portion of the test-suite is also working.
+
+2019-02-10: wsfulton
+ [MzScheme] Destructor wrappers were not being generated.
+
+2019-02-10: wsfulton
+ [MzScheme] Static variable wrappers fixed - $argnum was not expanded.
+
+2019-02-10: sethrj
+ #1452 Fix %apply for anonymous template instantiations
+
+2019-02-09: olly
+ [PHP] Fix access to already released memory during PHP module
+ shutdown, which often didn't cause visible problems, but could
+ result in segmentation faults, bus errors, etc. Fixes #1170,
+ reported by Jitka Plesn�kov�.
+
+2019-02-09: olly
+ [PHP] A renamed constructor is now wrapped as a static method in
+ PHP.
+
+2019-02-08: olly
+ [PHP] Don't generate code which references $r when $r hasn't been
+ defined. This could happen in overloaded methods which returned
+ void and took at least one const std::string& parameter.
+
+2019-02-08: olly
+ [PHP] The generated code is now compatible with PHP 7.3, and the
+ testsuite now runs cleanly with this version too.
+
+2019-02-05: wsfulton
+ #1437 SWIG now classifies the status of target languages into either 'Experimental' or
+ 'Supported'. This status is provided to indicate the level of maturity to expect when using
+ a particular target language as not all target languages are fully developed. Details are
+ in the Introduction.html chapter of the documentation.
+
+2019-02-04: wsfulton
+ [CFFI] #1447 Common Lisp CFFI has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [Allegrocl] #1447 Allegro Common Lisp has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [Chicken] #1447 CHICKEN has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [CLISP] #1447 GNU Common Lisp has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [S-EXP] #1447 Common Lisp S-Exp has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [UFFI] #1447 Common Lisp UFFI has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [Pike] #1447 Pike has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-04: wsfulton
+ [Modula3] #1447 Modula3 has been disabled as a target language in SWIG as part of a
+ clean up to remove target languages that have been neglected/not functional.
+
+2019-02-02: ahnolds
+ [Python] Documentation enhancements for Python:
+
+ #728 Fixed the handling of autodoc when using -fastproxy.
+
+ #1367 Added documentation to wrapped member variables using the
+ property(... doc="...") construct.
+
+ Only show a single documentation entry for functions with default arguments when
+ using autodoc.
+
+ Fixed a bug where a cached doxygen docstring could be deleted while still in use,
+ causing swig to segfault.
+
+2019-01-31: olly
+ SWIG now requires a target language to be specified instead of
+ defaulting to wrapping for Tcl. Specifying swig --help without
+ a target language now just shows the generic help. The -nolang
+ option has been removed.
+
+2019-01-28: ZackerySpytz
+ [OCaml] #1429 Remove support for OCaml versions < 3.12.0.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2019-01-22: vadz
+ [Ruby, Octave] #1424 Improve autodoc parameter naming.
+
+2019-01-22: vadz
+ [Python] #1271 #1423 Always include default parameter values in autodoc strings.
+
+2019-01-19: vadz
+ #1272, #1421 When a function's parameter is a keyword, the name of the paramater is
+ no longer simply changed to argN, where N is the argument number. Instead the
+ parameter name is changed to the renaming rules for keywords that normally apply to
+ symbols such as classes/functions etc. Note that unlike other symbol renaming,
+ parameter renaming does not issue a warning when the parameter is renamed. This
+ change only affects languages where the parameter names are actually used, for example,
+ Java function parameter lists in the proxy class or Python documentation comments.
+
+2019-01-18: wsfulton
+ #1420 Fix gdb debugger functions 'swigprint' and 'locswigprint' from swig.gdb to
+ work with newer versions of gdb-8. Fixes errors when debugging SWIG source with gdb:
+
+ (gdb) swigprint n
+ Undefined command: "Printf". Try "help".
+
+2019-01-16: wsfulton
+ Python static method wrapper changes
+
+ - Static method wrappers were using the 'fastproxy' approach by default.
+ This is inconsistent with instance method wrappers. The fastproxy approach
+ is now turned off by default to be consistent with instance methods.
+ Static method wrappers can now also be controlled using the -fastproxy and
+ -olddefs options.
+
+ Example:
+
+ struct Klass {
+ static int statmethod(int a = 2);
+ };
+
+ generates by default:
+
+ class Klass(object):
+ ...
+ @staticmethod
+ def statmethod(a=2):
+ return _example.Klass_statmethod(a)
+
+ instead of the following (which can be restored by using -fastproxy):
+
+ class Klass(object):
+ ...
+ statmethod = staticmethod(_example.Klass_statmethod)
+
+ - Modernise wrappers for static methods to use decorator syntax - @staticmethod.
+
+ - Add missing runtime test for static class methods and using the actual class method.
+
+2019-01-12: ZackerySpytz
+ [OCaml] #1403 #1194 Fix compilation problems for OCaml >= 4.03.0 due to OCaml using
+ int64_t instead of int64.
+
+2019-01-11: ZackerySpytz
+ [OCaml] #1400 Fix the getters and setters of non-static member variables.
+
+2019-01-07: wsfulton
+ #358 Add VOID to windows.i
+
+2019-01-05: wsfulton
+ #948 #1019 #1273 Fix for C++11 raw strings where the delimiters were mistakenly left
+ in the string contents in situations where the string was copied into generated code.
+ For example, %constant, the "docstring" feature and for C#/Java/D constants turned on
+ with %javaconst/%csconst/%dmanifestconst.
+
+2019-01-05: wsfulton
+ [Ruby] #538. Fix Ruby support for %feature("docstring").
+
+2019-01-03: wsfulton
+ #1202 Fix overloading of non-pointer class types in scripting languages when overloaded
+ with a pointer and a NULL scripting language equivalent is used, eg None in Python.
+
+ The implementation changes the SWIGTYPE, SWIGTYPE& and SWIGTYPE&& typecheck typemaps to
+ prevent accepting a conversion to a NULL pointer.
+
+2019-01-03: ZackerySpytz
+ [OCaml] #1386 Fix the OCaml examples and test suite for out-of-source builds.
+
+2019-01-01: wsfulton
+ [Python] #639 remove duplicate proxy method definitions for global function wrappers.
+
+ Global functions previously generated two definitions, eg:
+
+ def foo():
+ return _example.foo()
+ foo = _example.foo
+
+ The first definition is replaced by the second definition and so the second definition
+ is the one used when the method is actually called. Now just the first definition is
+ generated by default and if the -fastproxy command line option is used, just the second
+ definition is generated. The second definition is faster as it avoids the proxy Python
+ method as it calls the low-level C wrapper directly. Using both -fastproxy and -olddefs
+ command line options will restore the previously generated code as it will generate both
+ method definitions.
+
+ With this change, the wrappers for global C/C++ functions and C++ class methods now work
+ in the same way wrt to generating just a proxy method by default and control via
+ -fastproxy/-olddefs options.
+
+2018-12-20: hasinoff,wsfulton
+ [Java] #1334 Set Java thread name to native thread name when using directors.
+
+ Default is to use name "Thread-XXX" and is still works like this by default. However,
+ adding the following will turn on the thread name setting (works for more recent
+ versions of Linux and MacOS):
+
+ %begin %{
+ #define SWIG_JAVA_USE_THREAD_NAME
+ %}
+
+2018-12-20: chlandsi
+ [Python] #1357. Fix overriding __new__ in Python 3.6.
+
+ Fixes SystemError: Objects/tupleobject.c:81: bad argument to internal function"
+
+2018-12-16: wsfulton
+ [Python] #848 #1343 The module import logic has changed to stop obfuscating real ImportError
+ problems. Only one import of the low-level C/C++ module from the pure Python module is
+ attempted now. Previously a second import of the low-level C/C++ module was attempted
+ after an ImportError occurred and was done to support 'split modules'. A 'split module' is
+ a configuration where the pure Python module is a module within a Python package and the
+ low-level C/C++ module is a global Python module. Now a 'split module' configuration is
+ no longer supported by default. This configuration can be supported with a simple
+ customization, such as:
+
+ %module(package="mypackage", moduleimport="import $module") foo
+
+ or if using -builtin:
+
+ %module(package="mypackage", moduleimport="from $module import *") foo
+
+ instead of
+
+ %module(package="mypackage") foo
+
+ See the updated Python chapter titled "Location of modules" in the documentation.
+
+2018-12-11: tlby
+ [Perl] #1374 repair EXTEND() handling in typemaps
+
+2018-12-06: vadz
+ #1359 #1364 Add missing nested class destructor wrapper when the nested class is
+ inside a template. Removes associated bogus 'Illegal destructor name' warning. Only
+ occurred when the nested class' destructor is explicitly specified.
+
+2018-12-04: adr26
+ [Python] #1368 #1369 Access Violation in tp_print caused by mismatched Python/extension
+ CRT usage
+
+ Remove all use of tp_print, as this API uses a FILE*, which can be
+ mismatched when modules are built with different C libraries from
+ the main python executable.
+
+ This change also brings consistent output between Python 2 and 3 for the 'cvar' SWIG
+ object (that contains the global variables) and SWIG packed objects (such as callback
+ constants).
+
+2018-12-04: wsfulton
+ [Python] #1282 Fix running 'python -m' when using 'swig -builtin'
+
+ Similar to the earlier PEP 366 conforming fix for non-builtin.
+
+2018-11-29: adr26
+ [Python] #1360 Leak of SWIG var link object
+
+ Fix reference counting on _SWIG_globals to allow var link to be freed on module unload.
+
+2018-11-28: wsfulton
+ [Python] When using -builtin, the two step C-extension module import is now
+ one step and the wrapped API is only available once and not in an underlying
+ module attribute like it is without -builtin. To understand this, consider a
+ module named 'example' (using: %module example). The C-extension is compiled into
+ a Python module called '_example' and a pure Python module provides the actual
+ API from the module called 'example'. It was previously possible to additionally
+ access the API from the module attribute 'example._example'. The latter was an
+ implementation detail and is no longer available. It shouldn't have been used, but
+ if necessary it can be resurrected using the moduleimport attribute described in the
+ Python chapter of the documentation. If both modules are provided in a Python
+ package, try:
+
+ %module(moduleimport="from . import _example\nfrom ._example import *") example
+ or more generically:
+ %module(moduleimport="from . import $module\nfrom .$module import *") example
+
+ and if both are provided as global modules, try:
+
+ %module(moduleimport="import _example\nfrom _example import *") example
+ or more generically:
+ %module(moduleimport="import $module\nfrom $module import *") example
+
+ The module import code shown will appear in the example.py file.
+
+2018-11-24: vadz
+ #1358 Fix handling of abstract base classes nested inside templates
+
+ Correct detecting of whether a derived class method overrides a pure virtual
+ base class method when both classes are nested inside a template class: this
+ notably didn't work correctly for methods taking parameters of the base class
+ type.
+
+2018-11-22: rupertnash
+ [Python] #1282 Make generated module runnable via python -m (PEP 366 conforming)
+
+ Previously any SWIG generated modules in a package would fail with an ImportError
+ when using 'python -m' for example 'python -m mypkg.mymodule'.
+
+ This fix also allows the SWIG generated module to be placed into a directory and
+ then renamed __init__.py to convert the module into a package again. This ability
+ stopped working in swig-3.0.9. However, only Python 2.7 or 3.3 and later work. If
+ Python 3.2 support is needed, use moduleimport in %module to customise the import
+ code.
+
+2018-11-13: wsfulton
+ #1340 Remove -cppcast and -nocppcast command line options (this was an option
+ available to the scripting language targets).
+
+ The -cppcast option is still turned on by default. The -nocppcast option
+ to turn off the use of c++ casts (const_cast, static_cast etc) has been
+ removed. However, defining SWIG_NO_CPLUSPLUS_CAST will still generate C casts
+ instead of C++ casts for C++ wrappers.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-11-13: wsfulton
+ [Python] #1340 Remove -outputtuple and -nooutputtuple command line options.
+
+ Both the command line and %module options of the same name have been
+ removed. These were undocumented. The -outputtuple option returned a
+ Python tuple instead of a list, mostly typically in the OUTPUT
+ typemap implementations.
+
+ It unclear why a tuple instead of a list return type is needed and
+ hence this option has been removed as part of the simplification of
+ the SWIG Python command line options for SWIG 4.
+
+2018-11-13: wsfulton
+ [Python] #1340 Remove -noproxyimport command line option.
+
+ This option turned off the insertion of Python import statements
+ derived from a %import directive. For example given:
+
+ %module module_b
+ %import "module_a.i"
+
+ then module_b.py will contain:
+
+ import module_a
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-10-29: AlexanderGabriel
+ [PHP] The following PHP7 reserved keywords are now only renamed by
+ SWIG when used as function names in the API being wrapper:
+ __halt_compiler array die echo empty eval exit include include_once
+ isset list print require require_once return unset
+
+2018-10-22: olly,wsfulton
+ [Python] #1261 #1340 Turn on many optimisation options by default and rationalise the
+ number of command line options.
+
+ There were an unnecessary number of command line options and many of these have now
+ been removed in a drive for simplification. Some were needed to support older versions
+ of Python (2.6 and earlier).
+
+ Many of the options could be turned on individually and when using -O. Previously -O
+ resulted in turning on a set of options:
+
+ -modern -fastdispatch -nosafecstrings -fvirtual -noproxydel
+ -fastproxy -fastinit -fastunpack -fastquery -modernargs -nobuildnone
+
+ Now -O results in turning on this reduced set:
+
+ -fastdispatch -fastproxy -fvirtual
+
+ The following options are now on by default, a deprecated warning is displayed if they
+ are used:
+ -fastinit Class initialisation code done in C/C++ rather than in Python code.
+ -fastquery Python dictionary used for lookup of types.
+ -fastunpack Faster unpacking of function arguments in C/C++ wrappers.
+ -modern Use Python 2.3 features such as object and property.
+ -modernargs Use Python 2.3 C APIs for unpacking arguments in tuples.
+ -noproxydel Stop generating a proxy __del__ method for backwards compatibility.
+ -safecstrings No discernable difference
+
+ The following options have been removed altogether:
+ -aliasobj0
+ -buildnone
+ -classptr
+ -new_repr
+ -newrepr
+ -noaliasobj0
+ -nobuildnone
+ -nocastmode
+ -nodirvtable
+ -noextranative
+ -nofastinit
+ -nofastproxy
+ -nofastquery
+ -nomodern
+ -nomodernargs
+ -nooutputtuple
+ -nosafecstrings
+ -old_repr
+ -oldrepr
+ -proxydel
+
+ -new_vwm is no longer supported. Use the -newvwm alias instead.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-10-22: olly
+ [Python] #1261 Remove command line option no longer needed as Python 2.3 and earlier
+ are no longer supported:
+
+ -classic
+
+2018-10-09: wsfulton
+ [D, Go, Guile, Lua, Mzscheme, Ocaml, Perl5, Php, Scilab, Tcl]
+ Allow wrapping of std::map using non-default comparison function.
+
+2018-10-09: vadz
+ [Java] #1274 Allow wrapping of std::map using non-default comparison function.
+
+2018-10-04: wsfulton
+ [Python] #1126 Fix C default arguments with -builtin and -fastunpack and -modernargs.
+ Problem occurred when there is just one (defaulted) parameter in the parameter list.
+
+2018-09-24: wsfulton
+ [Python] #1319 C++11 hash tables implementation is finished now (including for -builtin):
+ std::unordered_map
+ std::unordered_set
+ std::unordered_multimap
+ std::unordered_multiset
+
+2018-09-21: wsfulton
+ [Python] Fix when using -builtin and wrapping std::map, std::set, std::unordered_map or
+ std::unordered_set to ensure __contains__ is called. This is a wrapper for the STL
+ container's find method. Without it, Python will do its own slower sequence search.
+
+2018-09-19: wsfulton
+ [Python] Fix functors (wrapped as __call__) when using -builtin -modern -fastunpack.
+
+2018-09-02: andreas.gaeer,tkrasnukha
+ [Python] #1321 Fix assert in PyTuple_GET_SIZE in debug interpreter builds of python-3.7
+ when calling tp_new.
+
+2018-09-01: ChristopherHogan
+ [Guile] #1288 Fix garbage collection for guile >= 2.0.12.
+
+2018-08-31: wsfulton
+ [Python] #1319 C++11 hash tables support:
+ std::unordered_map
+ std::unordered_set
+ std::unordered_multimap
+ std::unordered_multiset
+ is now compiling and working (sorting using -builtin not fully functional yet though).
+
+2018-08-20: wkalinin
+ #1305 Fix nested structure symbol tables in C mode to fix member name conflicts
+ in different structs with the same nested struct member name.
+
+2018-08-18: wsfulton
+ [Python] #688 Fix makefile recursion when running python test-suite.
+
+2018-08-18: wsfulton
+ [Python] #1310 Re-implement Python -fastproxy option.
+
+ The previous implementation failed with Python 3 and abstract base clases.
+ The new implementation replaces the Python 2 implementation using
+ new.instancemethod with the C API PyMethod_New to match the equivalent Python 3
+ implementation which uses PyInstanceMethod_New.
+
+ The new approach runs slightly faster. See #1310.
+
+2018-08-12: gmazzamuto
+ [Python] #1283 Update pybuffer.i library to use new-style Python buffer C API.
+
+2018-08-12: brianhatwood,wsfulton
+ [Java] #1303 #1304 Fix crash in directors when using OUTPUT and INOUT typemaps in typemaps.i and
+ passing NULL pointers in C++ to director method overloaded and implemented in Java.
+
+2018-08-10: wsfulton
+ [Python] #1293 Improve TypeError message inconsistencies between default and fastdispatch
+ mode when handling overloaded C++ functions. Previously the error message did not always
+ display the possible C/C++ prototypes in fastdispatch mode.
+
+2018-08-02: furylynx,jacobwgillespie,p2k
+ [Javascript] #1290, #968. Add support for NodeJS versions 2-10.
+
+2018-07-31: wsfulton
+ [Python] #1293 Overloaded C++ function wrappers now raise a TypeError instead
+ of NotImplementedError when the types passed are incorrect. This change means
+ there is now consistency with non-overloaded function wrappers which have always
+ raised TypeError when the incorrect types are passed. The error message remains
+ the same and is for example now:
+
+ TypeError: Wrong number or type of arguments for overloaded function 'f'.
+ Possible C/C++ prototypes are:
+ f(int)
+ f(char const *)
+
+ instead of:
+
+ NotImplementedError: Wrong number or type of arguments for overloaded function 'f'.
+ Possible C/C++ prototypes are:
+ f(int)
+ f(char const *)
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-06-23: wsfulton
+ [Python] #718 Fix pythonnondynamic feature for modern classes
+
+ Fixes nondynamic mode when an instance variable is set with the same
+ name as a class variable in a class derived from a SWIG proxy class.
+ This corner case set an instance variable instead of raising an AttributeError.
+
+ Also fix %pythonnondynamic in Python 3 with -modern. The metaclass
+ containing the implementation was previously not being applied in Python 3.
+
+2018-07-17: petrmitrichev,wsfulton
+ [Python] #1275 #1279 Initialize function-local statics (singletons) that call Python
+ code during Python module initialization in order to avoid deadlocks with subsequent
+ multi-threaded usage.
+
+2018-06-15: wsfulton
+ [Python] Fix seg fault using Python 2 when passing a Python string, containing
+ invalid utf-8 content, to a wstring or wchar * parameter. A TypeError is thrown instead, eg:
+
+ %include <std_wstring.i>
+ void instring(const std::wstring& s);
+
+ instring(b"h\xe9llooo") # Python
+
+2018-06-15: wsfulton
+ [Python] Python 3.7 support: Replace use of deprecated PyUnicode_GetSize with
+ PyUnicode_GetLength to remove deprecated warnings compiling the C/C++ wrappers.
+
+2018-06-12: wsfulton
+ [Python] Python 3.7 support: The %pythonabc feature in pyabc.i now uses base classes
+ collections.abc.MutableSequence
+ collections.abc.MutableMapping
+ collections.abc.MutableSet
+ instead of
+ collections.MutableSequence
+ collections.MutableMapping
+ collections.MutableSet
+ as the latter are deprecated in Python 3.7 and are due to be removed in Python 3.8.
+ The classes in collections.abc.* are available from Python 3.3 onwards. If you
+ require support for Python 3.2, then copy the pyabc.i file and modify by removing
+ the few instances of the .abc sub-module.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-06-12: olly,wsfulton
+ [Python] #701 Remove support for Python versions < 2.7 and 3.0 and 3.1.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-06-11: olly
+ [Python] Fix new GCC8 warnings in generated code by avoiding casts
+ between incompatible function types where possible, and by
+ suppressing the warning when it's due to the design of Python's C
+ API. Fixes #1259.
+
+2018-06-08: philippkraft
+ [Python] Stop exposing <CLASS>_swigregister to Python. It's not
+ useful for user Python code to call this, and it just clutters the
+ API unnecessarily. Fixes #1225.
+
+2018-06-07: cmfoil, kabbi, Jamie Kirkpatrick, markok314, vadz, wsfulton, Yann Diorcet
+ #170 Doxygen documentation support added. This allows translation of Doxygen comments
+ into JavaDoc and PyDoc documentation. It is enabled via the -doxygen command line
+ option. See the Doxygen.html chapter in the documentation for further information.
+
+2018-06-07: olly
+ [PHP] We've finally removed support for %pragma(php4) which was
+ deprecated back in 2008. Use %pragma(php) instead, which has been
+ supported since at least 2005.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-06-07: olly
+ [PHP5] Support for PHP5 has been removed. PHP5 is no longer
+ actively supported by the PHP developers and security support for
+ it ends completely at the end of 2018, so it doesn't make sense
+ to include support for it in the upcoming SWIG 4.0.0 release.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-06-06: olly
+ [Lua] Improve configure probes for Lua headers and libs used in testsuite.
+
+2018-05-15: kwwette
+ [Octave] add support for version 4.4
+ - Should not introduce any user-visible incompatibilities
+
+2018-05-15: wsfulton
+ [C#, D, Java] Fix lookup of csconstruct, dconstruct and javaconstruct typemaps.
+ The C++ namespace was previously ignored when looking up the typemap.
+
+2018-05-15: wsfulton
+ [Javascript] Fix generated C++ code when using %nspace on namespaces that are more
+ than two levels deep.
+
+2018-05-14: wsfulton
+ Issue #1251 Add support for C++17 nested namespace definitions,
+ for example:
+ namespace A::B { ... }
+
+2018-05-11: wsfulton
+ [C#, D, Java] Add support so that the %csmethodmodifiers, %dmethodmodifiers,
+ %javamethodmodifiers can modify the method modifiers for the destructor wrappers
+ in the proxy class: dispose, Dispose, delete. With this feature, it is now possible
+ to make a C# proxy class sealed, eg when wrapping a class X, the virtual method modifiers
+ can be removed using:
+
+ %typemap(csclassmodifiers) X "public sealed class"
+ %csmethodmodifiers X::~X "public /*virtual*/";
+
+2018-04-18: olly
+ [Python] Suppress new pycodestyle warning:
+ E252 missing whitespace around parameter equals
+
+2018-04-07: goatshriek
+ [Ruby] #1213 Fix ruby %alias directive for global C/C++ functions.
+
+2018-04-03: olly
+ [Ruby] Fix to pass Qnil instead of NULL to rb_funcall(), which silences GCC
+ -Wconversion-null warning (on by default with recent GCC).
+
+2018-03-09: wsfulton
+ [Java] #1184 Fix swigReleaseOwnership() and swigTakeOwnership() regression
+ for non-director classes. Restores a dynamic_cast which was previously removed.
+
+2018-03-07: llongi
+ Github PR #1166 - Fix preprocessor handling of macros with commas
+ in a // comment.
+
+2018-02-18: JPEWdev
+ Patch #1164 - Add support for a command-line options file, also sometimes
+ called a response file. This is useful if the command-line options exceed
+ the system command-line length limit. To use, put the command-line options
+ into a file, then provide the file name prefixed with @, for example using
+ a file called args.txt:
+
+ swig @args.txt
+
+2018-02-11: wsfulton
+ [Javascript] #1187 Fix compilation error wrapping std::complex via
+ std_complex.i.
+
+2018-01-30: smarchetto
+ [Scilab] add type name argument in SWIG_ptr() function to cast from pointer address to typed pointers
+
+2018-01-16: wsfulton
+ Expressions following a preprocessor directive must now be separated by whitespace
+ or non-numeric characters. This syntax change makes the SWIG preprocessor work like
+ the C preprocessor in this area.
+
+ For example, the following code used be accepted as valid syntax:
+ #if1
+ #define ABC 123
+ #endif
+
+ Now you get an error:
+ example.h:1: Error: Unknown SWIG preprocessor directive: if1 (if this is a block of
+ target language code, delimit it with %{ and %})
+ example.h:3: Error: Extraneous #endif.
+
+ The following is the correct syntax:
+ #if 1
+ #define ABC 123
+ #endif
+
+ The following of course also works:
+ #if(1)
+ #define ABC 123
+ #endif
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2018-01-15: wsfulton
+ Fix issue #1183. Floating point exception evaluating preprocessor expressions
+ resulting in division by zero.
+
+2018-01-14: wsfulton
+ Fix issue #1172. Seg fault parsing invalid exponents in the preprocessor.
+
+2018-01-12: Liryna
+ [C#] Patch #1128. Add ToArray function to std::vector wrappers.
+
+2018-01-12: wsfulton
+ [Java] Fix issue #1156. Add missing throws clause for interfaces when using the
+ %interface family of macros.
+
+2018-01-05: wsfulton
+ Fix default arguments using expressions containing -> syntax error. Problem reported on
+ swig-user mailing list.
+
+2017-12-30: wsfulton
+ [Python] Replace pep8 with pycodestyle for checking the Python code style when
+ running Python tests.
+
+2017-12-30: davedissian
+ Fixed a symbol lookup issue when encountering a typedef of a symbol from the tag
+ namespace to the global namespace when the names are identical, such as 'typedef
+ struct Foo Foo;'.
+
+2017-12-13: wsfulton
+ [Perl] add missing support for directorfree typemaps.
+
+2017-12-13: wsfulton
+ Issue #1167 Fix directorout typemaps which were causing undefined behaviour when
+ returning pointers by reference.
+
+2017-12-08: olly
+ [PHP] Use ZEND_MODULE_GLOBALS_ACCESSOR to access globals so the
+ generated code builds when PHP was built with ZTS enabled.
+
+2017-12-04: wsfulton
+ [Python] Add missing checks for failures in calls to PyUnicode_AsUTF8String. Previously a
+ seg fault could occur when passing invalid UTF8 strings (low surrogates), eg passing
+ u"\udcff" to the C layer (Python 3).
+
+2017-11-24: joequant
+ [R] Fix #1124 and return R_NilValue for null pointers
+
+2017-11-29: wsfulton
+ [Java] director exception handling improvements.
+
+ When a director method throws an exception and it is caught by DirectorException
+ and passed back to Java using Swig::DirectorException::throwException, the Java
+ stack trace now contains the original source line that threw the exception.
+
+ Deprecate Swig::DirectorException::raiseJavaException, please replace usage with
+ Swig::DirectorException::throwException.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2017-10-26: wsfulton
+ Add support for C++11 ref-qualifiers when using directors.
+
+2017-10-26: wsfulton
+ Fix generated code when using directors and methods returning const ref pointers.
+
+2017-10-26: wsfulton
+ [C#, D, Java, Octave, R, Scilab] Port director typemaps to these additional languages.
+ Issue #700.
+
+2017-10-26: radarsat1
+ [Ruby Python] Patch #1029 - Correct handling of null using directors and shared_ptr.
+
+2017-10-10: joequant
+ [R] pass enum expressions to R. This will generate
+ incorrect files when there is an arithmetic expression
+ in the enum, but this is better than silently generating
+ incorrect code
+
+2017-10-09: olly
+ [PHP] Fix incorrect wrapper code generated when there's a
+ combination of overloading, parameters with a default value
+ and %newobject. Fixes https://sourceforge.net/p/swig/bugs/1350/
+
+2017-10-09: olly
+ Remove GCJ support. It isn't in a good state and doesn't seem to
+ be used, and GCC7 dropped GCJ. Closes
+ https://sourceforge.net/p/swig/bugs/823/
+
+2017-10-07: olly
+ Fix preprocessor handling of empty macro arguments to match that of
+ C/C++ compilers. Fixes issue #1111 and
+ https://sourceforge.net/p/swig/bugs/826/
+
+2017-10-06: wsfulton
+ [Python] Issue #1108. Fix platform inconsistency in Python default argument handling.
+ 32 bit and 64 bit compiled versions of SWIG generated different Python files
+ when default arguments were outside the range of 32 bit signed integers.
+ The default arguments specified in Python are now only those that are in the
+ range of a 32 bit signed integer, otherwise the default is obtained from C/C++ code.
+
+2017-10-02: wsfulton
+ [C#] Fix std::complex types passed by value.
+
+2017-10-02: wsfulton
+ [Javascript, Python, Ruby] Issue #732 - Missing type information for std::complex
+ in std_complex.i meant that previously std::complex always had to be fully qualified
+ in order to be wrapped with the appropriate typemaps.
+
+2017-10-01: joequant
+ allow R package names with docs
+ allowing multiple get accessors in R
+ fix smart-pointer and NAMESPACE support
+ constructors now returning smart pointers (if class
+ declared as such)
+ smart-pointer classes deriving from parent smart-pointers
+
+2017-09-29: wsfulton
+ Issue #1100 - Allow an instantiated template to have the same name in the target
+ language as the C++ template name, for example, this is now possible:
+
+ template<typename T> struct X { ... };
+ %template(X) X<int>;
+
+2017-09-23: wsfulton
+ Issue #1098. Fix overloading of shared_ptr with underlying pointer types, eg:
+
+ void m(std::shared_ptr<T> p);
+ void m(T &p);
+ void m(T *p);
+
+ Only the first method is wrapped and the others are ignored/shadowed.
+ The implementation is done via a new attribute in the 'typecheck' typemap called
+ 'equivalent'. If specified, it must contain the equivalent pointer type for overloading
+ and can only be used for the special SWIG_TYPECHECK_POINTER precedence level.
+ The shared_ptr 'typecheck' typemaps have been modified accordingly.
+ Here is a simplified version:
+
+ %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="T *")
+ T,
+ T CONST &,
+ T CONST *,
+ T *CONST&,
+ std::shared_ptr< T >,
+ std::shared_ptr< T > &,
+ std::shared_ptr< T > *,
+ std::shared_ptr< T > *&
+ { ... }
+
+ Overloading with any of these types will result in SWIG ignoring all but the first
+ overloaded method by default. Without the 'equivalent' attribute, wrapping the overloaded
+ methods resulted in types being shadowed (scripting languages) or code that did not
+ compile (statically typed languages).
+
+2017-09-19: futatuki
+ [Python] #1003 Add --with-2to3=/path/to/2to3 option to configure.
+
+2017-09-18: wsfulton
+ Fix type promotion wrapping constant expressions of the form:
+ # define EXPR_MIXED1 (0x80 + 11.1) - 1
+ This was previously an integral type instead of a floating point type.
+
+2017-09-17: wsfulton
+ Fix generated code for constant expressions containing wchar_t L literals such as:
+ # define __WCHAR_MAX (0x7fffffff + L'\0')
+ # define __WCHAR_MIN (-__WCHAR_MAX - 1)
+
+2017-09-10: mlamarre
+ [Python] Patch #1083. Define_DEBUG to 1 to do exactly like Visual Studio
+ /LDd, /MDd or /MTd compiler options.
+
+2017-08-25: wsfulton
+ Issue #1059. Add support for C++11 ref-qualifiers on non-static member functions.
+ Members with lvalue ref-qualifiers such as:
+
+ struct RQ {
+ void m1(int x) &;
+ void m2(int x) const &;
+ };
+
+ are wrapped like any other member function. Member functions with rvalue ref-qualifiers
+ are ignored by default, such as:
+
+ struct RQ {
+ void m3(int x) &&;
+ void m4(int x) const &&;
+ };
+
+ example.i:7: Warning 405: Method with rvalue ref-qualifier m3(int) && ignored.
+ example.i:8: Warning 405: Method with rvalue ref-qualifier m4(int) const && ignored.
+
+ These can be unignored and exposed to the target language, see further documentation in
+ CPlusPlus11.html.
+
+2017-08-16: wsfulton
+ Fix #1063. Add using declarations to templates into typedef table.
+
+ Using declarations to templates were missing in SWIG's internal typedef tables.
+ This led to a few problems, such as, templates that did not instantiate and generated
+ C++ code that did not compile as SWIG did not know what scope the template was
+ in. This happened mostly when a using declaration was used on a template type in a
+ completely unrelated namespace.
+
+2017-08-16: wsfulton
+ Fix type lookup in the presence of using directives and using declarations.
+
+ Fix some cases of type lookup failure via a combination of both using directives and
+ using declarations resulting in C++ code that did not compile as the generated type was
+ not fully qualified for use in the global namespace. Example below:
+
+ namespace Space5 {
+ namespace SubSpace5 {
+ namespace SubSubSpace5 {
+ struct F {};
+ }
+ }
+ using namespace SubSpace5;
+ using SubSubSpace5::F;
+ void func(SubSubSpace5::F f);
+ }
+
+2017-08-16: wsfulton
+ Issue #1051. %template scope enforcement and class definition fixes.
+
+ The scoping rules around %template have been specified and enforced.
+ The %template directive for a class template is the equivalent to an
+ explicit instantiation of a C++ class template. The scope for a valid
+ %template instantiation is now the same as the scope required for a
+ valid explicit instantiation of a C++ template. A definition of the
+ template for the explicit instantiation must be in scope where the
+ instantiation is declared and must not be enclosed within a different
+ namespace.
+
+ For example, a few %template and C++ explicit instantiations of std::vector
+ are shown below:
+
+ // valid
+ namespace std {
+ %template(vin) vector<int>;
+ template class vector<int>;
+ }
+
+ // valid
+ using namespace std;
+ %template(vin) vector<int>;
+ template class vector<int>;
+
+ // valid
+ using std::vector;
+ %template(vin) vector<int>;
+ template class vector<int>;
+
+ // ill-formed
+ namespace unrelated {
+ using std::vector;
+ %template(vin) vector<int>;
+ template class vector<int>;
+ }
+
+ // ill-formed
+ namespace unrelated {
+ using namespace std;
+ %template(vin) vector<int>;
+ template class vector<int>;
+ }
+
+ // ill-formed
+ namespace unrelated {
+ namespace std {
+ %template(vin) vector<int>;
+ template class vector<int>;
+ }
+ }
+
+ // ill-formed
+ namespace unrelated {
+ %template(vin) std::vector<int>;
+ template class std::vector<int>;
+ }
+
+ When the scope is incorrect, an error now occurs such as:
+
+ cpp_template_scope.i:34: Error: 'vector' resolves to 'std::vector' and
+ was incorrectly instantiated in scope 'unrelated' instead of within scope 'std'.
+
+ Previously SWIG accepted the ill-formed examples above but this led to
+ numerous subtle template scope problems especially in the presence of
+ using declarations and using directives as well as with %feature and %typemap.
+
+ Actually, a valid instantiation is one which conforms to the C++03
+ standard as C++11 made a change to disallow using declarations and
+ using directives to find a template.
+
+ // valid C++03, ill-formed C++11
+ using std::vector;
+ template class vector<int>;
+
+ Similar fixes for defining classes using forward class references have
+ also been put in place. For example:
+
+ namespace Space1 {
+ struct A;
+ }
+ namespace Space2 {
+ struct Space1::A {
+ void x();
+ }
+ }
+
+ will now error out with:
+
+ cpp_class_definition.i:5: Error: 'Space1::A' resolves to 'Space1::A' and
+ was incorrectly instantiated in scope 'Space2' instead of within scope 'Space1'.
+
+ Previously some symbols would have been instantiated in the wrong scope and led
+ to lots of scope problems involving SWIG typemaps, features, renames etc.
+ You will need to correct the scope used in other SWIG directives which do not
+ support 'using declarations' and 'using directives'. For example, if you previously had:
+
+ %rename(Zap) vector<int>::clear;
+ using namespace std;
+ %template(VectorInt) vector<int>;
+
+ Prior versions of SWIG incorrectly instantiated vector<int> in the global namespace
+ and so the %rename matched. Now the template is instantiated in the correct namespace,
+ so is fully qualified as std::vector<int>. The other SWIG directives need correcting as
+ they do not follow 'using declarations' and 'using directives'. Change it to:
+
+ %rename(Zap) std::vector<int>::clear;
+ using namespace std;
+ %template(vin) vector<int>;
+
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2017-08-16: wsfulton
+ Fix scope lookup for template parameters containing unary scope operators.
+
+ Fixes cases like:
+
+ namespace Alloc {
+ template<typename T> struct Rebind {
+ typedef int Integer;
+ };
+ }
+ %template(RebindBucket) Alloc::Rebind< Bucket >;
+ OR
+ %template(RebindBucket) Alloc::Rebind< ::Bucket >;
+
+ Alloc::Rebind< Bucket >::Integer Bucket1();
+ Alloc::Rebind< ::Bucket >::Integer Bucket2();
+ Alloc::Rebind<::template TemplateBucket<double>>::Integer Bucket3();
+
+2017-08-16: wsfulton
+ For templates only, the template parameters are fully resolved when
+ handling typemaps. Without this, it is too hard to have decent rules
+ to apply typemaps when parameter types are typedef'd and template
+ parameters have default values.
+
+ Fixes %clear for typedefs in templates, eg:
+
+ %typemap("in") XXX<int>::Long "..."
+ template typename<T> struct XXX {
+ typedef long Long;
+ };
+ %clear XXX<int>::Long;
+
+ as the typemap was previously incorrectly stored as a typemap for long
+ instead of XXX<int>::Long.
+
+2017-08-05: olly
+ [C++11] Allow static_assert at the top level (and disallow it right
+ after template<T>). Fixes issue 1031 reported by Artem V L.
+
+2017-08-02: wsfulton
+ Fix incorrectly shown warning when an empty template instantiation was used on a
+ class used as a base class and that base class was explicitly ignored with %ignore.
+ Example of the warning which will no longer appear:
+
+ Warning 401: Base class 'Functor< int,int >' has no name as it is an empty
+ template instantiated with '%template()'. Ignored.
+
+2017-07-17: fflexo
+ [Java] #674 Add std_list.i to add support for std::list containers. The Java proxy
+ extends java.util.AbstractSequentialList and makes the C++ std::list container look
+ and feel much like a java.util.LinkedList from Java.
+
+2017-07-07: wsfulton
+ [Python] Fix display of documented template types when using the autodoc
+ feature. For example when wrapping:
+
+ %feature("autodoc");
+ template<typename X> struct T {};
+ %template(TInteger) T<int>;
+
+ the generated documentation contains:
+ """Proxy of C++ T< int > class."""
+ instead of:
+ """Proxy of C++ T<(int)> class."""
+ and
+ """__init__(TInteger self) -> TInteger"""
+ instead of
+ """__init__(T<(int)> self) -> TInteger"""
+
+2017-06-27: nihaln
+ [PHP] Update the OUTPUT Typemap to add return statement to the
+ PHP Wrapper.
+
+2017-06-27: nihaln
+ [PHP] Update the enum and value examples to use the OO wrappers
+ rather than the flat functions produced with -noproxy. There's
+ not been a good reason to use -noproxy for since PHP5 OO wrapping
+ was fixed back in 2005.
+
+2017-06-23: m7thon
+ [Python] fix and improve default argument handling:
+
+ 1. Fix negative octals. Currently not handled correctly by `-py3`
+ (unusual case, but incorrect).
+ 2. Fix arguments of type "octal + something" (e.g. `0640 | 04`).
+ Currently drops everything after the first octal. Nasty!
+ 3. Fix bool arguments "0 + something" (e.g. `0 | 1`) are always
+ "False" (unusual case, but incorrect).
+ 4. Remove special handling of "TRUE" and "FALSE" from
+ `convertValue` since there's no reason these have to match
+ "true" and "false".
+ 5. Remove the Python 2 vs. Python 3 distinction based on the
+ `-py3` flag. Now the same python code is produced for default
+ arguments for Python 2 and Python 3. For this, octal default
+ arguments, e.g. 0644, are now wrapped as `int('644', 8)`. This
+ is required, as Python 2 and Python 3 have incompatible syntax
+ for octal literals.
+
+ Fixes #707
+
+2017-06-21: futatuki
+ #1004 - Fix ccache-swig executable name to respect configure's --program-prefix and
+ --program-suffix values if used.
+
+2017-06-21: tamuratak
+ [Ruby] #911 - Add std::wstring support.
+
+2017-06-19: wsfulton
+ [Python] Fix handling of rich comparisons when wrapping overloaded operators:
+
+ operator< operator<= operator> operator>= operator== operator!=
+
+ Previously a TypeError was always thrown if the type was not correct. NotImplemented
+ is now returned from these wrapped functions if the type being compared with is
+ not correct. The subsequent behaviour varies between different versions of Python
+ and the comparison function being used, but is now consistent with normal Python
+ behaviour. For example, for the first 4 operator overloads above, a TypeError
+ 'unorderable types' is thrown in Python 3, but Python 2 will return True or False.
+ NotImplemented should be returned when the comparison cannot be done, see PEP 207 and
+ https://docs.python.org/3/library/constants.html#NotImplemented
+
+ Note that the bug was only present when overloaded operators did not also have a
+ function overload.
+
+ Fixes SF bug #1208 (3441262) and SF patch #303.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2017-06-17: fabrice102
+ [Go] Fix Go callback example. Fixes github #600, #955, #1000.
+
+2017-06-16: wsfulton
+ Make sure warning and error messages are not split up by other processes writing to
+ stdout at the same time.
+
+2017-06-16: wsfulton
+ [R] Fix wrapping function pointers containing rvalue and lvalue reference parameters.
+
+2017-06-13: olly
+ [Perl] Fix testsuite to work without . in @INC - it was removed in
+ Perl 5.26 for security reasons, and has also been removed from
+ older versions in some distros. Fixes #997 reported by lfam.
+
+2017-06-03: wsfulton
+ Fix %import on a file containing a file scope %fragment forced inclusion to not
+ generate the fragment contents as %import should not result in code being generated.
+ The behaviour is now the same as importing code insertion blocks.
+ Wrapping FileC.i in the following example will result in no generated code, whereas
+ previously "#include <limits.h>" was generated:
+
+ // FileA.i
+ %fragment("<limits.h>", "header") %{
+ #include <limits.h>
+ %}
+
+ %{
+ #include <stdio.h>
+ %}
+ %fragment("<limits.h>");
+
+ // FileC.i
+ %import "FileA.i"
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2017-05-26: Volker Diels-Grabsch, vadz
+ [Java] #842 Extend from java.util.AbstractList<> and implement java.util.RandomAccess for
+ std::vector wrappers. This notably allows to iterate over wrapped vectors in a natural way.
+ Note that boxed types are now used in the Java layer when wrapping vector of C primitive
+ types, for example. This may introduce some subtle incompatibilities due to some
+ differences in how Java converts boxed types and unboxed types. For example,
+
+ int i=0;
+ double d1 = i; // ok
+ Double d2 = i; // error: incompatible types: int cannot be converted to Double
+
+ This can be a problem when calling the add and set functions. A suggested backwards
+ compatible workaround is to use something like (shown for std::vector<double>:
+
+ #if defined(SWIGJAVA)
+ // Add in old api that uses non-boxed types
+ %extend std::vector<double> {
+ %proxycode %{
+ public void add(double x) {
+ add(Double.valueOf(x));
+ }
+ public void set(int i, double val) {
+ set(i, Double.valueOf(val));
+ }
+ %}
+ }
+ #endif
+
+ %include "std_vector.i"
+ %template(VectorDouble) std::vector<double>;
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2017-05-30: davidcl
+ [Scilab] #994 Undefined symbol error when loading in Scilab 6
+
+2017-05-25: asibross
+ [Java] #370 #417 Missing smart pointer handling in Java director extra methods
+ swigReleaseOwnership() and swigTakeOwnership().
+
+2017-05-23: wsfulton
+ [Java] #230 #759 Fix Java shared_ptr and directors for derived classes java compilation
+ error.
+
+ For shared_ptr proxy proxy classes, add a protected method swigSetCMemOwn for modifying
+ the swigCMemOwn and swigCMemOwnDerived member variables which are used by various other
+ methods for controlling memory ownership.
+
+2017-05-21: Sghirate
+ [Java, C#, D] #449 Remove unnecessary use of dynamic_cast in directors to enable
+ non-RTTI compilation.
+
+2017-05-21: wsfulton
+ [Python] #993 Fix handling of default -ve unsigned values, such as:
+ void f(unsigned = -1U);
+
+2017-05-20: jschueller
+ [Python] #991 Fix E731 PEP8 warning: do not assign a lambda expression
+
+2017-05-16: nihal95
+ [PHP] Add %pragma version directive to allow the version of the
+ extension to be set. Patch #970, fixes #360.
+
+2017-05-13: yag00
+ Patch #975 - Add support for noexcept on director methods.
+
+2017-04-27: redbrain
+ Issue #974, Patch #976 - Fix preprocessor handling of macros with commas in a comment.
+
+2017-04-25: jleveque
+ [Lua] #959 - Fix Visual Studio C4244 conversion warnings in Lua wrappers.
+
+2017-04-21: tamuratak
+ [Ruby] #964 - Add shared_ptr director typemaps.
+
+2017-04-20: wsfulton
+ [Ruby] #586, #935 Add assert for invalid NULL type parameter when calling SWIG_Ruby_NewPointerObj.
+
+2017-04-20: tamuratak
+ [Ruby] #930, #937 - Fix containers of std::shared_ptr.
+ Upcasting, const types (eg vector<shared_ptr<const T>>) and NULL/nullptr support added.
+
+2017-04-12: smarchetto
+ [Scilab] New parameter targetversion to specify the Scilab target version (5, 6, ..) for code generation
+ With Scilab 6 target specified, identifier names truncation is disabled (no longer necessary)
+
+2017-03-24: tamuratak
+ [Ruby] Fix #939 - Wrapping std::vector<bool> fix due to incorrect null checks
+ on VALUE obj.
+
+2017-03-17: vadz
+ [C#] #947 Add support for std::complex<T>
+
+2017-03-17: wsfulton
+ [Go] Fix handling of typedef'd function pointers and typedef'd member function pointers
+ such as:
+
+ typedef int (*FnPtr_td)(int, int);
+ int do_op(int x, int y, FnPtr_td op);
+
+2017-03-16: wsfulton
+ Add support for member const function pointers such as:
+
+ int fn(short (Funcs::* parm)(bool)) const;
+
+ Also fix parsing of references/pointers and qualifiers to member
+ pointers such as:
+
+ int fn(short (Funcs::* const parm)(bool));
+ int fn(short (Funcs::* & parm)(bool));
+
+2017-03-10: wsfulton
+ Extend C++11 alternate function syntax parsing to support const and noexcept, such as:
+
+ auto sum1(int x, int y) const -> int { return x + y; }
+ auto sum2(int x, int y) noexcept -> int { return x + y; }
+
+2017-02-29: tamuratak
+ [Ruby] #917 - Add Enumerable module to all container class wrappers. It was missing
+ for std::list, std::multiset, std::unordered_multiset and std::unordered_map.
+
+2017-02-27: assambar
+ [C++11] Extend parser to support throw specifier in combination
+ with override and/or final.
+
+2017-02-10: tamuratak
+ [Ruby] #883 - Add support for C++11 hash tables:
+ std::unordered_map
+ std::unordered_set
+ std::unordered_multimap
+ std::unordered_multiset
+
+2017-02-08: jcsharp
+ [C#] #887 Improve std::vector<T> wrapper constructors -
+ Replace constructor taking ICollection with IEnumerable and also add IEnumerable<T>
+ constructor to avoid the boxing and unboxing overhead of the original constructor,
+ when the type parameter is a value type.
+
+Version 3.0.12 (27 Jan 2017)
+============================
+
+2017-01-27: wsfulton
+ [C#] #882 Fix missing filename in error messages when there is a problem
+ writing out C# files.
+
+2017-01-27: briancaine
+ [Guile] #744 Fix compilation errors in Guile wrappers - regression
+ introduced in swig-3.0.11.
+
+2017-01-24: andrey-starodubtsev
+ [Java] Apply #704 - director typemap improvements.
+ Memory leak fixes, add support for "directorargout" typemap and
+ add director support to typemaps.i.
+
+2017-01-24: wsfulton
+ Enhance %extend to extend a class with template constructors, eg:
+
+ struct Foo {
+ %extend {
+ template<typename T>
+ Foo(int a, T b) {
+ ...
+ }
+ }
+ };
+ %template(Foo) Foo::Foo<double>;
+
+2017-01-22: wsfulton
+ Issue #876 Enhance %extend to extend a class with template methods, eg:
+
+ struct Foo {
+ %extend {
+ template<typename T>
+ void do_stuff(int a, T b) {
+ ...
+ }
+ }
+ };
+ %template(do_stuff_inst) Foo::do_stuff<double>;
+
+ Similarly for static template methods.
+
+2017-01-22: kwwette
+ [Octave] add support for version 4.2
+ - The Octave API now uses some C++11 features. It is recommended to use
+ the mkoctfile program supplied by Octave to compile the SWIG-generated
+ wrapper code, as mkoctfile will ensure the correct C++ compiler/options
+ are used. Otherwise, the value of `mkoctfile -p CXX` should be parsed
+ for any -std=* flags which might be present.
+ - Octave has dropped support for << and >> operators, so SWIG now
+ ignores them.
+ - The Octave error() function now raises C++ exceptions to propagate
+ Octave errors, so %exception directives may need to be modified.
+ For convenience the SWIG_RETHROW_OCTAVE_EXCEPTIONS macro can be used
+ to rethrow any Octave exceptions for Octave itself to handle, e.g.:
+
+ try {
+ $action // may call error()
+ }
+ SWIG_RETHROW_OCTAVE_EXCEPTIONS // error() exceptions are rethrown
+ catch(...) {
+ ... // all other exceptions
+ }
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2017-01-16: wkalinin
+ [C#] Fix #733 regression introduced in swig-3.0.9.
+ Missing virtual function override in C# layer when using %import.
+
+2017-01-16: fschlimb
+ Fix #813 template symbol name lookup bug when typedef names are the same but in different
+ namespaces.
+
+2017-01-15: wsfulton
+ [C# D Java]
+ The SWIG library no longer uses the javatype, dtype or cstype typemaps, thereby
+ completely freeing them up for users to use without having to replicate the library
+ code that they previously added. The code previously generated by these typemaps
+ has been replaced by the new %proxycode directive. Their use in the library code
+ was fairly minimal:
+
+ C# cstype: std_array.i std_map.i std_vector.i
+ D dtype: std_vector.i
+ Java javatype: arrays_java.i
+
+2017-01-14: wsfulton
+ The %extend directive can now optionally support one of the 'class', 'struct' or 'union'
+ keywords before the identifier name, for example:
+
+ struct X { ... };
+ %extend struct X { ... }
+
+ Previously this had to specified as:
+
+ struct X { ... };
+ %extend X { ... }
+
+2017-01-13: wsfulton
+ [C# D Java] Add new %proxycode directive which is a macro for %insert("proxycode").
+ This is a way of adding pure C#/D/Java code into the appropriate proxy class, eg:
+
+ %extend Proxy2 {
+ %proxycode %{
+ public int proxycode2(int i) {
+ return i+2;
+ }
+ %}
+ }
+
+ %inline %{
+ struct Proxy2 {};
+ %}
+
+ There will then be a pure Java/C#/D method called proxycode2 in the Proxy2 class.
+
+2016-12-31: ajrheading1
+ Issue #860 - Remove use of std::unary_function and std::binary_function
+ which is deprecated in C++11.
+
+2016-12-30: olly
+ [PHP7] Register internal 'swig_runtime_data_type_pointer' constant
+ as "CONST_PERSISTENT" to avoid segmentation fault on module unload.
+ Fixes #859 reported by Timotheus Pokorra. Thanks also to Javier Torres
+ for a minimal reproducer.
+
+Version 3.0.11 (29 Dec 2016)
+============================
+
+2016-12-24: wsfulton
+ [C#] Add %feature("csdirectordelegatemodifiers") to enable customization
+ of the delegate access modifiers generated in director classes.
+ Fixes issue #748.
+
+2016-12-23: wsfulton
+ [Python] Fix builtin "python:slot" feature failing for tp_hash when using
+ hashfunc closure with a "Wrong type for hash function" for Python 2.
+ Issue #843.
+
+2016-12-21: joequamt
+ Changed generation of functions so that only functions
+ that end in _set generate accessor functions rather than
+ looking for "set".
+ Change generation of operators to not have underscores
+ to start in R. Users need to provide custom names for these operator overloads.
+
+2016-12-21: olly
+ Fix isfinite() checks to work with all C++11 compilers.
+ Fixes issues #615, #788 and #849.
+
+2016-12-20: wsfulton
+ %namewarn unnecessarily caused keyword warnings for non-instantiated template classes
+ and duplicate warnings for instantiated template classes when keywords were used.
+ Issue #845.
+
+2016-12-18: ezralanglois
+ [Python, Ruby, Octave] Memory leak fix on error in std::pair wrappers.
+ Issue #851.
+
+2016-12-18: wsfulton
+ Zero initialize arrays when using %array_class and %array_functions.
+
+2016-12-18: t-ikegami
+ [Python] Fix #446
+ Python %array_class of carrays.i failed with -builtin option.
+
+2016-12-16: briancaine
+ [Guile] Patch #744 Added support for Guile's native pointer functionality
+
+2016-12-01: wsfulton
+ [Python] Issue #769.
+ Add optional moduleimport attribute to %module so that the
+ default module import code can be overridden. See the "Searching for the wrapper module"
+ documentation in Python.html. Example:
+
+ %module(moduleimport="import _foo") foo
+
+ $module also expands to the low-level C/C++ module name, so the following is the
+ same as above
+
+ %module(moduleimport="import $module") foo
+
+2016-11-30: olly
+ [PHP] Add support for PHP7. PHP5's C extension API has changed
+ substantially so you need to use -php7 to specify you want PHP7
+ compatible wrappers. The default extension for generated wrappers
+ is now .cxx (to match SWIG's default for every other language - to
+ generate foo_wrap.cpp you can run SWIG with -cppext cpp). Fixes
+ issue #571.
+
+ As part of this change, the language subdirectory for PHP5 has
+ changed from "php" to "php5" - if you are making use of the search
+ path feature where the language subdirectory of each directory
+ is also searched, you'll need to update your bindings. A simple
+ fix which works for older and newer SWIG is to add a symlink:
+ ln -s php php5
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2016-11-30: olly
+ [PHP] Only emit one copy of each distinct arginfo. Previously we
+ emitted a separate one for every wrapped function, but typically
+ many functions have the same number of parameters and combinations
+ of parameters passed by reference or not.
+
+ This change significantly reduces both the size of the generated
+ wrapper, and of the compiled PHP extension module (e.g. by ~6% for
+ the stripped extension module for Xapian's PHP7 bindings).
+
+2016-11-28: wsfulton
+ Fix %rename override of wildcard %rename for templates. For example:
+
+ %rename(GlobalIntOperator) *::operator bool; // wildcard %rename
+
+ %rename(XIntOperator) X::operator bool; // fix now overrides first %rename above
+ OR
+ %rename(XIntOperator) X<int>::operator bool; // fix now overrides first %rename above
+
+ template<typename T> struct X {
+ operator bool();
+ ...
+ };
+ %template(Xint) X<int>;
+
+ This also fixes %rename override of global %rename for templates. For example:
+
+ // Global rename to make all functions start with a lower case letter
+ %rename("%(firstlowercase)s", %$isfunction ) "";
+ %rename(woohoo) W::Woo; // fix now overrides above %rename
+
+ template<typename T> struct W {
+ W Woo();
+ ...
+ };
+ %template(Wint) W<int>;
+
+ The above also introduces a possibly unexpected change. Many of the STL containers
+ provided by SWIG use %rename to rename some methods, eg in std::vector, push_back
+ is renamed to add in Java. Previously this intended rename did not happen when using
+ using global %rename rules and the method would remain as push_back, but is now
+ renamed to add. Some more info in issue #856.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2016-11-26: m7thon
+ [Python] Issue #709 - improved wrapping of division operators
+ 'from __future__ import division' now works in Python 2 whether or not the
+ -py3 flag is used.
+
+2016-11-12: joequant
+ [R] Issue #697 - fix comma issue with overload methods
+
+2016-11-12: joequant
+ [R] Issue #555 - R runtime needs stdio.h
+
+2016-11-02: wsfulton
+ [Python] Issue #816 - fix compilation error when using -extranative and -builtin.
+
+2016-11-02: liorgold
+ Patch #741 - Add support for C++11 alias templates, see updated CPlusPlus11.html
+ documentation.
+
+2016-10-30: myd7349
+ [C#] Patch #740 Add std_array.i for C# for wrapping std::array.
+
+ Patch also enhances std::vector<std::wstring> C# wrappers with additional functions
+ (Contains, IndexOf, LastIndexOf and Remove).
+
+2016-10-30: tobilau
+ [Java] Fix wrappers for wstring parameters in director methods to cleanup local
+ ref after director callback has finished.
+
+2016-10-23: wsfulton
+ [C#] Add missing csdirectorin VOID_INT_PTR and csdirectorout VOID_INT_PTR typemaps.
+
+2016-10-23: jiulongw
+ Patch #781 - Fix wrapping of C compound expressions containing char constants
+ in quotes such as:
+
+ #define H_SUPPRESS_SCALING_MAGIC (('s'<<24) | ('u'<<16) | ('p'<<8) | 'p')
+
+ enum DifferentTypes {
+ typecharcompound='A'+1,
+ typecharcompound2='B' << 2
+ };
+
+2016-10-13: wsfulton
+ [Python] Issue #808 - fix Python pickling and metaclass for builtin wrappers.
+
+ The metaclass (SwigPyObjectType) for SWIG objects was not defined in
+ a way that let importlib successfully import the Python wrappers.
+ The pickle module previously failed to pickle objects because it couldn't
+ determine what module the SWIG wrapped objects were in.
+
+2016-09-29: wsfulton
+ [Allegrocl, CFFI, GO, Javascript, Ocaml, R, Scilab]
+ Add missing support for the "ret" typemap in a few target languages.
+ The documentation also now has info on the "ret" typemap.
+
+2016-09-27: ahmed-usman
+ [xml] Handle template parameters correctly.
+
+2016-09-27: dontpanic92
+ [Go] Fix argument names in inherited functions taking more than 8
+ parameters. Fixes #795.
+
+2016-09-26: smarchetto
+ [Scilab] mlists that map pointers can be given a custom type name.
+
+2016-09-25: wsfulton
+ Patch #793 from q-p to expand exception handling to include std::bad_cast
+ in std_except.i.
+
+2016-09-24: olly
+ [PHP] Fix code generated for feature("director:except") -
+ previously the return value of call_user_function() was ignored and
+ we checked an uninitialised value instead. Fixes #627. Based on
+ patch from Sergey Seroshtan.
+
+2016-09-22: wsfulton
+ [Python] More flexible python builtin slots for overloaded C++ function.
+
+ The closure names used for builtin slots are mangled with their functype so
+ that overloaded C++ method names can be used for multiple slots.
+ For example:
+
+ %feature("python:slot", "mp_subscript", functype="binaryfunc") SimpleArray::__getitem__;
+ %feature("python:slot", "sq_item", functype="ssizeargfunc") SimpleArray::__getitem__(Py_ssize_t n);
+
+ will generate closures:
+
+ SWIGPY_SSIZEARGFUNC_CLOSURE(_wrap_SimpleArray___getitem__) /* defines _wrap_SimpleArray___getitem___ssizeargfunc_closure */
+ SWIGPY_BINARYFUNC_CLOSURE(_wrap_SimpleArray___getitem__) /* defines _wrap_SimpleArray___getitem___binaryfunc_closure */
+
+ Previously only one name was defined: _wrap_SimpleArray___getitem___closure.
+ Hence the overloaded __getitem__ method can be used to support both mp_subscript and sq_item slots.
+
+2016-09-17: wsfulton
+ [Python] Fix iterators for containers of NULL pointers (or Python None) when using
+ -builtin. Previously iteration would stop at the first element that was NULL.
+
+2016-09-16: olly
+ [Javascript] Fix SWIG_exception() macro to return from the current
+ function. Fixes #789, reported by Julien Dutriaux.
+
+2016-09-16: olly
+ [PHP] Fix SWIG_exception() macro to return from the current function.
+ Fixes #240, reported by Sergey Seroshtan.
+
+2016-09-12: xypron
+ [C#] Patch #786 Keyword rename to be CLS compliant by adding an underscore
+ suffix instead of an underscore prefix to the C symbol name. Please use an explicit
+ %rename to rename the symbol with a _ prefix if you want the old symbol name.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2016-09-09: olly
+ [Python] Fix import handling for Python 2.6 to work in a frozen
+ application. Fixes #145, reported by Thomas Kluyver.
+
+2016-09-02: smarchetto
+ [Scilab] Pointers are mapped to mlist instead of tlist
+ (mlist better for scilab overloading)
+
+2016-09-02: olly
+ [PHP] Fix "out" typemap for member function pointers and "in"
+ typemap for char INPUT[ANY].
+
+2016-09-01: wsfulton
+ [Python] More efficient Python slicing.
+ Call reserve for container types that support it to avoid repeated
+ memory reallocations for new slices or slices that grow in size.
+
+2016-09-01: wsfulton
+ [Python] #771 - Make builtin types hashable by default.
+ Default hash is the underlying C/C++ pointer. This matches up with testing for
+ equivalence (Py_EQ in SwigPyObject_richcompare) which compares the pointers.
+
+2016-08-22: wsfulton
+ [Python] The following builtin slots can be customized like other slots via the
+ "python:<x>" and "python:slot" features where <x> is the appropriate slot name:
+ tp_allocs
+ tp_bases
+ tp_basicsize
+ tp_cache
+ tp_del
+ tp_dealloc
+ tp_flags
+ tp_frees
+ tp_getset
+ tp_is_gc
+ tp_maxalloc
+ tp_methods
+ tp_mro
+ tp_new
+ tp_next
+ tp_prev
+ tp_richcompare
+ tp_subclasses
+ tp_weaklist
+ was_sq_ass_slice
+ was_sq_slice
+
+ A few documentation improvements for slot customization.
+
+2016-08-09: joequant
+ [R] Patch #765 Fix extern "C" header includes for C++ code.
+
+2016-08-05: olly
+ [xml] Fix how the output filename is built to avoid problems when
+ it contains the embedded strings ".c", ".cpp" or ".cxx".
+ Fixes #540 reported by djack42.
+
+2016-07-01: wsfulton
+ Fix corner case of wrapping std::vector of T pointers where a pointer to a pointer of T
+ also exists in the wrapped code. SF Bug 2359417 (967).
+
+2016-06-26: wkalinin
+ [Java, C#] Patch #681 Fix seg fault when ignoring nested classes.
+
+2016-06-25: mromberg
+ [Python] #711 Fix -castmode and conversion of signed and unsigned integer types.
+ See 2015-12-23 CHANGES entry for details of these improvements when they were
+ implemented for the default options (ie not using -castmode).
+
+2016-06-25: ahnolds
+ Patch #730 - Fix %implicitconv for overloaded functions when using
+ -castmode or -fastdispatch options.
+
+ The result is that in all overload cases where there are multiple possibilities
+ with the same number of arguments, the dispatch function will first check for
+ exact (aka non implicit) matches, and then subsequently check for implicit
+ casting matches. This was already happening in the normal dispatch situation,
+ and in the -fastdispatch case two passes through the candidates were happening,
+ just with SWIG_POINTER_IMPLICIT_CONV always set. After this patch, it is not set
+ on the first pass, and then set on the second pass.
+
+2016-06-25: liorgold
+ Patch #727 - Add support for C++11 type aliasing.
+
+Version 3.0.10 (12 Jun 2016)
+============================
+
+2016-06-06: mromberg
+ [Python] Patch #698. Add support for -relativeimport for python 2.7, so -py3 is no
+ longer also required for relative import support.
+
+2016-06-05: mromberg
+ [Python] Patch #694 - Fix package import regressions introduced in swig-3.0.9.
+
+ 1) The code in 3.0.9 did not fall back to 'import _foo' if 'import bar._foo' failed
+ (assuming bar.foo was the main module). Every place _foo is imported now first tries
+ it from the package where foo was found and if that fails tries _foo as a global module.
+
+ 2) The separate block of Python code that injected code to pull in the attributes
+ from _foo when -builtin is used made use of the -py3 switch to either do
+ 'from ._foo import *' or "from _foo import *". This block of code no longer does this
+ and instead checks the Python version at runtime to switch between the two syntaxes.
+
+ In summary, swig-3.0.10 has been modified to ease the creation of wrapper modules
+ that can be fully made part of a Python package. SWIG no longer
+ assumes the dynamically linked C module is a global module.
+ The dynamic module can now be placed into either the same package as the pure Python
+ module or as a global module. Both locations are used by the Python wrapper to
+ locate the C module.
+
+ However, this could cause a backwards incompatibility with some code
+ that was relying on the ability of "from package import _module" to
+ pull attributes out of the package directly. If your code populates a
+ module (which is also a package) with attributes that are SWIG
+ generated modules which were not loaded in a conventional way,
+ swig-3.0.8 and earlier may have worked due to 'from package import
+ _module' bypassing a real import and pulling your module in as an
+ attribute. This will no longer work. Since this is not a common (or
+ even recommended) practice, most folk should not be affected.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2016-05-31: wsfulton
+ Fix #690 - Smart pointer to %ignored class doesn't expose inherited methods.
+ Regression introduced in swig-3.0.9.
+
+Version 3.0.9 (29 May 2016)
+===========================
+
+2016-05-24: mromberg
+ [Python] Patch #612 - Add support for Python's implicit namespace packages.
+
+2016-05-23: wsfulton
+ [Ruby] Fix #602 - Error handling regression of opaque pointers introduced
+ in swig-3.0.8 when C functions explicitly reset a pointer using 'DATA_PTR(self) = 0'.
+ An ObjectPreviouslyDeleted error was incorrectly thrown when the pointer was used
+ as a parameter.
+
+2016-05-17: tamuratak
+ [Ruby] Patch #651 - Correct overloaded function error message when function is
+ using %newobject.
+
+2016-05-17: aurelj
+ [Ruby] Patch #582 - add support for docstring option in %module()
+
+2016-05-14: wsfulton
+ Fix #434 - Passing classes by value as parameters in director methods did not create
+ a copy of the argument leading to invalid memory accesses if the object was used
+ after the upcall into the target language. Passing arguments by value shouldn't give
+ rise to these sorts of memory problems and so the objects are now copied and ownership
+ of their lifetime is controlled by the target language.
+
+2016-05-07: wsfulton
+ Fix #611. Fix assertion handling defaultargs when using %extend for a template
+ class and the extended methods contain default arguments.
+
+2016-05-05: ejulian
+ [Python] Patch #617. Fix operator/ wrappers.
+
+2016-05-02: wsfulton
+ Fix #669. Don't issue warning about ignoring base classes when the derived class is
+ itself ignored.
+
+2016-04-18: ianlancetaylor
+ [Go] Fix use of goout typemap when calling base method by
+ forcing the "type" attribute to the value we need.
+
+2016-04-17: ianlancetaylor
+ [Go] Fixes for Go 1.6: avoid returning Go pointers from
+ directors that return string values; add a trailing 0 byte
+ when treating Go string as C char*.
+
+2016-04-06: smarchetto
+ [Scilab] #552 Make Scilab runtime keep track of pointer types
+ Instead of a Scilab pointer which has no type, SWIG Scilab maps a
+ pointer to a structure tlist containing the pointer adress and its type.
+
+2016-04-02: ahnolds
+ [Python] Apply #598. Fix misleading error message when attempting to read a non-existent
+ attribute. The previous cryptic error message:
+ AttributeError: type object 'object' has no attribute '__getattr__'
+ is now replaced with one mentioning the attribute name, eg:
+ AttributeError: 'Foo' object has no attribute 'bar'
+
+2016-04-02: derkuci
+ [Python] Patch #610 to fix #607.
+ Fix single arguments when using python -builtin -O with %feature("compactdefaultargs")
+
+2016-03-31: wsfulton
+ Fixes #594. Fix assertion for some languages when wrapping a C++11 enum class that
+ is private in a class.
+
+ Also don't wrap private enums for a few languages that attempted to do so.
+
+2016-03-31: wsfulton
+ [Java] unsigned long long marshalling improvements when a negative number
+ is passed from Java to C. A cast to signed long long in the C layer will now
+ result in the expected value. No change for positive numbers passed to C.
+ Fixes #623.
+
+2016-03-22: alexwarg
+ [Lua] #398 Fix lua __getitem + inheritance
+ The new handling of classes in Lua (not merging methods into the derived classes)
+ breaks for classes that provide a __getitem function. The __getitem function
+ prevents method calls to any method defined in a base class. This fix calls
+ __getitem only if the member is not found using recursive lookup.
+
+2016-03-18: ptomulik
+ [Python] #563 Stop generating unnecessary _swigconstant helpers.
+
+2016-03-16: richardbeare
+ [R] #636 Add extra std::vector numeric types
+
+2016-03-14: wsfulton
+ [Java] Add std_array.i for C++11 std::array support.
+
+2016-03-12: wsfulton
+ [Java, C#, D] Fix static const char member variables wrappers with %javaconst(1)
+ %csconst(1) or %dmanifestconst.
+ This fixes the case when an integer is used as the initializer, such as:
+
+ struct W { static const char w = 100; };
+
+ Fix generated code parsing enum values using char escape sequences
+ when these values appear in the Java code (usually when using %javaconst(1))
+ such as:
+
+ enum X { x1 = '\n', x2 = '\1' };
+
+ Similarly for static const member char variables such as:
+
+ struct Y { static const char y = '\n'; }
+
+ Likewise for D and %dmanifestconstant. For C# and %csconst(1), char
+ values in C# are now hex escaped as C# doesn't support C octal escaping.
+
+2016-03-11: wsfulton
+ [Java C#] Add support for treating C++ base classes as Java interfaces
+ instead of Java proxy classes. This enable some sort of support for
+ multiple inheritance. The implementation is in swiginterface.i and
+ provides additional macros (see Java.html for full documentation):
+
+ %interface(CTYPE)
+ %interface_impl(CTYPE)
+ %interface_custom("PROXY", "INTERFACE", CTYPE)
+
+2016-03-01: wsfulton
+ Add rstrip encoder for use in %rename. This is like the strip encoder but
+ strips the symbol's suffix instead of the prefix. The example below
+ will rename SomeThingCls to SomeThing and AnotherThingCls to AnotherThing:
+
+ %rename("%(rstrip:[Cls])s") "";
+
+ class SomeThingCls {};
+ struct AnotherThingCls {};
+
+2016-03-01: olly
+ Fix isfinite() check to work with GCC6. Fixes
+ issue #615 reported by jplesnik.
+
+2016-02-17: olly
+ [Python] Add missing keywords 'as' and 'with' to pythonkw.swg.
+
+2016-02-07: kwwette
+ [Octave] recognise various unary functions
+ * Use __float__() for numeric conversions, e.g. when calling double()
+ * Map various unary functions, e.g. abs() to __abs__(), see full list
+ in section 32.3.10 of manual; only available in Octave 3.8.0 or later
+
+2016-02-07: kwwette
+ [Octave] export function swig_octave_prereq() for testing Octave version
+
+2016-02-06: pjohangustavsson
+ [C#] Fix duplicate symbol problems when linking the source generated
+ from multiple SWIG modules into one shared library for the -namespace
+ option. The namespace is now mangled into the global PInvoke function
+ names.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2016-01-27: ahnolds
+ [Python] Added support for differentiating between Python Bytes
+ and Unicode objects using by defining SWIG_PYTHON_STRICT_BYTE_CHAR
+ and SWIG_PYTHON_STRICT_UNICODE_WCHAR.
+
+2016-01-27: steeve
+ [Go] Ensure structs are properly packed between gc and GCC/clang.
+
+2016-01-25: ahnolds
+ [Python] Support the full Python test suite in -classic mode
+ * Convert long/unsigned long/long long/unsigned long long to PyInt
+ rather than PyLong when possible. Certain python functions like
+ len() require a PyInt when operating on old-style classes.
+ * Add support for static methods in classic mode, including support
+ for pythonappend, pythonprepend, and docstrings.
+ * Removing the use of __swig_getmethods__ for static member methods
+ since they will always be found by the standard argument lookup
+ * Fix a bug where the wrong type of exception was caught when
+ checking for new-style class support
+
+2016-01-23: ahnolds
+ [Go] Enable support for the Go test-suite on OSX:
+ * The linker on OSX requires that all symbols (even weak symbols)
+ are defined at link time. Because the function _cgo_topofstack is
+ only defined starting in Go version 1.4, we explicitly mark it as
+ undefined for older versions of Go on OSX.
+ * Avoid writing empty swigargs structs, since empty structs are not
+ allowed in extern "C" blocks.
+
+2016-01-12: olly
+ [Javascript] Look for "nodejs" as well as "node", as it's packaged
+ as the former on Debian.
+
+2016-01-12: olly
+ [Javascript] For v8 >= 4.3.0, use V8_MAJOR_VERSION.
+ Fixes issue 561.
+
+2016-01-10: ahnolds
+ Improved size_t and ptrdiff_t typemaps to support large values
+ on platforms where sizeof(size_t) > sizeof(unsigned long) and
+ sizeof(ptrdiff_t) > sizeof(long).
+
+Version 3.0.8 (31 Dec 2015)
+===========================
+
+2015-12-30: wsfulton
+ The pdf documentation is now generated by wkhtmltopdf and has colour
+ for the code snippets just like the html documentation!
+
+2015-12-23: ahnolds
+ [Python] Fixes for conversion of signed and unsigned integer types:
+
+ No longer check for PyInt objects in Python3. Because PyInt_Check
+ and friends are #defined to the corresponding PyLong methods, this
+ had caused errors in Python3 where values greater than what could be
+ stored in a long were incorrectly interpreted as the value -1 with
+ the Python error indicator set to OverflowError. This applies to
+ both the conversions PyLong->long and PyLong->double.
+
+ Conversion from PyLong to long, unsigned long, long long, and
+ unsigned long long now raise OverflowError instead of TypeError in
+ both Python2 and Python3 for PyLong values outside the range
+ expressible by the corresponding C type. This matches the existing
+ behavior for other integral types (signed and unsigned ints, shorts,
+ and chars), as well as the conversion for PyInt to all numeric
+ types. This also indirectly applies to the size_t and ptrdiff_t
+ types, which depend on the conversions for unsigned long and long.
+
+2015-12-19: wsfulton
+ [Python] Python 2 Unicode UTF-8 strings can be used as inputs to char * or
+ std::string types if the generated C/C++ code has SWIG_PYTHON_2_UNICODE defined.
+
+2015-12-17: wsfulton
+ Issues #286, #128
+ Remove ccache-swig.1 man page - please use the CCache.html docs instead.
+ The yodl2man and yodl2html tools are no longer used and so SWIG no
+ longer has a dependency on these packages which were required when
+ building from git.
+
+2015-12-16: zturner/coleb
+ [Python] Fix Python3.5 interpreter assertions when objects are being
+ deleted due to an existing exception. Most notably in generators
+ which terminate using a StopIteration exception. Fixes #559 #560 #573.
+ If a further exception is raised during an object destruction,
+ PyErr_WriteUnraisable is used on this second exception and the
+ original exception bubbles through.
+
+2015-12-14: ahnolds/wsfulton
+ [Python] Add in missing initializers for tp_finalize,
+ nb_matrix_multiply, nb_inplace_matrix_multiply, ht_qualname
+ ht_cached_keys and tp_prev.
+
+2015-12-12: wsfulton
+ Fix STL wrappers to not generate <: digraphs.
+ For example std::vector<::X::Y> was sometimes generated, now
+ corrected to std::vector< ::X::Y >.
+
+2015-11-25: wsfulton
+ [Ruby] STL ranges and slices fixes.
+
+ Ruby STL container setting slices fixes:
+
+ Setting an STL container wrapper slice better matches the way Ruby
+ arrays work. The behaviour is now the same as Ruby arrays. The only
+ exception is the default value used when expanding a container
+ cannot be nil as this is not a valid type/value for C++ container
+ elements.
+
+ Obtaining a Ruby STL container ranges and slices fixes:
+
+ Access via ranges and slices now behave identically to Ruby arrays.
+ The fixes are mostly for out of range indices and lengths.
+ - Zero length slice requests return an empty container instead of nil.
+ - Slices which request a length greater than the size of the container
+ no longer chop off the last element.
+ - Ranges which used to return nil now return an empty array when the
+ the start element is a valid index.
+
+ Ruby STL container negative indexing support improved.
+
+ Using negative indexes to set values works the same as Ruby arrays, eg
+
+ %template(IntVector) std::vector<int>;
+
+ iv = IntVector.new([1,2,3,4])
+ iv[-4] = 9 # => [1,2,3,9]
+ iv[-5] = 9 # => IndexError
+
+2015-11-21: wsfulton
+ [Ruby, Python] Add std::array container wrappers.
+
+ These work much like any of the other STL containers except Python/Ruby slicing
+ is somewhat limited because the array is a fixed size. Only slices of
+ the full size are supported.
+
+2015-10-10: wsfulton
+ [Python] #539 - Support Python 3.5 and -builtin. PyAsyncMethods is a new
+ member in PyHeapTypeObject.
+
+2015-10-06: ianlancetaylor
+ [Go] Don't emit a constructor function for a director
+ class with an abstract method, since the function will
+ always panic.
+
+2015-10-01: wsfulton
+ Fix %shared_ptr support for private and protected inheritance.
+ - Remove unnecessary Warning 520: Derived class 'Derived' of 'Base'
+ is not similarly marked as a smart pointer
+ - Do not generate code that attempts to cast up the inheritance chain in the
+ type system runtime in such cases as it doesn't compile and can't be used.
+ Remove unnecessary warning 520 for %shared_ptr when the base class is ignored.
+
+2015-10-01: vkalinin
+ Fix #508: Fix segfault parsing anonymous typedef nested classes.
+
+2015-09-26: wsfulton
+ [Ruby] Add shared_ptr support
+
+2015-09-13: kkaempf
+ [Ruby] Resolve tracking bug - issue #225.
+ The bug is that the tracking code uses a ruby hash and thus may
+ allocate objects (Bignum) while running the GC. This was tolerated in
+ 1.8 but is invalid (raises an exception) in 1.9.
+ The patch uses a C hash (also used by ruby) instead.
+
+2015-09-09: lyze
+ [CFFI] Extend the "export" feature in the CFFI module to support
+ exporting to a specified package.
+
+2015-09-04: olly
+ [Python] Fix docstrings for %callback functions.
+
+2015-09-03: demi-rluddy
+ [Go] Removed golang stringing for signed/unsigned char
+
+ Changed default handling of signed char* and unsigned char* to be
+ opaque pointers rather than strings, similarly to how other
+ languages work.
+
+ Any existing code relying on treating signed char* or unsigned
+ char* as a string can restore the old behavior with typemaps.i by
+ using %apply to copy the [unchanged] char* behavior.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2015-08-07: talby
+ [Perl] tidy -Wtautological-constant-out-of-range-compare warnings when building generated code under clang
+
+2015-08-07: xantares
+ [Python] pep257 & numpydoc conforming docstrings:
+ - Mono-line module docsstring
+ - Rewrite autodoc parameters section in numpydoc style:
+ https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+ - One line summary should end with "."
+ - Adds a blank line after class docstring
+
+2015-08-05: vadz
+ [Java] Make (char* STRING, size_t LENGTH) typemaps usable for
+ strings of other types, e.g. "unsigned char*".
+
+Version 3.0.7 (3 Aug 2015)
+==========================
+
+2015-08-02: wsfulton
+ [Java] Fix potential security exploit in generated Java classes.
+ The swigCPtr and swigCMemOwn member variables in the generated Java
+ classes are now declared 'transient' by default. Further details of the exploit
+ in Android is being published in an academic paper as part of USENIX WOOT '15:
+ https://www.usenix.org/conference/woot15/workshop-program/presentation/peles.
+
+ In the unlikely event that you are relying on these members being serializable,
+ then you will need to override the default javabody and javabody_derived typemaps
+ to generate the old generated code. The relevant typemaps are in the Lib directory
+ in the java.swg, boost_shared_ptr.i and boost_intrusive_ptr.i files. Copy the
+ relevant default typemaps into your interface file and remove the 'transient' keyword.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2015-08-01: vadz
+ Make configure --without-alllang option more useful: it can now be overridden by the following
+ --with-xxx options, allowing to easily enable just one or two languages.
+
+2015-07-30: wsfulton
+ Fix #440 - Initialise all newly created arrays when using %array_functions and %array_class
+ in the carrays.i library - bug is only relevant when using C++.
+
+2015-07-29: wsfulton
+ [Python] Improve indentation warning and error messages for code in the following directives:
+
+ %pythonprepend
+ %pythonappend
+ %pythoncode
+ %pythonbegin
+ %feature("shadow")
+
+ Old error example:
+ Error: Line indented less than expected (line 3 of pythoncode)
+
+ New error example:
+ Error: Line indented less than expected (line 3 of %pythoncode or %insert("python") block)
+ as no line should be indented less than the indentation in line 1
+
+ Old warning example:
+ Warning 740: Whitespace prefix doesn't match (line 2 of %pythoncode or %insert("python") block)
+
+ New warning example:
+ Warning 740: Whitespace indentation is inconsistent compared to earlier lines (line 3 of
+ %pythoncode or %insert("python") block)
+
+
+2015-07-28: wsfulton
+ [Python] Fix #475. Improve docstring indentation handling.
+
+ SWIG-3.0.5 and earlier sometimes truncated text provided in the docstring feature.
+ This occurred when the indentation (whitespace) in the docstring was less in the
+ second or later lines when compared to the first line.
+ SWIG-3.0.6 gave a 'Line indented less than expected' error instead of truncating
+ the docstring text.
+ Now the indentation for the 'docstring' feature is smarter and is appropriately
+ adjusted so that no truncation occurs.
+
+2015-07-22: wsfulton
+ Support for special variable expansion in typemap attributes. Example usage expansion
+ in the 'out' attribute (C# specific):
+
+ %typemap(ctype, out="$*1_ltype") unsigned int& "$*1_ltype"
+
+ is equivalent to the following as $*1_ltype expands to 'unsigned int':
+
+ %typemap(ctype, out="unsigned int") unsigned int& "unsigned int"
+
+ Special variables can be used within special variable macros too. Example usage expansion:
+
+ %typemap(cstype) unsigned int "uint"
+ %typemap(cstype, out="$typemap(cstype, $*1_ltype)") unsigned int& "$typemap(cstype, $*1_ltype)"
+
+ Special variables are expanded first and hence the above is equivalent to:
+
+ %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)"
+
+ which then expands to:
+
+ %typemap(cstype, out="uint") unsigned int& "uint"
+
+2015-07-22: lindleyf
+ Apply patch #439 - support for $typemap() (aka embedded typemaps or special variable
+ macros) in typemap attributes. A simple example where $typemap() is expanded in the
+ 'out' attribute (C# specific):
+
+ %typemap(cstype) unsigned int "uint"
+ %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)"
+
+ is equivalent to:
+
+ %typemap(cstype, out="uint") unsigned int& "uint"
+
+2015-07-18: m7thon
+ [Python] Docstrings provided via %feature("docstring") are now quoted and added to
+ the tp_doc slot when using python builtin classes (-builtin). When no docstring is
+ provided, the tp_doc slot is set to the fully qualified C/C++ class name.
+ Github issues #445 and #461.
+
+2015-07-17: kwwette
+ [octave] Support Octave version 4.0.0 (thanks to patches from Orion Poplawski).
+
+2015-07-07: wsfulton
+ SWIG no longer generates a wrapper for a class' constructor if that class has
+ any base class with a private destructor. This is because your compiler should
+ not allow a class to be instantiated if a base has a private destructor. Some
+ compilers do, so if you need the old behaviour, use the "notabstract" feature, eg:
+
+ %feature("notabstract") Derived;
+ class Base {
+ ~Base() {}
+ };
+ struct Derived : Base {};
+
+Version 3.0.6 (5 Jul 2015)
+==========================
+
+2015-07-02: wsfulton
+ Fix syntax error when the template keyword is used in types, eg:
+
+ std::template vector<int> v;
+
+2015-07-02: ngladitz
+ [Lua] Push characters as unformatted 1-character strings to avoid
+ unprintable characters such as (char)127 being converted to
+ "<\127>" with Lua 5.3 and later. (github PR #452)
+
+2015-06-29: olly
+ [Python] Improve handling of whitespace in %pythoncode.
+
+ Previously SWIG looked at the indentation of the first line and
+ removed that many characters from each subsequent line, regardless
+ of what those characters were. This was made worse because SWIG's
+ preprocessor removes any whitespace before a '#'. Fixes github
+ issue #379, reported by Joe Orton.
+
+2015-06-12: wsfulton
+ [R] Fix #430 - call to SWIG_createNewRef in copyToC was incorrectly named.
+
+2015-06-11: sghirate
+ [C#] Patch #427 adds in new command line option -outfile to combine all the
+ generated C# code into a single file.
+
+2015-06-09: wsfulton
+ Fix seg fault processing C++11 type aliasing. Issue #424.
+
+2015-05-28: wsfulton
+ [Python] Add new feature "python:cdefaultargs" to control default argument
+ code generation. By default, SWIG attempts to convert C/C++ default argument values
+ into Python values and generates code into the Python layer with these values.
+ Recent versions of SWIG are able to convert more of these values, however, the
+ new behaviour can be circumvented if desired via this new feature, such that
+ the default argument values are obtained from the C layer and not the Python layer.
+ For example:
+
+ struct CDA {
+ int fff(int a = 1, bool b = false);
+ };
+
+ The default code generation in the Python layer is:
+
+ class CDA(_object):
+ ...
+ def fff(self, a=1, b=False):
+ return _default_args.CDA_fff(self, a, b)
+
+ Adding the feature:
+
+ %feature("python:cdefaultargs") CDA::fff;
+
+ Results in:
+
+ class CDA(_object):
+ ...
+ def fff(self, *args):
+ return _default_args.CDA_fff(self, *args)
+
+ Some code generation modes, eg -builtin and -fastproxy, are unaffected by this as
+ the default values are always obtained from the C layer.
+
+2015-05-27: wsfulton
+ [Python] Deal with an integer as the default value of a typedef to bool
+ parameter in the C++ prototype. See #327. Regression from 3.0.0 onwards.
+
+2015-05-19: olly
+ [Python] Fix warning when compiling generated code with MSVC.
+ (Fixes https://sourceforge.net/p/swig/patches/351/ reported by
+ Mateusz Szyma�ski).
+
+2015-05-14: wsfulton
+ Fix seg fault wrapping shared_ptr of classes with private constructors and destructors.
+ This also fixes the "unref" feature when used on classes with private destructors.
+
+2015-05-10: wsfulton
+ [Java] Fix multi-argument typemaps (char *STRING, size_t LENGTH)
+ so that they can be applied to a wider range of types. Fixes #385.
+
+2015-05-07: olly
+ [Python] Deal with an integer as the default value of a bool
+ parameter in the C++ prototype. Fixes github #327, reported by
+ Greg Allen.
+
+2015-05-07: LindleyF
+ [Java] Allow feature("director") and feature("ref") to be used
+ together. Github PR#403.
+
+2015-05-05: olly
+ Suppress warning 325 "Nested class not currently supported (Foo
+ ignored)" when Foo has already been explicitly ignored with "%ignore".
+
+2015-05-04: wsfulton
+ Add support for friend templates, including operator overloading - fixes #196. Considering
+ the example below, previously the operator gave a syntax error and friendfunc incorrectly
+ warned with:
+
+ "Warning 503: Can't wrap 'friendfunc<(Type)>' unless renamed to a valid identifier."
+
+ template <class Type> class MyClass {
+ friend int friendfunc <Type>(double is, MyClass <Type> & x);
+ friend int operator<< <Type>(double un, const MyClass <Type> &x);
+ };
+
+ The following also previously incorrectly warned with:
+
+ "Warning 302: Identifier 'template_friend' redefined (ignored),"
+
+ template<typename T> T template_friend(T);
+ struct MyTemplate {
+ template<typename T> friend T template_friend(T);
+ };
+
+2015-05-01: wsfulton
+ Fix handling of conversion operators where the operator is split over multiple
+ lines or has comments within the operator type. Fixes #401.
+
+ Also fix similar problem with normal operators which gave a syntax error if split over
+ multiple lines or had a comment within the operator declaration.
+
+2015-04-30: olly
+ Ignore unknown preprocessor directives which are inside an inactive
+ conditional (github issue #394, reported by Dan Wilcox).
+ Regression introduced in 3.0.3.
+
+2015-04-27: vadz
+ [Python] Fix "default" typemap used after an argument with "numinputs=0" (#377).
+
+2015-04-24: wsfulton
+ [Python] Fix #256. Code generated with '-builtin -modernargs' segfaults for any
+ method taking zero arguments.
+
+ Also fixes: "SystemError: error return without exception set" during error checking
+ when using just -builtin and the incorrect number of arguments is passed to a class
+ method expecting zero arguments.
+
+2015-04-23: wsfulton
+ [Java] Bug #386 - Memory leak fix in (char *STRING, size_t LENGTH) typemaps.
+
+2015-04-23: vadz
+ [Python] Make "default" typemap work again (#330, #377).
+
+2015-04-23: vadz
+ [Python] Fix the use of default values for the pointer types (#365, #376).
+
+2015-04-23: wsfulton
+ Fix 'make check-ccache' which is part of 'make check' when one of the CCACHE_
+ environment variables, for example CCACHE_DISABLE, is set.
+
+2015-04-14: wsfulton
+ Clearer warning message for badly constructed typecheck typemaps. For example, was:
+
+ example.i:3: Warning 467: Overloaded foo(int) not supported (no type checking
+ rule for 'int').
+
+ Now:
+
+ example.i:3: Warning 467: Overloaded foo(int) not supported (incomplete type checking
+ rule - no precedence level in typecheck typemap for 'int').
+
+2015-04-11: wsfulton
+ [Java] Fix #353 - Linker multiple definition of 'ExceptionMatches' when
+ using directors and multiple modules.
+
+2015-04-11: wsfulton
+ Merge #320 - Make __dict__ accessible for Python builtin classes.
+
+2015-04-07: wsfulton
+ Fix #375 - parsing of extern "C" and typedef for example:
+ extern "C" typedef void (*Hook2_t)(int, const char *);
+ extern "C" typedef int Integer;
+
+2015-03-12: olly
+ -DSWIG_DIRECTOR_STATIC is now supported for all languages with
+ director support, not only Python and PHP.
+
+2015-03-02: ianlancetaylor
+ [Go] Add -cgo option, required for Go versions 1.5 and
+ later.
+
+2015-02-26: olly
+ Fix segmentation fault when top==NULL, introduced by nested class
+ handling (reported in issue#346 by Pawe� Tomulik).
+
+2015-02-09: wsfulton
+ [Guile] Fix generated code for static const char member variables when
+ defined and declared inline.
+
+2015-02-09: mishas
+ [Go] Fix %import of files in sub directories.
+
+2015-02-05: ianlancetaylor
+ [Go] Ignore Go specific type maps (goin, goout, etc.) if they are empty.
+
+2015-02-05: ianlancetaylor
+ [Go] Generated Go code no longer calls _swig_goallocate or
+ _swig_makegostring, as they will no longer work as of Go 1.5.
+
+Version 3.0.5 (31 Jan 2015)
+===========================
+
+2015-01-30: wsfulton
+ [Python] Fix Python -classic and property setting. Setting properties on classic classes
+ was broken in swig-3.0.3 by attempting to use __setattr__. This regression is fixed now
+ by using __dict__ again when using -classic.
+ Fixes patch #232.
+
+2015-01-27: smarchetto
+ [Scilab] Support for the Scilab language has been added
+
+2015-01-23: olly
+ [PHP] When wrapping a returned resource as an object, check if all
+ cases wrap it in the same class, and if so eliminate the pointless
+ switch statement wrapper we previously generated.
+
+2015-01-22: wsfulton
+ [Octave] Merge patch #297 for SF bug #1277 - Octave shared_ptr support
+
+2015-01-15: wsfulton
+ [Python] Merge patch #250 - Fixes for using %constant and objects (non-primitive types)
+
+2015-01-15: wsfulton
+ [C# Go] Merge patch #308 and fix #307 - C++11 strongly typed enum support
+ in directors
+
+2015-01-15: wsfulton
+ [Python] Second fix for #294 #296 - Regression introduced in SWIG-3.0.3 when
+ wrapping functions with default arguments, this time when using kwargs.
+
+Version 3.0.4 (14 Jan 2015)
+===========================
+
+2015-01-12: olly
+ [PHP] Fix segfault in director upcall check when using PHP built with
+ ZTS enabled. Fixes #155, reported by Pierre Labastie.
+
+2015-01-12: vadz
+ [Python] Fix #294 #296 - Regression introduced in SWIG-3.0.3 when
+ wrapping functions with default arguments. Invalid or missing default
+ arguments were sometimes being generated into the python layer.
+
+2015-01-08: olly
+ Allow C++11 "explicit constexpr". Fixes github issue #284 reported
+ by Pawel Tomulik. Also handle "constexpr explicit" and "constexpr
+ static".
+
+2015-01-08: olly
+ When reporting an error for a construct which hasn't been
+ terminated when the end of the file is reached, report it at the
+ start line rather than "EOF" as then tools like editors and IDEs
+ will take you to a generally more useful place for fixing the
+ problem.
+
+2015-01-08: olly
+ Improve error messages for a few cases which previously gave the
+ one of the cryptic catch-all errors "Syntax error in input".
+
+2015-01-08: olly
+ Provide -cppext as a general command line option for setting the
+ extension used for generated C++ files (previously it was specific
+ to the PHP backend). Deprecate the equivalent -suffix option
+ provided by the Ocaml backend, but continue to support that for
+ now.
+
+Version 3.0.3 (30 Dec 2014)
+===========================
+
+2014-12-27: wsfulton
+ Fix #280 - abort using all default template parameters within other template
+ parameters.
+
+2014-12-27: talby
+ [Perl] Issue #282 perl5 archlib vs archlibexp
+ [Perl] tidy "warning: duplicate 'extern' declaration specifier" when building generated code
+ under clang
+
+2014-12-18: wsfulton
+ Add support for %constant and structs/classes - issue #272
+
+2014-12-09: wsfulton
+ Fix #245 - regression (since swig-3.0.0) in templated constructors.
+ Templated constructors could not be instantiated - they were incorrectly ignored with a warning 504:
+ "Function: xyz must have a return type. Ignored."
+
+2014-12-07: wsfulton
+ Add support for C++11 strongly typed enumerations.
+
+2014-11-21: wsfulton
+ [Java C#] Fix multiply defined error when using %rename of enum items when using the "simple enum"
+ wrappers.
+
+2014-10-28: vadz
+ [Python] Patch #201 The generated .py file no longer uses *args for all Python parameters.
+ Instead, the parameters are named using the C++ parameter names.
+
+ "compactdefaultargs" feature can be enabled to restore the old behaviour.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-10-24: timotheecour
+ [D] Patch #204 Use core.atomic.atomicOp to mutate shared variables
+
+2014-10-21: wsfulton
+ Fix issue #242 - Use of the "kwargs" feature no longer automatically turns on the
+ "compactdefaultargs" feature if the target language does not support kwargs.
+ This change affects all languages except Python and Ruby.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-10-10: diorcety
+ [Python] Patch #232 Fix property access using directors
+
+2014-10-06: wsfulton
+ [Python] Fixes when using -builtin and std::vector/std::list wrappers to allow deletion
+ of single elements, such as 'del vec[0]'.
+
+2014-09-30: oliverb
+ [Javascript] Merge patch #216 by Richie765 - Added support for many versions of v8 javascript.
+
+2014-09-30: oliverb
+ [Javascript] Merge patch #195 by zittix - Fixed JSClassRef declaration not using the static one.
+
+2014-09-30: ianlancetaylor
+ [Go] In configure script, require Go 1.1 or later.
+
+2014-09-30: wsfulton
+ [Python] Patch #207 - Fix No module error with -relativeimport when using single
+ header file import.
+
+2014-09-27: wsfulton
+ Patch #208 - Initialise newly created array when using array_functions in the
+ carrays.i library (C++ usage).
+
+2014-09-27: wsfulton
+ [Ruby] Patch #187 - Fix crash on shutdown of the Ruby interpreter if more than one
+ module was loaded at a time when data is being shared between modules.
+
+2014-09-27: wsfulton
+ [Java] Patch #168 - Fix leak in Java director string handling after the Java
+ upcall when called from a native thread.
+
+2014-09-25: ianlancetaylor
+ [Go] Adjust generated code to work with upcoming Go 1.4
+ release.
+
+2014-09-23: wsfulton
+ [Python] Add patch from Thomas Maslach to fix crash in wrappers when using -threads in
+ the STL iterators (SwigPyIterator destructor).
+
+2014-09-17: wsfulton
+ [C#] Merge patch #229 from contre - Add bool array types to arrays_csharp.i
+
+2014-09-12: olly
+ [PHP] Add support for specifying any PHP interfaces a wrapped class
+ implements, e.g.: %typemap("phpinterfaces") MyIterator "Iterator"
+
+2014-09-11: olly
+ [PHP] Fix throwing a PHP exception through C++ from a subclassed
+ director method - PHP NULL gets returned by the subclassed method
+ in this case, so the directorout typemap needs to allow that (at
+ least if an exception is active).
+
+2014-09-09: ianlancetaylor
+ [Go] Add goargout typemap.
+
+2014-09-09: olly
+ [PHP] Fix segmentation faults with directors in PHP >= 5.4, and
+ reenable runme tests for director_basic testcase. Fix from
+ pavel-charvat in issue#164.
+
+2014-09-05: ianlancetaylor
+ [Go] Add imtype, goin, goout, godirectorin, and
+ godirectorout typemaps, to support writing Go code to
+ convert between types.
+
+2014-09-02: olly
+ [Python] Fix regression in indentation of python code produced with
+ -modern, introduced by changes in #188. Reported by fabiencastan
+ in #218.
+
+2014-09-01: olly
+ Issue an error for unknown SWIG preprocessor directives, rather
+ than quietly ignoring them. Reported by jrhelsey in issue#217.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-08-15: talby
+ [Perl] Include guard fix for nested modules from Anthony Heading (SF Patch #350).
+
+2014-08-04: wsfulton
+ [C#] Merge patch #200 from gpetrou - Changed CSharp license header to include auto-generated
+ tag so that StyleCop ignores the files.
+
+2014-08-04: wsfulton
+ [Java] Merge patch #198 from Yuval Kashtan - Support for java.nio.ByteBuffer mapping to
+ unsigned char * in various.i in NIOBUFFER typemaps.
+
+2014-07-14: ianlancetaylor
+ [Go] Change struct definition to use void *, not uint8, so
+ that the type is recorded as possibly containing
+ pointers. This ensures that the 1.3 garbage collector
+ does not collect pointers passed to C++ code.
+
+2014-07-01: wsfulton
+ Fix SF Bug #1375 - Expansion of the $parentclassname special variable incorrectly contains
+ brackets in the expanded name.
+
+Version 3.0.2 (4 Jun 2014)
+==========================
+
+2014-06-02: v-for-vandal
+ [Lua] Pull request #176:
+ If class has no __eq implemented, then default __eq is generated.
+ Default __eq compares actual pointers stored inside Lua userdata.
+
+2014-06-02: vkalinin
+ Fix #183 - %extend and unnamed nested structs
+
+2014-05-28: kwwette
+ Fix install failure when using an 'out of source' build using the shipped
+ tarball - regression introduced in swig-3.0.1.
+
+2014-05-24: kwwette
+ [Octave] Remove deprecated -global/-noglobal command-line arguments
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+Version 3.0.1 (27 May 2014)
+===========================
+
+2014-05-25: hfalcic
+ [Python] Python 3 byte string output: use errors="surrogateescape"
+ if available on the version of Python that's in use. This allows
+ obtaining the original byte string (and potentially trying a fallback
+ encoding) if the bytes can't be decoded as UTF-8.
+
+ Previously, a UnicodeDecodeError would be raised with no way to treat
+ the data as bytes or try another codec.
+
+2014-05-18: vkalinin
+ Bug #175 - Restore %extend to work for unnamed nested structures by using a C
+ symbol comprising the outer structure name and unnamed variable instance name.
+
+2014-05-15: kwwette
+ Add #166 - 'make check' now works out of source. This required the examples to build
+ out of source. The main languages have been tested - C#, Go, Guile, Java, Javascript,
+ Lua, Octave, Perl, PHP, Python, Ruby and Tcl.
+
+2014-05-01: Oliver Buchtala
+ Javascript support added, see Javascript chapter in the documentation.
+
+2014-05-01: olly
+ [PHP] The generated __isset() method now returns true for read-only properties.
+
+2014-04-24: kwwette
+ [Go] Fix go ./configure parsing of gccgo --version, and
+ goruntime.swg typo in __GNUC_PATCHLEVEL__ (SF Bug #1298)
+
+2014-04-24: kwwette
+ Fix {python|perl5|ruby|tcl}/java examples
+
+ In Lib/gcj/cni.i, for compatibility with newer gcj versions:
+
+ - remove JvAllocObject() which gcj no longer defines, from gcj Changelog:
+ 2004-04-16 Bryce McKinlay <[email protected]>
+ * gcj/cni.h (JvAllocObject): Remove these obsolete,
+ undocumented CNI calls.
+
+ - change JvCreateJavaVM() argument from void* to JvVMInitArgs*, from gcj Changelog:
+ 2005-02-23 Thomas Fitzsimmons <[email protected]>
+ PR libgcj/16923
+ ...
+ (JvCreateJavaVM): Declare vm_args as JvVMInitArgs* rather than void*.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-04-08: wsfulton
+ SF Bug #1366 - Remove duplicate declarations of strtoimax and strtoumax in inttypes.i
+
+2014-04-08: wsfulton
+ [Java C#] Enums which have been ignored via %ignore and are subsequently
+ used are handled slightly differently. Type wrapper classes are now generated
+ which are effectively a wrapper of an empty enum. Previously in Java uncompilable
+ code was generated and in C# an int was used.
+
+2014-04-04: wsfulton
+ Fix regression in 3.0.0 where legal code following an operator<< definition might
+ give a syntax error. SF Bug #1365.
+
+2014-04-03: olly
+ [PHP] Fix wrapping director constructors with default parameters
+ with a ZTS-enabled build of PHP.
+
+2014-04-02: olly
+ [PHP] Pass the ZTS context we already have to avoid needing to
+ call TSRMLS_FETCH, which is relatively expensive.
+
+2014-04-02: olly
+ [PHP] Pass ZTS context through to t_output_helper() so it works
+ with a ZTS-enabled build of PHP. Reported by Pierre Labastie in
+ github PR#155.
+
+2014-03-28: wsfulton
+ [Java C# D Go] Fixes for C enums used in an API and the definition of the enum
+ has not been parsed. For D, this fixes a segfault in SWIG. The other languages
+ now produce code that compiles, although the definition of the enum is needed
+ in order to use the enum properly from the target language.
+
+2014-03-23: v-for-vandal
+ [Lua] Fix for usage of snprintf in Lua runtime which Visual Studio does not have.
+
+Version 3.0.0 (16 Mar 2014)
+===========================
+
+2014-03-16: wsfulton
+ C++11 support initially developed as C++0x support by Matevz Jekovec as a Google Summer of Code
+ project has been further extended. The C++11 support is comprehensive, but by no means complete
+ or without limitations. Full details for each new feature in C++11 is covered in the
+ CPlusPlus11.html chapter in the documentation which is included in SWIG and also available
+ online at https://www.swig.org/Doc3.0/CPlusPlus11.html.
+
+2014-03-14: v-for-vandal
+ [Lua] Numerous Lua improvements:
+ 1. %nspace support has been added. Namespaces are mapped to tables in the module, with the same
+ name as the C++ namespace.
+ 2. Inheritance is now handled differently. Each class metatable keeps a list of class bases instead
+ of merging all members of all bases into the derived class.
+ 3. The new metatables result in differences in accessing class members. For example:
+
+ %module example
+ struct Test {
+ enum { TEST1 = 10, TEST2 = 20 };
+ static const int ICONST = 12;
+ };
+
+ Now this can be used as follows:
+ print(example.Test.TEST1)
+ print(example.Test.ICONST)
+ The old way was:
+ print(example.Test_TEST1)
+ print(example.Test_ICONST)
+
+ 4. The special class metatable member ".constructor" was removed. Now SWIG generates the proxy
+ function by itself and assigns it directly to the class table "__call" method.
+ 5. eLua should also now support inheritance.
+ 6. 'const' subtable in eLua is considered deprecated.
+
+ Changes in behaviour:
+ a. You can no longer assign to non-existing class members in classes without a __setitem__ method.
+ It will cause a Lua error.
+ b. You can no longer iterate over a module table and copy everything into the global namespace.
+ Actually, this was never the case, but it is now explicitly prohibited.
+ c. Now changing a base class will immediately affect all derived classes.
+ d. There might be some issues with inheritance. Although the bases iteration scheme is the same
+ as was used for merging base classes into derived one, some unknown issues may arise.
+
+ The old metatable behaviour can be restored by using the -no-old-metatable-bindings option.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-03-06: wsfulton
+ [Python] Change in default behaviour wrapping C++ bool. Only a Python True or False
+ will now work for C++ bool parameters. This fixes overloading bool with other types.
+ Python 2.3 minimum is now required for wrapping bool.
+
+ When wrapping:
+
+ const char* overloaded(bool value) { return "bool"; }
+ const char* overloaded(int value) { return "int"; }
+
+ Previous behaviour:
+ >>> overloaded(False)
+ 'int'
+ >>> overloaded(True)
+ 'int'
+ >>> overloaded(0)
+ 'int'
+
+ Now we get the expected behaviour:
+ >>> overloaded(False)
+ 'bool'
+ >>> overloaded(0)
+ 'int'
+
+ The consequence is when wrapping bool in non-overloaded functions:
+
+ const char* boolfunction(bool value) { return value ? "true" : "false"; }
+
+ The previous behaviour was very Pythonic:
+ >>> boolfunction("")
+ 'false'
+ >>> boolfunction("hi")
+ 'true'
+ >>> boolfunction(12.34)
+ 'true'
+ >>> boolfunction(0)
+ 'false'
+ >>> boolfunction(1)
+ 'true'
+
+ Now the new behaviour more along the lines of C++ due to stricter type checking. The
+ above calls result in an exception and need to be explicitly converted into a bool as
+ follows:
+ >>> boolfunction(0)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ TypeError: in method 'boolfunction', argument 1 of type 'bool'
+ >>> boolfunction(bool(0))
+ 'false'
+
+ The old behaviour can be resurrected by passing the -DSWIG_PYTHON_LEGACY_BOOL command line
+ parameter when executing SWIG. Typemaps can of course be written to customise the behaviour
+ for specific parameters.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-03-06: wsfulton
+ Fix SF Bug #1363 - Problem with method overloading when some methods are added by %extend
+ and others are real methods and using template default parameters with smart pointers.
+ This is noticeable as a regression since 2.0.12 when using the default smart pointer
+ handling for some languages when the smart pointer wraps std::map and other STL containers.
+
+2014-03-02: wsfulton
+ [Python] SF Patch #346 from Jens Krueger. Correct exception thrown attempting to
+ access a non-existent C/C++ global variable on the 'cvar' object. The exception thrown
+ used to be a NameError. However, as this access is via a primary, an AttributeError
+ is more correct and so the exception thrown now is an AttributeError. Reference:
+ http://docs.python.org/2/reference/expressions.html#attribute-references
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-03-01: wsfulton
+ [Python] Patch #143 Fix type shown when using type() to include the module and package
+ name when using -builtin.
+
+2014-03-01: wsfulton
+ [Python] SF patch #347 Fix missing argument count checking with -modern.
+ Fixes regression introduced when builtin changes were introduced in SWIG-2.0.3.
+
+2014-02-21: wsfulton
+ [PHP] Fix warning suppression using %warnfilter for PHP reserved class names.
+
+2014-02-19: olly
+ [Lua] Add keyword warnings for Lua keywords and Basic Functions.
+
+2014-02-19: olly
+ -Wallkw now includes keywords for all languages with keyword
+ warnings (previously Go and R were missing).
+
+2014-02-19: olly
+ [PHP] Update the lists of PHP keywords with new ones from PHP 5.4
+ and newer (and some missing ones from 5.3). Reserved PHP constants
+ names are now checked against enum values and constants, instead
+ of against function and method names. Built-in PHP function names
+ no longer match methods added by %extend. Functions and methods
+ named '__sleep', '__wakeup', 'not', 'parent', or 'virtual' are no
+ longer needlessly renamed.
+
+2014-02-15: wsfulton
+ Fix the %$ismember %rename predicates to also apply to members added via %extend.
+
+ Add %$isextendmember for %rename of members added via %extend. This can be used to
+ distinguish between normal class/struct members and %extend members. For example
+ '%$ismember, %$not %$isextendmember' will now identify just class/struct members.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-02-16: hfalcic
+ [Python] Patch #137 - fix crashes/exceptions in exception handling in Python 3.3
+
+2014-02-15: wsfulton
+ [Java] Add support for the cdata library.
+
+2014-02-08: vkalinin
+ Nested class support added. This primarily allows SWIG to properly parse nested
+ classes and keep the nested class information in the parse tree. Java and C#
+ have utilised this information wrapping the C++ nested classes as Java/C#
+ nested classes. The remaining target languages ignore nested classes as in
+ previous versions. Help is needed by users of these remaining languages to
+ design how C++ nested classes can be best wrapped. Please talk to us on the
+ swig-devel mailing list if you think you can help.
+
+ Previously, there was limited nested class support. Nested classes were treated
+ as opaque pointers. However, the "nestedworkaround" feature provided a way to
+ wrap a nested class as if it was a global class. This feature no longer exists
+ and is replaced by the new "flatnested" feature. This effectively does the same
+ thing with less manual code to be written. Please see the 'Nested classes'
+ section in the documentation in SWIGPlus.html if you were previously using this
+ feature.
+
+ SWIG now parses the contents of nested classes where previously it did not. You
+ may find that you will need to make adjustments to your interface file as
+ effectively extra code is being wrapped.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2014-02-06: gjanssens
+ [Guile] Patch #133. Make scm to string conversion work with non-ascii strings.
+ Guile 2 has a completely rewritten string implementation. SWIG made some assumptions
+ that are no longer valid as to the internals of guile's string representation.
+
+2014-01-30: wsfulton
+ [C#] Add new swigtype_inout.i library containing SWIGTYPE *& OUTPUT typemaps.
+
+ Example usage wrapping:
+
+ void f(XXX *& x) { x = new XXX(111); }
+
+ would be:
+
+ XXX x = null;
+ f(out x);
+ // use x
+ x.Dispose(); // manually clear memory or otherwise leave out and leave it to the garbage collector
+
+2014-01-21: ianlancetaylor
+ [Go] Add %go_import directive.
+
+2014-01-21: ianlancetaylor
+ [Go] Add support for Go 1.3, not yet released.
+
+2014-01-20: wsfulton
+ Director exceptions (Swig::DirectorException) now derive from std::exception
+ and hence provide the what() method. In Python and Ruby, this replaces the now
+ deprecated DirectorException::getMessage() method.
+
+2014-01-14: diorcety
+ Patch #112 - Fix symbol resolution involving scopes that have multiple levels
+ of typedefs - fixes some template resolutions as well as some typemap searches.
+
+2014-01-11: wsfulton
+ Fix and document the naturalvar feature override behaviour - the naturalvar
+ feature attached to a variable name has precedence over the naturalvar
+ feature attached to the variable's type. The overriding was not working
+ when turning the feature off on the variable's name.
+
+ Fix so that any use of the naturalvar feature will override the global
+ setting. Previously when set globally by -naturalvar or %module(naturalvar=1),
+ use of the naturalvar feature was not always honoured.
+
+2014-01-06: ianlancetaylor
+ [Go] Fix bug that broke using directors from a thread not
+ created by Go.
+
+2013-12-24: ptomulik
+ [Python] SF Bug #1297
+
+ Resolve several issues related to python imports.
+ For example, it's now possible to import modules having the same module
+ names, but belonging in different packages.
+
+ From the user's viewpoint, this patch gives a little bit more control on
+ import statements generated by SWIG. The user may choose to use relative
+ or absolute imports.
+
+ Some details:
+ - we (still) generate import statements in the form 'import a.b.c' which
+ corresponds to absolute imports in python3 and (the only available)
+ ambiguous one in python2.
+ - added -relativeimport option to use explicit relative import syntax
+ (python3),
+
+ The "Python Packages" section in the documentation discusses how to work
+ with importing packages including the new -relativeimport command line option.
+
+2013-12-23: vadz
+ [Octave, Perl, Python, R, Ruby, Tcl] Change the length of strings created from fixed-size char
+ buffers in C code.
+
+ This is a potential backwards compatibility break: a "char buf[5]" containing "ho\0la" was
+ returned as a string of length 5 before, but is returned as a string of length 2 now. Also,
+ it was possible to assign a (non-NUL-terminated) string "hello" to such a buffer before but
+ now this fails and only "helo" can fit.
+
+ Apply "char FIXSIZE[ANY]" typemaps to explicitly choose the old behaviour.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2013-12-23: talby
+ [Perl] Add support for directors.
+
+2013-12-18: ianlancetaylor
+ [Go] Don't require that Go environment variables be set
+ when running examples or testsuite when using Go 1 or
+ later.
+
+2013-12-17: ianlancetaylor
+ [Go] Remove -longsize option (for backward compatibility,
+ ignore it if seen).
+
+2013-12-17: ianlancetaylor
+ [Go] Add -go-pkgpath option.
+
+2013-12-16: ianlancetaylor
+ [Go] Update for Go 1.2 release. Add support for linking
+ SWIG code directly into executable, rather than using a
+ shared library.
+
+2013-12-13: ianlancetaylor
+ [Go] Add SWIG source file name as comments in generated
+ files. This can be used by Go documentation tools.
+
+2013-12-12: jleveque
+ [Lua] Fix typo (wchar instead of wchar_t) which made wchar.i
+ for Lua useless.
+
+2013-12-12: vmiklos
+ [PHP] PHP's peculiar call-time pass-by-reference feature was
+ deprecated in PHP 5.3 and removed in PHP 5.4, so update the REF
+ typemaps in phppointers.i to specify pass-by-reference in the
+ function definition. Examples/php/pointer has been updated
+ accordingly.
+
+2013-12-12: olly
+ [PHP] The usage of $input in PHP directorout typemaps has been
+ changed to be consistent with other languages. The typemaps
+ provided by SWIG have been updated accordingly, but if you
+ have written your own directorout typemaps, you'll need to
+ update $input to &$input (or make equivalent changes).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2013-11-27: vadz
+ [C#, Java, Python] Add std_auto_ptr.i defining typemaps for returning std::auto_ptr<>.
+
+2013-11-09: wsfulton
+ [C#] Apply patch #79 from Brant Kyser
+ - Remove using directives from the generated C# code and fully qualify the use of all .NET
+ framework types in order to minimize potential name collisions from input files defining
+ types, namespace, etc with the same name as .NET framework members.
+ - Globally qualify the use of .NET framework types in the System namespace
+ - Remove .NET 1.1 support, .NET 2 is the minimum for the C# module
+
+ This is a potential backwards compatibility break if code has been added relying on these using
+ statements that used to be generated:
+
+ using System;
+ using System.Runtime.InteropServices;
+
+ The quick fix to add these back in is to add the -DSWIG2_CSHARP command line option when
+ executing SWIG. See CSharp.html documentation for more info.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2013-11-05: wsfulton
+ [Java] Fix some corner cases for the $packagepath/$javaclassname special variable substitution.
+
+2013-11-05: wsfulton
+ [Java] Apply patch #91 from Marvin Greenberg - Add director:except feature for improved
+ exception handling in director methods for Java.
+
+2013-10-15: vadz
+ Allow using \l, \L, \u, \U and \E in the substitution part of %(regex:/pattern/subst/)
+ inside %rename to change the case of the text being replaced.
+
+2013-10-12: wsfulton
+ [CFFI] Apply #96 - superclass not lispify
+
+2013-10-12: wsfulton
+ Merge in C++11 support from the gsoc2009-matevz branch where Matevz Jekovec first
+ started the C++0x additions. Documentation of the C++11 features supported is in a
+ new Chapter of the documentation, "SWIG and C++11" in Doc/Manual/CPlusPlus11.html.
+
+2013-10-04: wsfulton
+ Fix %naturalvar not having any affect on templated classes instantiated with an
+ enum as the template parameter type. Problem reported by Vadim Zeitlin.
+
+2013-09-20: wsfulton
+ [Java] Fix a memory leak for the java char **STRING_ARRAY typemaps.
+
+Version 2.0.12 (9 Feb 2014)
+===========================
+
+2014-01-16: wsfulton
+ [PHP] Fix compilation error in ZTS mode (64 bit windows) due to incorrect placement
+ of TSRMLS_FETCH() in SWIG_Php_GetModule() as reported by Mark Dawson-Butterworth.
+
+2014-01-13: kwwette
+ [Octave] update support to Octave version 3.8.0
+
+ - Octave 3.8.0 no longer defines OCTAVE_API_VERSION_NUMBER, but 3.8.1
+ will define OCTAVE_{MAJOR,MINOR,PATCH}_VERSION instead: see
+ http://hg.savannah.gnu.org/hgweb/octave/rev/b6b6e0dc700e
+ So we now use a new macro SWIG_OCTAVE_PREREQ(major,minor,patch) to
+ enable features requiring Octave version major.minor.patch or later.
+
+ For Octave versions prior to 3.8.1, we reconstruct values for
+ OCTAVE_{MAJOR,MINOR,PATCH}_VERSION based on OCTAVE_API_VERSION_NUMBER,
+ extracted from Octave's ChangeLogs. An additional hack is needed to
+ distinguish between Octave <= 3.2.x and 3.8.0, neither of which define
+ OCTAVE_API_VERSION_NUMBER.
+
+ - Octave 3.8.0 deprecates symbol_table::varref(), so remove its use
+ for this and future versions of Octave.
+
+ - Octave 3.8.0 removes octave_value::is_real_nd_array(), used in
+ octave_swig_type::dims(). Its use is not required here, so remove it.
+
+ - Retested against Octave versions 3.0.5, 3.2.4, 3.4.3, 3.6.4, and 3.8.0.
+
+ - Updated Octave documentation with tested Octave versions, and added a
+ warning against using versions <= 3.x.x, which are no longer tested.
+
+2013-12-22: wsfulton
+ C++11 support for new versions of erase and insert in the STL containers.
+
+ The erase and insert methods in the containers use const_iterator instead
+ of iterator in C++11. There are times when the methods wrapped must match
+ the parameters exactly. Specifically when full type information for
+ template types is missing or SWIG fails to look up the type correctly,
+ for example:
+
+ %include <std_vector.i>
+ typedef float Real;
+ %template(RealVector) std::vector<Real>;
+
+ SWIG does not find std::vector<Real>::iterator because %template using
+ typedefs does not always work and so SWIG doesn't know if the type is
+ copyable and so uses SwigValueWrapper<iterator> which does
+ not support conversion to another type (const_iterator). This resulted
+ in compilation errors when using the C++11 version of the containers.
+
+ Closes #73
+
+2013-10-17: wsfulton
+ [R] Fix SF #1340 - Visual Studio compile error in C++ wrappers due to #include <exception>
+ within extern "C" block.
+
+2013-10-17: wsfulton
+ [Python] Fix SF #1345 - Missing #include <stddef.h> for offsetof when using -builtin.
+
+2013-10-12: wsfulton
+ [Lua] Apply #92 - missing return statements for SWIG_Lua_add_namespace_details()
+ and SWIG_Lua_namespace_register().
+
+Version 2.0.11 (15 Sep 2013)
+============================
+
+2013-09-15: wsfulton
+ [R] Fix attempt to free a non-heap object in OUTPUT typemaps for:
+ unsigned short *OUTPUT
+ unsigned long *OUTPUT
+ signed long long *OUTPUT
+ char *OUTPUT
+ signed char*OUTPUT
+ unsigned char*OUTPUT
+
+2013-09-12: wsfulton
+ [Lua] Pull Git patch #62.
+ 1) Static members and static functions inside class can be accessed as
+ ModuleName.ClassName.FunctionName (MemberName respectively). Old way such as
+ ModuleName.ClassName_FunctionName still works.
+ 2) Same goes for enums inside classes: ModuleName.ClassName.EnumValue1 etc.
+
+2013-09-12: wsfulton
+ [UTL] Infinity is now by default an acceptable value for type 'float'. This fix makes
+ the handling of type 'float' and 'double' the same. The implementation requires the
+ C99 isfinite() macro, or otherwise some platform dependent equivalents, to be available.
+
+ Users requiring the old behaviour of not accepting infinity, can define a 'check' typemap
+ wherever a float is used, such as:
+
+ %typemap(check,fragment="<float.h>") float, const float & %{
+ if ($1 < -FLT_MAX || $1 > FLT_MAX) {
+ SWIG_exception_fail(SWIG_TypeError, "Overflow in type float");
+ }
+ %}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2013-08-30: wsfulton
+ [Lua] Pull Git patch #81: Include Lua error locus in SWIG error messages.
+ This is standard information in Lua error messages, and makes it much
+ easier to find bugs.
+
+2013-08-29: wsfulton
+ Pull Git patch #75: Handle UTF-8 files with BOM at beginning of file. Was giving an
+ 'Illegal token' syntax error.
+
+2013-08-29: wsfulton
+ [C#] Pull Git patch #77: Allow exporting std::map using non-default comparison function.
+
+2013-08-28: wsfulton
+ [Python] %implicitconv is improved for overloaded functions. Like in C++, the methods
+ with the actual types are considered before trying implicit conversions. Example:
+
+ %implicitconv A;
+ struct A {
+ A(int i);
+ };
+ class CCC {
+ public:
+ int xx(int i) { return 11; }
+ int xx(const A& i) { return 22; }
+ };
+
+ The following python code:
+
+ CCC().xx(-1)
+
+ will now return 11 instead of 22 - the implicit conversion is not done.
+
+2013-08-23: olly
+ [Python] Fix clang++ warning in generated wrapper code.
+
+2013-08-16: wsfulton
+ [Python] %implicitconv will now accept None where the implicit conversion takes a C/C++ pointer.
+ Problem highlighted by Bo Peng. Closes SF patch #230.
+
+2013-08-07: wsfulton
+ [Python] SF Patch #326 from Kris Thielemans - Remove SwigPyObject_print and SwigPyObject_str and
+ make the generated wrapper use the default python implementations, which will fall back to repr
+ (for -builtin option).
+
+ Advantages:
+ - it avoids the swig user having to jump through hoops to get print to work as expected when
+ redefining repr/str slots.
+ - typing the name of a variable on the python prompt now prints the result of a (possibly redefined)
+ repr, without the swig user having to do any extra work.
+ - when redefining repr, the swig user doesn't necessarily have to redefine str as it will call the
+ redefined repr
+ - the behaviour is exactly the same as without the -builtin option while requiring no extra work
+ by the user (aside from adding the %feature("python:slot...) statements of course)
+
+ Disadvantage:
+ - default str() will give different (but clearer?) output on swigged classes
+
+2013-07-30: wsfulton
+ [Python, Ruby] Fix #64 #65: Missing code in std::multimap wrappers. Previously an instantiation
+ of a std::map was erroneously required in addition to an instantiation of std::multimap with the
+ same template parameters to prevent compilation errors for the wrappers of a std::multimap.
+
+2013-07-14: joequant
+ [R] Change types file to allow for SEXP return values
+
+2013-07-05: wsfulton
+ [Python] Add %pythonbegin directive which works like %pythoncode, except the specified code is
+ added at the beginning of the generated .py file. This is primarily needed for importing from
+ __future__ statements required to be at the very beginning of the file. Example:
+
+ %pythonbegin %{
+ from __future__ import print_function
+ print("Loading", "Whizz", "Bang", sep=' ... ')
+ %}
+
+2013-07-01: wsfulton
+ [Python] Apply SF patch #340 - Uninitialized variable fix in SWIG_Python_NonDynamicSetAttr
+ when using -builtin.
+
+2013-07-01: wsfulton
+ [Python, Ruby, Ocaml] Apply SF patch #341 - fix a const_cast in generated code that was generating
+ a <:: digraph when using the unary scope operator (::) (global scope) in a template type.
+
+2013-07-01: wsfulton
+ [Python] Add SF patch #342 from Christian Delbaere to fix some director classes crashing on
+ object deletion when using -builtin. Fixes SF bug #1301.
+
+2013-06-11: wsfulton
+ [Python] Add SWIG_PYTHON_INTERPRETER_NO_DEBUG macro which can be defined to use the Release version
+ of the Python interpreter in Debug builds of the wrappers. The Visual Studio .dsp example
+ files have been modified to use this so that Debug builds will now work without having
+ to install or build a Debug build of the interpreter.
+
+2013-06-07: wsfulton
+ [Ruby] Git issue #52. Fix regression with missing rb_complex_new function for Ruby
+ versions prior to 1.9 using std::complex wrappers if just using std::complex as an output type.
+ Also fix the Complex helper functions external visibility (to static by default).
+
+2013-06-04: olly
+ [PHP] Fix SWIG_ZTS_ConvertResourcePtr() not to dereference NULL
+ if the type lookup fails.
+
+Version 2.0.10 (27 May 2013)
+============================
+
+2013-05-25: wsfulton
+ [Python] Fix Python 3 inconsistency when negative numbers are passed
+ where a parameter expects an unsigned C type. An OverFlow error is
+ now consistently thrown instead of a TypeError.
+
+2013-05-25: Artem Serebriyskiy
+ SVN Patch ticket #338 - fixes to %attribute macros for template usage
+ with %arg.
+
+2013-05-19: wsfulton
+ Fix ccache-swig internal error bug due to premature file cleanup.
+
+ Fixes SF bug 1319 which shows up as a failure in the ccache tests on
+ Debian 64 bit Wheezy, possibly because ENABLE_ZLIB is defined.
+
+ This is a corner case which will be hit when the maximum number of files
+ in the cache is set to be quite low (-F option), resulting in a cache miss.
+
+2013-05-09: kwwette
+ [Octave] Fix bugs in Octave module loading:
+ - fix a memory leak in setting of global variables
+ - install functions only once, to speed up module loads
+
+2013-04-28: gjanssens
+ [Guile] Updates in guile module:
+ - Add support for guile 2.0
+ - Drop support for guile 1.6
+ - Drop support for generating wrappers using guile's gh interface.
+ All generated wrappers will use the scm interface from now on.
+ - Deprecate -gh and -scm options. They are no longer needed.
+ A warning will be issued when these options are still used.
+ - Fix all tests and examples to have a successful travis test
+
+2013-04-18: wsfulton
+ Apply Patch #36 from Jesus Lopez to add support for $descriptor() special variable macro expansion
+ in fragments. For example:
+
+ %fragment("nameDescriptor", "header")
+ %{
+ static const char *nameDescriptor = "$descriptor(Name)";
+ %}
+
+ which will generate into the wrapper if the fragment is used:
+
+ static const char *nameDescriptor = "SWIGTYPE_Name";
+
+2013-04-18: wsfulton
+ Fix SF Bug #428 - Syntax error when preprocessor macros are defined inside of enum lists, such as:
+
+ typedef enum {
+ eZero = 0
+ #define ONE 1
+ } EFoo;
+
+ The macros are silently ignored.
+
+2013-04-17: wsfulton
+ [C#] Pull patch #34 from BrantKyser to fix smart pointers in conjunction with directors.
+
+2013-04-15: kwwette
+ [Octave] Fix bugs in output of cleanup code.
+ - Cleanup code is now written also after the "fail:" label, so it will be called if
+ a SWIG_exception is raised by the wrapping function, consistent with other modules.
+ - Octave module now also recognises the "$cleanup" special variable, if needed.
+
+2013-04-08: kwwette
+ Add -MP option to SWIG for generating phony targets for all dependencies.
+ - Prevents make from complaining if header files have been deleted before
+ the dependency file has been updated.
+ - Modelled on similar option in GCC.
+
+2013-04-09: olly
+ [PHP] Add missing directorin typemap for char* and char[] which
+ fixes director_string testcase failure.
+
+2013-04-05: wsfulton
+ [Ruby] SF Bug #1292 - Runtime fixes for Proc changes in ruby-1.9 when using STL
+ wrappers that override the default predicate, such as:
+
+ %template(Map) std::map<swig::LANGUAGE_OBJ, swig::LANGUAGE_OBJ, swig::BinaryPredicate<> >;
+
+2013-04-05: wsfulton
+ [Ruby] SF Bug #1159 - Correctly check rb_respond_to call return values to fix some
+ further 1.9 problems with functors and use of Complex wrappers.
+
+2013-04-02: wsfulton
+ [Ruby] Runtime fixes for std::complex wrappers for ruby-1.9 - new native Ruby complex numbers are used.
+
+2013-03-30: wsfulton
+ [Ruby] Fix seg fault when using STL containers of generic Ruby types, GC_VALUE or LANGUAGE_OBJECT,
+ on exit of the Ruby interpreter. More frequently observed in ruby-1.9.
+
+2013-03-29: wsfulton
+ [Ruby] Fix delete_if (reject!) for the STL container wrappers which previously would
+ sometimes seg fault or not work.
+
+2013-03-25: wsfulton
+ [Python] Fix some undefined behaviour deleting slices in the STL containers.
+
+2013-03-19: wsfulton
+ [C#, Java, D] Fix seg fault in SWIG using directors when class and virtual method names are
+ the same except being in different namespaces when the %nspace feature is not being used.
+
+2013-02-19: kwwette
+ Fix bug in SWIG's handling of qualified (e.g. const) variables of array type. Given the typedef
+ a(7).q(volatile).double myarray // typedef volatile double[7] myarray;
+ the type
+ q(const).myarray // const myarray
+ becomes
+ a(7).q(const volatile).double // const volatile double[7]
+ Previously, SwigType_typedef_resolve() produces the type
+ q(const).a(7).q(volatile).double // non-sensical type
+ which would never match %typemap declarations, whose types were parsed correctly.
+ Add typemap_array_qualifiers.i to the test suite which checks for the correct behaviour.
+
+2013-02-18: wsfulton
+ Deprecate typedef names used as constructor and destructor names in %extend. The real
+ class/struct name should be used.
+
+ typedef struct tagEStruct {
+ int ivar;
+ } EStruct;
+
+ %extend tagEStruct {
+ EStruct() // illegal name, should be tagEStruct()
+ {
+ EStruct *s = new EStruct();
+ s->ivar = ivar0;
+ return s;
+ }
+ ~EStruct() // illegal name, should be ~tagEStruct()
+ {
+ delete $self;
+ }
+ }
+
+ For now these trigger a warning:
+
+ extend_constructor_destructor.i:107: Warning 522: Use of an illegal constructor name 'EStruct' in
+ %extend is deprecated, the constructor name should be 'tagEStruct'.
+ extend_constructor_destructor.i:111: Warning 523: Use of an illegal destructor name 'EStruct' in
+ %extend is deprecated, the destructor name should be 'tagEStruct'.
+
+ These %extend destructor and constructor names were valid up to swig-2.0.4, however swig-2.0.5 ignored
+ them altogether for C code as reported in SF bug #1306. The old behaviour of using them has been
+ restored for now, but is officially deprecated. This does not apply to anonymously defined typedef
+ classes/structs such as:
+
+ typedef struct {...} X;
+
+2013-02-17: kwwette
+ When generating functions provided by %extend, use "(void)" for no-argument functions
+ instead of "()". This prevents warnings when compiling with "gcc -Wstrict-prototypes".
+
+2013-02-17: kwwette
+ [Octave] Minor fix to autodoc generation: get the right type for functions returning structs.
+
+2013-02-15: wsfulton
+ Deprecate typedef names used in %extend that are not the real class/struct name. For example:
+
+ typedef struct StructBName {
+ int myint;
+ } StructB;
+
+ %extend StructB {
+ void method() {}
+ }
+
+ will now trigger a warning:
+
+ swig_extend.i:19: Warning 326: Deprecated %extend name used - the struct name StructBName
+ should be used instead of the typedef name StructB.
+
+ This is only partially working anyway (the %extend only worked if placed after the class
+ definition).
+
+2013-02-09: wsfulton
+ [CFFI] Apply patch #22 - Fix missing package before &body
+
+2013-01-29: wsfulton
+ [Java] Ensure 'javapackage' typemap is used as it stopped working from version 2.0.5.
+
+2013-01-28: wsfulton
+ [Python] Apply patch SF #334 - Fix default value conversions "TRUE"->True, "FALSE"->False.
+
+2013-01-28: wsfulton
+ [Java] Apply patch SF #335 - Truly ignore constructors in directors with %ignore.
+
+2013-01-18: Brant Kyser
+ [Java] Patch #15 - Allow the use of the nspace feature without the -package commandline option.
+ This works as long and the new jniclasspackage pragma is used to place the JNI intermediate class
+ into a package and the nspace feature is used to place all exposed types into a package.
+
+2013-01-15: wsfulton
+ Fix Visual Studio examples to work when SWIG is unzipped into a directory containing spaces.
+
+2013-01-15: wsfulton
+ [C#] Fix cstype typemap lookup for member variables so that a fully qualified variable name
+ matches. For example:
+ %typemap(cstype) bool MVar::mvar "MyBool"
+ struct MVar {
+ bool mvar;
+ };
+
+2013-01-11: Brant Kyser
+ [Java, C#, D] SF Bug #1299 - Fix generated names for when %nspace is used on
+ classes with the same name in two different namespaces.
+
+2013-01-11: Vladimir Kalinin
+ [C#] Add support for csdirectorin 'pre', 'post' and 'terminator' attributes.
+
+2013-01-08: olly
+ [PHP] Fix to work with a ZTS build of PHP (broken in 2.0.7).
+
+2013-01-07: olly
+ Fix bashism in configure, introduced in 2.0.9.
+
+2013-01-06: wsfulton
+ Pull patch #4 from ptomulik to fix SF Bug #1296 - Fix incorrect warning for virtual destructors
+ in templates, such as:
+ Warning 521: Illegal destructor name B< A >::~B(). Ignored.
+
+2013-01-05: wsfulton
+ [Python] Pull patch #3 from ptomulik to fix SF Bug #1295 - standard exceptions as
+ classes using the SWIG_STD_EXCEPTIONS_AS_CLASSES macro.
+
+2013-01-04: wsfulton
+ [Java] Pull patch #2 from BrantKyser to fix SF Bug #1283 - fix smart pointers in conjuction
+ with directors.
+
+2013-01-03: wsfulton
+ [Java] Pull patch #1 from BrantKyser to fix SF Bug #1278 - fix directors and nspace feature when
+ multilevel namespaces are used.
+
+Version 2.0.9 (16 December 2012)
+================================
+
+2012-12-16: wsfulton
+ Fix garbage line number / empty file name reporting for some missing
+ '}' or ')' error messages.
+
+2012-12-15: kkaempf
+ [Ruby] Apply patch 3530444, Class#methods and Class#constants returns array of
+ symbols in Ruby 1.9+
+
+2012-12-14: kkaempf
+ [Ruby] Apply patch 3530439 and finally replace all occurrences of the STR2CSTR() macro
+ with StringValuePtr(). STR2CSTR was deprecated since years and got removed in Ruby 1.9
+
+2012-12-14: kkaempf
+ [Ruby] Applied patches #3530442 and 3530443 to adapt compile and runtime include
+ paths to match Ruby 1.9+
+
+2012-12-14: wsfulton
+ [CFFI] Fix #3161614 - Some string constants are incorrect
+
+2012-12-13: wsfulton
+ [CFFI] Fix #3529690 - Fix incorrect constant names.
+
+2012-12-12: drjoe
+ [R] add fix to finalizer that was missed earlier
+
+2012-12-11: wsfulton
+ [Python] Apply patch #3590522 - fully qualified package paths for Python 3 even if a module is in the
+ same package.
+
+2012-12-08: wsfulton
+ [Python] Bug #3563647 - PyInt_FromSize_t unavailable prior to Python 2.5 for unsigned int types.
+
+2012-12-08: wsfulton
+ [Perl] Fix bug #3571361 - C++ comment in C wrappers.
+
+2012-12-07: wsfulton
+ [C#] Apply patch #3571029 which adds missing director support for const unsigned long long &.
+
+2012-11-28: kwwette
+ [Octave] Simplified module loading: now just the syntax
+ $ example;
+ is accepted, which loads functions globally but constants and variables relative to the current scope.
+ This make module loading behaviour reliably consistent, and reduces problems when loading modules which
+ depend on other modules which may not have been previously loaded.
+
+2012-11-27: wsfulton
+ [cffi] Fix junk output when wrapping single character literal constants.
+
+2012-11-17: wsfulton
+ [Tcl, Modula3] Add missing support for -outdir.
+
+2012-11-17: wsfulton
+ Fix segfaults when using filename paths greater than 1024 characters in length.
+
+2012-11-14: wsfulton
+ [ccache-swig] Apply patch #3586392 from Frederik Deweerdt to fix some error cases - incorrectly using
+ memory after it has been deleted.
+
+2012-11-09: vzeitlin
+ [Python] Fix overflow when passing values greater than LONG_MAX from Python 3 for parameters with unsigned long C type.
+
+2012-11-09: wsfulton
+ Fix some feature matching issues for implicit destructors and implicit constructors and implicit
+ copy constructors added with %copyctor. Previously a feature for these had to be fully qualified
+ in order to match. Now the following will also match:
+
+ %feature("xyz") ~XXX();
+ struct XXX {};
+
+2012-11-09: wsfulton
+ Further consistency in named output typemap lookups for implicit constructors and destructors and
+ implicit copy constructors added with %copyctor. Previously only the fully qualified name was being
+ used, now the unqualified name will also be used. For example, previously:
+
+ example.i:38: Searching for a suitable 'out' typemap for: void Space::More::~More
+ Looking for: void Space::More::~More
+ Looking for: void
+
+ Now the unqualified name is also used:
+
+ example.i:38: Searching for a suitable 'out' typemap for: void Space::More::~More
+ Looking for: void Space::More::~More
+ Looking for: void ~More
+ Looking for: void
+
+2012-11-02: wsfulton
+ Fix some subtle named output typemap lookup misses, the fully qualified name was not always being
+ used for variables, for example:
+
+ struct Glob {
+ int MyVar;
+ };
+
+ Previously the search rules (as shown by -debug-tmsearch) for the getter wrapper were:
+
+ example.i:44: Searching for a suitable 'out' typemap for: int MyVar
+ Looking for: int MyVar
+ Looking for: int
+
+ Now the scope is named correctly:
+
+ example.i:44: Searching for a suitable 'out' typemap for: int Glob::MyVar
+ Looking for: int Glob::MyVar
+ Looking for: int MyVar
+ Looking for: int
+
+2012-10-26: wsfulton
+ Fix director typemap searching so that a typemap specified with a name will be correctly matched. Previously
+ the name was ignored during the typemap search. Applies to the following list of typemaps:
+ directorout, csdirectorout, cstype, imtype, ctype, ddirectorout, dtype, gotype, jtype, jni, javadirectorout.
+
+2012-10-11: wsfulton
+ Most of the special variables available for use in %exception are now also available for expansion in
+ %extend blocks. These are: $name $symname $overname $decl $fulldecl $parentclassname $parentclasssymname, see docs
+ on "Class extension" in SWIGPlus.html. Patch based on submission from Kris Thielemans.
+
+2012-10-10: wsfulton
+ Additional new special variables in %exception are expanded as follows:
+ $parentclassname - The parent class name (if any) for a method.
+ $parentclasssymname - The target language parent class name (if any) for a method.
+
+2012-10-08: iant
+ [Go] Generating Go code now requires using the -intgosize option to
+ indicate the size of the 'int' type in Go. This is because the
+ size of the type is changing from Go 1.0 to Go 1.1 for x86_64.
+
+2012-09-14: wsfulton
+ Add new warning if the empty template instantiation is used as a base class, for example:
+
+ template <typename T> class Base {};
+ %template() Base<int>;
+ class Derived : public Base<int> {};
+
+ gives the following warning instead of silently ignoring the base:
+
+ cpp_inherit.i:52: Warning 401: Base class 'Base< int >' has no name as it is an empty template instantiated with '%template()'. Ignored.
+ cpp_inherit.i:51: Warning 401: The %template directive must be written before 'Base< int >' is used as a base class and be declared with a name.
+
+
+2012-09-11: wsfulton
+ [Java] Fix #3535304 - Direct use of a weak global reference in directors
+ sometimes causing seg faults especially on Android.
+
+2012-09-06: wsfulton
+ [Java] Fix (char *STRING, size_t LENGTH) typemaps to accept NULL string.
+
+2012-08-26: drjoe
+ [R] make ExternalReference slot ref to contain reference
+
+2012-08-26: drjoe
+ [R] fix Examples/Makefile to use C in $(CC) rather than $(CXX)
+
+Version 2.0.8 (20 August 2012)
+==============================
+
+2012-08-15: wsfulton
+ [Perl] Add size_type, value_type, const_reference to the STL containers.
+
+2012-08-15: wsfulton
+ [Python] Add discard and add methods to std::set wrappers so that pyabc.i can be used ensuring
+ MutableSet is a valid abstract base class for std::set. As reported by Alexey Sokolov.
+ Similarly for std::multiset.
+
+2012-08-15: wsfulton
+ [Python] Fix #3541744 - Missing PyInt_FromSize_t calls for Python 3.
+
+2012-08-13: wsfulton
+ [Java] Patch from David Baum to add the assumeoverride feature for Java directors to
+ improve performance when all overridden methods can be assumed to be overridden.
+
+2012-08-05: wsfulton
+ [Python] #3530021 Fix unused variable warning.
+
+2012-08-05: wsfulton
+ [C#] Fix #3536360 - Invalid code sometimes being generated for director methods
+ with many arguments.
+
+2012-08-05: wsfulton
+ [Perl] #3545877 - Don't undefine bool if defined by C99 stdbool.h - problem using
+ Perl 5.16 and later.
+
+2012-08-04: wsfulton
+ Remove incorrect warning (314) about target language keywords which were triggered
+ by using declarations and using directives. For example 'string' is a keyword in C#:
+ namespace std { class string; }
+ using std::string;
+
+2012-07-21: wsfulton
+ Fix display of pointers in various places on 64 bit systems - only 32 bits were being shown.
+
+2012-07-21: wsfulton
+ Fix gdb debugger functions 'swigprint' and 'locswigprint' to display to the gdb output window
+ rather than stdout. This fixes display problems in gdbtui and the ensures the output
+ appears where expected in other gdb based debuggers such as Eclipse CDT.
+
+2012-07-20: kwwette
+ [Octave] segfault-on-exit prevention hack now preserves exit status, and uses C99 _Exit().
+
+2012-07-02: wsfulton
+ Fix Debian bug http://bugs.debian.org/672035, typemap copy failure - regression introduced
+ in swig-2.0.5:
+ %include<stl.i>
+ using std::pair;
+ %template(StrPair) pair<std::string, std::string>;
+
+2012-07-02: wsfulton
+ Fix using declarations combined with using directives with forward class declarations so that
+ types are correctly found in scope for templates. Example:
+
+ namespace Outer2 {
+ namespace Space2 {
+ template<typename T> class Thing2;
+ }
+ }
+ using namespace Outer2;
+ using Space2::Thing2;
+ template<typename T> class Thing2 {};
+ // STILL BROKEN void useit2(Thing2<int> t) {}
+ void useit2a(Outer2::Space2::Thing2<int> t) {}
+ void useit2b(::Outer2::Space2::Thing2<int> t) {}
+ void useit2c(Space2::Thing2<int> t) {}
+ namespace Outer2 {
+ void useit2d(Space2::Thing2<int> t) {}
+ }
+
+ %template(Thing2Int) Thing2<int>;
+
+
+2012-06-30: wsfulton
+ Fix template namespace problems for symbols declared with a forward class declarations, such as:
+
+ namespace Space1 {
+ namespace Space2 {
+ template<typename T> struct YYY;
+ }
+ template<typename T> struct Space2::YYY {
+ T yyy(T h) {
+ return h;
+ }
+ };
+ void testYYY1(Space1::Space2::YYY<int> yy) {}
+ void testYYY2(Space2::YYY<int> yy) {}
+ void testYYY3(::Space1::Space2::YYY<int> yy) {}
+ }
+
+ %template(YYYInt) Space1::Space2::YYY<int>;
+
+2012-06-30: wsfulton
+ Fix namespace problems for symbols declared with a forward class declarations, such as:
+
+ namespace Space1 {
+ namespace Space2 {
+ struct XXX;
+ struct YYY;
+ }
+
+ struct Space2::YYY {};
+ struct Space1::Space2::XXX {};
+
+ void testXXX2(Space2::XXX xx) {}
+ void testYYY2(Space2::YYY yy) {}
+ }
+
+ where xx and yy were not recognised as the proxy classes XXX and YYY.
+
+2012-06-30: wsfulton
+ Fix using declarations combined with using directives with forward class declarations so that
+ types are correctly found in scope.
+
+ namespace Outer2 {
+ namespace Space2 {
+ class Thing2;
+ }
+ }
+ using namespace Outer2;
+ using Space2::Thing2;
+ class Thing2 {};
+ // None of the methods below correctly used the Thing2 proxy class
+ void useit2(Thing2 t) {}
+ void useit2a(Outer2::Space2::Thing2 t) {}
+ void useit2b(::Outer2::Space2::Thing2 t) {}
+ void useit2c(Space2::Thing2 t) {}
+ namespace Outer2 {
+ void useit2d(Space2::Thing2 t) {}
+ }
+
+2012-06-25: wsfulton
+ Fix using declarations combined with using directives so that types are correctly found in scope.
+ Example:
+
+ namespace Outer2 {
+ namespace Space2 {
+ class Thing2 {};
+ }
+ }
+ using namespace Outer2; // using directive
+ using Space2::Thing2; // using declaration
+ void useit2(Thing2 t) {}
+
+ Similarly for templated classes.
+
+2012-05-29: wsfulton
+ Fix #3529601 - seg fault when a protected method has the "director"
+ feature but the parent class does not. Also fix similar problems with
+ the allprotected feature.
+
+2012-05-28: wsfulton
+ Fix seg fault when attempting to warn about an illegal destructor - #3530055, 3530078 and #3530118.
+
+Version 2.0.7 (26 May 2012)
+===========================
+2012-05-26: wsfulton
+ std::string typemap modifications so they can be used with %apply for other string
+ classes.
+
+2012-05-25: wsfulton
+ [Lua] Fixes for -external-runtime to work again.
+
+2012-05-22: szager
+ [python] Disambiguate SWIG_From_unsigned_SS_int and SWIG_From_unsigned_SS_long.
+
+2012-05-18: olly
+ [PHP] Fix getters for template members. (SF#3428833, SF#3528035)
+
+2012-05-14: wsfulton
+ Fix some language's std::map wrappers to recognise difference_type, size_type, key_type
+ and mapped_type.
+
+2012-05-14: kwwette (signed off by xavier98)
+ [Octave] Prevent Octave from seg-faulting at exit when SWIG
+ modules are loaded, due to bugs in Octave's cleanup code:
+ * Wrapping functions now declared with Octave DEFUN_DLD macro,
+ and loaded through Octave's dynamic module loader
+ * Global variables of swigref type are now assigned a new()
+ copy of the swigref class, to prevent double-free errors
+ * SWIG module at-exit cleanup function now created in Octave
+ through eval(), so not dependent on loaded .oct library
+ * For Octave versions 3.1.* to 3.3.*, register C-level at-exit
+ function which terminates Octave immediately (with correct
+ status code) without performing memory cleanup. This function
+ can be controlled with macros in Lib/octave/octruntime.swg
+
+ [Octave] New syntax for determing whether SWIG module should be
+ loaded globally or non-globally. To load module "example" globally,
+ type the module name
+ $ example;
+ as before; to load module non-globally, assign it to a variable:
+ $ example = example;
+ or
+ $ ex = example;
+ for a shorter (local) module name. -global/-noglobal command-line
+ options and module command line are deprecated. Added usage info
+ to module, so typing
+ $ help example
+ or incorrect usage should display proper usage, with examples.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2012-05-12: olly
+ [PHP] Fix memory leak in code generated for a callback. Patch from
+ SF bug #3510806.
+
+2012-05-12: olly
+ [PHP] Avoid using zend_error_noreturn() as it doesn't work with all
+ builds of PHP (SF bug #3166423). Instead we now wrap it in a
+ SWIG_FAIL() function which we annotate as "noreturn" for GCC to
+ avoids warnings. This also reduces the size of the compiled
+ wrapper (e.g. the stripped size is reduced by 6% for Xapian's PHP
+ bindings).
+
+2012-05-11: wsfulton
+ [Java] SF patch #3522855 Fix unintended uninitialised memory access in OUTPUT typemaps.
+
+2012-05-11: wsfulton
+ [Java] SF patch #3522674 Fix possible uninitialised memory access in char **STRING_OUT
+ typemap.
+
+2012-05-11: wsfulton
+ [Java] SF patch #3522611 Fix uninitialised size regression in char **STRING_ARRAY
+ introduced in swig-2.0.6.
+
+2012-05-11: wsfulton
+ SF bug #3525050 - Fix regression introduced in swig-2.0.5 whereby defining one typemap
+ method such as an 'out' typemap may hide another typemap method such as an 'in' typemap -
+ only occurs when the type is a template type where the template parameters are the same
+ via a typedef.
+
+2012-05-10: olly
+ [PHP] Fix the constant typemaps for SWIGTYPE, etc - previously
+ these used the wrong name for renamed constants. Add
+ autodoc_runme.php to the testsuite as a regression test for this.
+
+2012-05-02: ianlancetaylor
+ [Go] Remove compatibility support for gccgo 4.6. Using
+ SWIG with gccgo will now require gccgo 4.7. Using SWIG
+ with the more commonly used gc compiler is unaffected.
+
+2012-05-01: wsfulton
+ Fix generated code for C forward enum declarations in some languages.
+
+Version 2.0.6 (30 April 2012)
+=============================
+
+2012-04-25: wsfulton
+ [Lua] Fix uninitialised variable in SWIGTYPE **OUTPUT typemaps as reported by Jim Anderson.
+
+2012-04-28: wsfulton
+ [Python] Fix compilation errors when wrapping STL containers on Mac OS X and possibly other systems.
+
+2012-04-28: wsfulton
+ [Java] Patch 3521811 from Leo Davis - char **STRING_ARRAY typemaps fixed to handle
+ null pointers.
+
+Version 2.0.5 (19 April 2012)
+=============================
+
+2012-04-14: wsfulton
+ [Lua] Apply patch #3517435 from Miles Bader - prefer to use Lua_pushglobaltable
+
+2012-04-14: wsfulton
+ [Ruby] Apply patch #3517769 from Robin Stocker to fix compile error on MacRuby using RSTRING_PTR.
+
+2012-04-13: wsfulton
+ Apply patch #3511009 from Leif Middelschulte for slightly optimised char * variable wrappers.
+
+2012-04-13: wsfulton
+ [Lua] Apply #3219676 from Shane Liesegang which adds:
+ - support for %factory
+ - a __tostring method
+ - a __disown method
+
+2012-04-13: wsfulton
+ [Xml] Apply #3513569 which adds a catchlist to the xml output.
+
+2012-04-05: olly
+ [Lua] Add support for Lua 5.2 (patch SF#3514593 from Miles Bader)
+
+2012-03-26: xavier98
+ [octave] Apply patch #3425993 from jgillis: add extra logic to the octave_swig_type::dims(void) method: it checks if the user has defined a __dims__ method and uses this in stead of returning (1,1)
+ [octave] Apply patch #3424833 from jgillis: make is_object return true for swig types
+
+2012-03-24: wsfulton
+ [D] Apply #3502431 to fix duplicate symbols in multiple modules.
+
+2012-03-21: wsfulton
+ Fix #3494791 - %$isglobal for %rename matching.
+
+2012-03-20: wsfulton
+ Fix #3487706 and #3391906 - missing stddef.h include for ptrdiff_t when using %import
+ for STL containers and compiling with g++-4.6. An include of stddef.h is now only
+ generated when SWIG generates STL helper templates which require ptrdiff_t. If you
+ were previously relying on "#include <stddef.h>" always being generated when using a
+ %include of an STL header, you may now need to add this in manually.
+
+2012-03-16: wsfulton
+ Apply patch #3392264 from Sebastien Bine to parse (unsigned) long long types in enum value assignment.
+
+2012-03-16: wsfulton
+ Apply patch #3505530 from Karl Wette to allow custom allocators in STL string classes for the UTL languages.
+
+2012-03-13: wsfulton
+ Apply patch #3468362 from Karl Wette to fix %include inside %define.
+
+2012-03-13: wsfulton
+ [Python, Ruby, Octave, R] Fix #3475492 - iterating through std::vector wrappers of enumerations.
+
+2012-02-27: xavier98 (patches from Karl Wette)
+ [Octave] Use -globals . to load global variables in module namespace
+ [Octave] Comment declaration of unimplemented function swig_register_director
+ [Octave] Fix OCTAVE_PATH in octave Makefiles
+ [Octave] Add support for std::list - fix li_std_containers_int test
+ [Octave] Fix imports test
+
+2012-02-16: wsfulton
+ [Java] Make generated support functions in arrays_java.i static so that generated code
+ from multiple instances of SWIG can be compiled and linked together - problem reported by
+ Evan Krause.
+
+2012-01-24: wsfulton
+ Fix crash with bad regex - bug #3474250.
+
+2012-01-24: wsfulton
+ [Python] Add Python stepped slicing support to the STL wrappers (std::vector, std::list).
+ Assigning to a slice, reading a slice and deleting a slice with steps now work.
+ For example:
+
+ %template(vector_i) std::vector<int>
+
+ vi = vector_i(range(10))
+ print list(vi)
+ vi[1:4:2] = [111, 333]
+ print list(vi)
+ del vi[3:10:3]
+ print list(vi)
+ print list(vi[::-1])
+
+ gives (same behaviour as native Python sequences such as list):
+
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ [0, 111, 2, 333, 4, 5, 6, 7, 8, 9]
+ [0, 111, 2, 4, 5, 7, 8]
+ [8, 7, 5, 4, 2, 111, 0]
+
+2012-01-23: klickverbot
+ [D] Correctly annotate function pointers with C linkage.
+ [D] Exception and Error have become blessed names; removed d_exception_name test case.
+
+2012-01-20: wsfulton
+ [Python] Fix some indexing bugs in Python STL wrappers when the index is negative, eg:
+
+ %template(vector_i) std::vector<int>
+
+ iv=vector_i([0,1,2,3,4,5])
+ iv[-7:]
+
+ now returns [0, 1, 2, 3, 4, 5] instead of [5].
+
+ vv[7:9] = [22,33]
+
+ now returns [0, 1, 2, 3, 4, 5, 22, 33] instead of "index out range" error.
+
+ Also fix some segfaults when replacing ranges, eg when il is a std::list wrapper:
+
+ il[0:2] = [11]
+
+2012-01-17: wsfulton
+ [Go] Fix forward class declaration within a class when used as a base.
+
+2012-01-07: wsfulton
+ [C#] Add support for %nspace when using directors.
+
+2012-01-06: wsfulton
+ [Java] Patch #3452560 from Brant Kyser - add support for %nspace when using directors.
+
+2011-12-21: wsfulton
+ The 'directorin' typemap now accepts $1, $2 etc expansions instead of having to use workarounds -
+ $1_name, $2_name etc.
+
+2011-12-20: wsfulton
+ [Java] Add (char *STRING, size_t LENGTH) director typemaps.
+
+2011-12-20: wsfulton
+ [C#, Go, Java, D] Add support for the 'directorargout' typemap.
+
+2011-12-20: wsfulton
+ [Ocaml, Octave, PHP, Python, Ruby] Correct special variables in 'directorargout' typemap.
+ This change will break any 'directorargout' typemaps you may have written. Please change:
+ $result to $1
+ $input to $result
+
+ Also fix the named 'directorargout' DIRECTOROUT typemaps for these languages which didn't
+ previously compile and add in $1, $2 etc expansion.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2011-12-10: talby
+ [perl5] SWIG_error() now gets decorated with perl source file/line number.
+ [perl5] error handling now conforms to public XS api (fixes perl v5.14 issue).
+
+2011-12-10: wsfulton
+ [Android/Java] Fix directors to compile on Android.
+
+ Added documentation and examples for Android.
+
+2011-12-08: vadz
+ Bug fix: Handle methods renamed or ignored in the base class correctly in the derived classes
+ (they could be sometimes mysteriously not renamed or ignored there before).
+
+2011-12-03: klickverbot
+ [D] Fix exception glue code for newer DMD 2 versions.
+ [D] Do not default to 32 bit glue code for DMD anymore.
+ [D] Use stdc.config.c_long/c_ulong to represent C long types.
+
+2011-12-01: szager
+ [python] Fixed bug 3447426: memory leak in vector.__getitem__.
+
+2011-11-30: wsfulton
+ [R] Remove C++ comments from generated C code.
+
+2011-11-27: olly
+ [Python] Fix some warnings when compiling generated wrappers with
+ certain GCC warning options (Debian bug #650246).
+
+2011-11-28: wsfulton
+ Fix #3433541 %typemap(in, numinputs=0) with 10+ arguments.
+
+2011-11-28: olly
+ [Perl] Fix warnings when compiling generated wrappers with certain
+ GCC warning options (Debian bug #436711).
+
+2011-11-28: olly
+ [PHP] Update keyword list to include keywords added in PHP releases up to 5.3.
+
+2011-11-25: wsfulton
+ [C#] Provide an easy way to override the default visibility for the proxy class pointer
+ constructors and getCPtr() method. The visibility is 'internal' by default and if multiple
+ SWIG modules are being used and compiled into different assemblies, then they need to be
+ 'public' in order to use the constructor or getCPtr() method from a different assembly.
+ Use the following macros to change the visibilities in the proxy and type wrapper class:
+
+ SWIG_CSBODY_PROXY(public, public, SWIGTYPE)
+ SWIG_CSBODY_TYPEWRAPPER(public, public, public, SWIGTYPE)
+
+ [Java] Provide an easy way to override the default visibility for the proxy class pointer
+ constructors and getCPtr() method. The visibility is 'protected' by default and if multiple
+ SWIG modules are being used and compiled into different packages, then they need to be
+ 'public' in order to use the constructor or getCPtr() method from a different package.
+ Use the following macros to change the visibilities in the proxy and type wrapper class:
+
+ SWIG_JAVABODY_PROXY(public, public, SWIGTYPE)
+ SWIG_JAVABODY_TYPEWRAPPER(public, public, public, SWIGTYPE)
+
+ The default for Java has changed from public to protected for the proxy classes. Use the
+ SWIG_JAVABODY_PROXY macro above to restore to the previous visibilities.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2011-11-22: szager
+ [python] Bug 3440044: #ifdef out SWIG_Python_NonDynamicSetAttr if -builtin
+ isn't being used, to avoid unnecessary binary incompatibilities between
+ python installations.
+
+2011-11-17: wsfulton
+ Bug fix: Remove root directory from directory search list in Windows.
+
+2011-11-13: wsfulton
+ [Ruby] Apply patch #3421876 from Robin Stocker to fix #3416818 - same class name in
+ different namespaces confusion when using multiple modules.
+
+2011-11-11: wsfulton
+ Fix pcre-build.sh to work with non-compressed tarballs - problem reported by Adrian Blakely.
+
+2011-11-03: wsfulton
+ Expand special variables in typemap warnings, eg:
+
+ %typemap(in, warning="1000:Test warning for 'in' typemap for $1_type $1_name") int "..."
+
+2011-11-01: wsfulton
+ Fix named output typemaps not being used when the symbol uses a qualifier and contains
+ a number, eg:
+
+ %typemap(out) double ABC::m1 "..."
+
+2011-10-24: talby
+ [perl5] SF bug #3423119 - overload dispatch stack corruption fix. Better, but more research
+ is needed on a stable path for tail calls in XS.
+
+ Also, fix for large long longs in 32 bit perl.
+
+2011-10-13: xavier98
+ [octave] Allow Octave modules to be re-loaded after a "clear all".
+
+2011-09-19: wsfulton
+ Fix regression introduced in swig-2.0.1 reported by Teemu Ikonone leading to uncompilable code
+ when using typedef and function pointer references, for example:
+
+ typedef int FN(const int &a, int b);
+ void *typedef_call1(FN *& precallback, FN * postcallback);
+
+2011-09-14: wsfulton
+ [Lua] Patch #3408012 from Raman Gopalan - add support for embedded Lua (eLua)
+ including options for targeting Lua Tiny RAM (LTR).
+
+2011-09-14: wsfulton
+ [C#] Add boost_intrusive_ptr.i library contribution from patch #3401571.
+
+2011-09-13: wsfulton
+ Add warnings for badly named destructors, eg:
+
+ struct KStruct {
+ ~NOT_KStruct() {}
+ };
+
+ cpp_extend_destructors.i:92: Warning 521: Illegal destructor name ~NOT_KStruct. Ignored.
+
+2011-09-13: wsfulton
+ Fix %extend and destructors for templates. The destructor in %extend was not always wrapped,
+ for example:
+
+ %extend FooT {
+ ~FooT() { delete $self; } // was not wrapped as expected
+ };
+ template<class T> class FooT {};
+ %template(FooTi) FooT<int>;
+
+2011-09-13: wsfulton
+ Fix special variables such as "$decl" and "$fulldecl" in destructors to include the ~ character.
+
+2011-09-10: talby
+ [perl5] SF bug #1481958 - Improve range checking for integer types.
+ Enhance li_typemaps_runme.pl
+
+2011-09-08: wsfulton
+ Fix %extend on typedef classes in a namespace using the typedef name, for example:
+ namespace Space {
+ %extend CStruct {
+ ...
+ }
+ typedef struct tagCStruct { ... } CStruct;
+ }
+
+2011-08-31: xavier98
+ [octave] patches from Karl Wette: improvements to module loading behavior;
+ added example of friend operator to operator example; fixed octave panic/crash in 3.0.5;
+ documentation improvements
+
+2011-08-30: szager
+ [python] Bug 3400486, fix error signalling for built-in constructors.
+
+2011-08-26: wsfulton
+ [Go] Fix file/line number display for "gotype" when using typemap debugging options
+ -tmsearch and -tmused.
+
+2011-08-26: wsfulton
+ [C#, D] Fix %callback which was generating uncompilable code.
+
+2011-08-25: wsfulton
+ Fix constructors in named typedef class declarations as reported by Gregory Bronner:
+
+ typedef struct A {
+ A(){} // Constructor which was not accepted by SWIG
+ B(){} // NOT a constructor --illegal, but was accepted by SWIG
+ } B;
+
+ For C code, the fix now results in the use of 'struct A *' instead of just 'B *' in
+ the generated code when wrapping members in A, but ultimately this does not matter, as
+ they are the same thing.
+
+2011-08-23: wsfulton
+ Fix %newobject when used in conjunction with %feature("ref") as reported by Jan Becker. The
+ code from the "ref" feature was not always being generated for the function specified by %newobject.
+ Documentation for "ref" and "unref" moved from Python to the C++ chapter.
+
+2011-08-22: szager
+ [python] Fixed memory leak with --builtin option (bug 3385089).
+
+2011-08-22: wsfulton
+ [Lua] SF patch #3394339 from Torsten Landschoff - new option -nomoduleglobal to disable installing
+ the module table into the global namespace. Require call also returns the module table instead
+ of a string.
+
+2011-08-09: xavier98
+ Fix bug 3387394; Octave patches for 3.4.0 compatibility, etc. (from Karl Wette)
+
+2011-08-04: wsfulton
+ Add in $symname expansion for director methods.
+
+2011-07-29: olly
+ [PHP] Don't generate "return $r;" in cases where $r hasn't been set.
+ This was basically harmless, except it generated a PHP E_NOTICE if
+ the calling code had enabled them.
+
+2011-07-26: wsfulton
+ Fix scoping of forward class declarations nested within a class (for C++). Previously the symbol
+ was incorrectly put into the outer namespace, eg
+
+ namespace std {
+ template<class Key, class T> struct map {
+ class iterator;
+ };
+ }
+
+ iterator was scoped as std::iterator, but now it is correctly std::map<Key, T>::iterator;
+
+ Also fixed is %template and template parameters that are a typedef when the template contains
+ default template parameters, eg:
+
+ namespace Std {
+ template<class Key, class T, class C = int> struct Map {
+ typedef Key key_type;
+ typedef T mapped_type;
+ };
+ }
+ typedef double DOUBLE;
+ %template(MM) Std::Map<int, DOUBLE>;
+
+ All symbols within Map will be resolved correctly, eg key_type and mapped_type no matter if the
+ wrapped code uses Std::Map<int, double> or std::Map<int, DOUBLE> or Std::Map<int, double, int>
+
+ Also fixes bug #3378145 - regression introduced in 2.0.4 - %template using traits.
+
+2011-07-20 szager
+ [python] Fix closure for tp_call slot.
+
+2011-07-16: wsfulton
+ [python] Fix director typemap using PyObject *.
+
+2011-07-13: szager
+ [python] SF patch #3365908 - Add all template parameters to map support code in std_map.i
+
+2011-07-13: szager
+ [python] Fix for bug 3324753: %rename member variables with -builtin.
+
+2011-07-01: wsfulton
+ Fix some scope and symbol lookup problems when template default parameters are being
+ used with typedef. For example:
+
+ template<typename XX, typename TT = SomeType> struct Foo {
+ typedef XX X;
+ typedef TT T;
+ };
+ template<typename TT> struct UsesFoo {
+ void x(typename Foo<TT>::T, typename Foo<TT>::X);
+ };
+
+ Also fixes use of std::vector<int>::size_type for Python as reported by Aubrey Barnard.
+
+2011-06-23: olly
+ [PHP] Fix director code to work when PHP is built with ZTS enabled,
+ which is the standard configuration on Microsoft Windows.
+
+2011-06-21: mutandiz
+ [allegrocl]
+ - various small tweaks and bug fixes.
+ - Avoid name conflicts between smart pointer wrappers and the wrappers for
+ the actual class.
+ - Fix default typemaps for C bindings, which were incorrectly attempting to
+ call non-existent destructors on user-defined types.
+ - New feature, feature:aclmixins, for adding superclass to the foreign class
+ wrappers.
+ - Improve longlong typemaps.
+
+2011-06-19: wsfulton
+ Fix incorrect typemaps being used for a symbol within a templated type, eg:
+ A<int>::value_type would incorrectly use a typemap for type A.
+
+2011-06-18: olly
+ [Tcl] Fix variable declarations in middle of blocks which isn't
+ permitted in C90 (issue probably introduced in 2.0.3 by patch #3224663).
+ Reported by Paul Obermeier in SF#3288586.
+
+2011-06-17: wsfulton
+ [Java] SF #3312505 - slightly easier to wrap char[] or char[ANY] with a Java byte[]
+ using arrays_java.i.
+
+2011-06-13: wsfulton
+ [Ruby, Octave] SF #3310528 Autodoc fixes similar to those described below for Python.
+
+2011-06-10: wsfulton
+ [Python] Few subtle bugfixes in autodoc documentation generation,
+ - Unnamed argument names fix for autodoc levels > 0.
+ - Display of template types fixed for autodoc levels > 1.
+ - Fix SF #3310528 - display of typedef structs for autodoc levels > 1.
+ - Add missing type for self for autodoc levels 1 and 3.
+ - autodoc levels 2 and 3 documented.
+ - Minor tweaks to autodoc style to conform with PEP8.
+
+2011-05-30: olly
+ [PHP] Fix handling of directors when -prefix is used.
+
+2011-05-24: olly
+ [PHP] Fix handling of methods of classes with a virtual base class (SF#3124665).
+
+Version 2.0.4 (21 May 2011)
+===========================
+
+2011-05-19: wsfulton
+ [Guile] Patch #3191625 fixing overloading of integer types.
+
+2011-05-19: wsfulton
+ [Perl] Patch #3260265 fixing overloading of non-primitive types and integers in
+ Perl 5.12 and later.
+
+2011-05-19: wsfulton
+ [Ruby] Fix %import where one of the imported files %include one of the STL include
+ files such as std_vector.i.
+
+2011-05-17: wsfulton
+ [Java] Apply #3289851 from Alan Harder to fix memory leak in directors when checking
+ for pending exceptions.
+
+2011-05-17: wsfulton
+ [Tcl] Apply #3300072 from Christian Delbaere to fix multiple module loading not
+ always sharing variables across modules.
+
+2011-05-16: xavier98
+ [octave] Fix an incompatibility with never versions of Octave. Case on Octave
+ API >= 40 to handle rename of Octave_map to octave_map.
+ [octave] Add support for y.__rop__(x) operators when x.__op__(y) doesn't exist.
+ [octave] Allow global operators to be defined by SWIG-wrapped functions.
+ [octave] Fix several bugs around module namespaces; add -global, -noglobal,
+ -globals <name> command line options to the module.
+
+2011-05-14: wsfulton
+ %varargs when used with a numeric argument used to create an additional argument
+ which was intended to provide a guaranteed sentinel value. This never worked and now
+ the additional argument is not generated.
+
+2011-05-13: wsfulton
+ [python] Additional fixes for python3.2 support.
+
+2011-05-07: szager
+ [python] Fixed PyGetSetDescr for python3.2.
+
+2011-05-05: wsfulton
+ [Lua, Python, Tcl] C/C++ prototypes shown in error message when calling an overloaded
+ method with incorrect arguments improved to show always show fully qualified name
+ and if a const method.
+
+ Also fixed other Lua error messages in generated code which weren't consistently
+ using the fully qualified C++ name - requested by Gedalia Pasternak.
+
+2011-04-29: szager
+ Bug 2635919: Convenience method to convert std::map to a python dict.
+
+2011-04-29: szager
+ [Python] Fixed bug 2811549: return non-const iterators from STL
+ methods begin(), end(), rbegin(), rend().
+
+2011-04-25: szager
+ [Python] Fixed bug 1498929: Access to member fields in map elements
+
+2011-04-23: klickverbot
+ [D] nspace: Correctly generate identifiers for base classes when
+ not in split proxy mode.
+
+2011-04-13: szager
+ Fixed bug 3286333: infinite recursion with mutual 'using namespace' clauses.
+
+2011-04-12: szager
+ Fixed bug 1163440: vararg typemaps.
+
+2011-04-12: szager
+ Fixed bug #3285386: parse error from 'operator T*&()'. Added operator_pointer_ref
+ test case to demonstrate.
+
+2011-04-11: szager
+ [Python] Fixed PyVarObject_HEAD_INIT to eliminate VC++ compiler errors about
+ static initialization of struct members with pointers.
+
+2011-04-11: wsfulton
+ [Tcl] Apply patch #3284326 from Colin McDonald to fix some compiler warnings.
+
+2011-04-11: szager
+ [Python] Fixed PyVarObject_HEAD_INIT to eliminate VC++ compiler errors about
+ static initialization of struct members with pointers.
+
+2011-04-10: klickverbot
+ [D] Fixed wrapping of enums that are type char, for example:
+ enum { X = 'X'; } (this was already in 2.0.3 for C# and Java)
+
+2011-04-10: klickverbot
+ [D] nspace: Fixed referencing types in the root namespace when
+ not in split proxy mode.
+
+2011-04-09: szager
+ [Python] Applied patch #1932484: migrate PyCObject to PyCapsule.
+
+2011-04-09: szager
+ [Python] Added preprocessor guards for python functions PyUnicode_AsWideChar and
+ PySlice_GetIndices, which changed signatures in python3.2.
+
+2011-04-07: wsfulton
+ Fix wrapping of const array typedefs which were generating uncompilable code as
+ reported by Karl Wette.
+
+2011-04-03: szager
+ [Python] Fixed the behavior of %pythonnondynamic to conform to the spec in Lib/pyuserdir.swg.
+
+2011-04-03: szager
+ [Python] Merged in the szager-python-builtin branch, adding the -builtin feature
+ for python. The -builtin option may provide a significant performance gain
+ in python wrappers. For full details and limitations, refer to Doc/Manual/Python.html.
+ A small test suite designed to demonstrate the performance gain is in
+ Examples/python/performance.
+
+2011-04-01: wsfulton
+ Add in missing wrappers for friend functions for some target languages, mostly
+ the non-scripting languages like Java and C#.
+
+Version 2.0.3 (29 March 2011)
+=============================
+
+2011-03-29: wsfulton
+ [R] Apply patch #3239076 from Marie White fixing strings for R >= 2.7.0
+
+2011-03-29: wsfulton
+ [Tcl] Apply patch #3248280 from Christian Delbaere which adds better error messages when
+ the incorrect number or type of arguments are passed to overloaded methods.
+
+2011-03-29: wsfulton
+ [Tcl] Apply patch #3224663 from Christian Delbaere.
+ 1. Fix when function returns a NULL value, a "NULL" command will be created in the Tcl interpreter
+ and calling this command will cause a segmentation fault.
+
+ 2. Previous implementation searches for class methods using a linear search causing performance issues
+ in wrappers for classes with many member functions. The patch adds a method hash table to classes and
+ changes method name lookup to use the hash table instead of doing a linear search.
+
+2011-03-26: wsfulton
+ [C#, Java] SF bug #3195112 - fix wrapping of enums that are type char, for example:
+ enum { X = 'X'; }
+
+2011-03-21: vadz
+ Allow setting PCRE_CFLAGS and PCRE_LIBS during configuration to override the values returned by
+ pcre-config, e.g. to allow using a static version of PCRE library.
+
+2011-03-17: wsfulton
+ [UTL] Add missing headers in generated STL wrappers to fix compilation with gcc-4.6.
+
+2011-03-17: wsfulton
+ Fix regression introduced in swig-2.0.2 where filenames with spaces were not found
+ when used with %include and %import. Reported by Shane Liesegang.
+
+2011-03-15: wsfulton
+ [UTL] Fix overloading when using const char[], problem reported by David Maxwell.
+ Similarly for char[ANY] and const char[ANY].
+
+2011-03-15: wsfulton
+ [C#] Apply patch #3212624 fixing std::map Keys property.
+
+2011-03-14: olly
+ [PHP] Fix handling of overloaded methods/functions where some
+ return void and others don't - whether this worked or not depended
+ on the order they were encountered in (SF#3208299).
+
+2011-03-13: klickverbot
+ [D] Extended support for C++ namespaces (nspace feature).
+
+2011-03-12: olly
+ [PHP] Fix sharing of type information between multiple SWIG-wrapped
+ modules (SF#3202463).
+
+2011-03-09: wsfulton
+ [Python] Fix SF #3194294 - corner case bug when 'NULL' is used as the default value
+ for a primitive type parameter in a method declaration.
+
+2011-03-07: olly
+ [PHP] Don't use zend_error_noreturn() for cases where the function
+ returns void - now this issue can only matter if you have a function
+ or method which is directed and returns non-void.
+
+2011-03-06: olly
+ [PHP] Add casts to the typemaps for long long and unsigned long
+ long to avoid issues when they are used with shorter types via
+ %apply.
+
+2011-03-02: wsfulton
+ Templated smart pointers overloaded with both const and non const operator-> generated uncompilable
+ code when the pointee was a class with either public member variables or static methods.
+ Regression in 2.0.x reported as working in 1.3.40 by xantares on swig-user mailing list.
+
+Version 2.0.2 (20 February 2011)
+================================
+
+2011-02-19: wsfulton
+ [PHP] Add missing INPUT, OUTPUT and INOUT typemaps in the typemaps.i library
+ for primitive reference types as well as signed char * and bool *.
+
+2011-02-19: olly
+ [PHP] Address bug in PHP on some platforms/architectures which
+ results in zend_error_noreturn() not being available using
+ SWIG_ZEND_ERROR_NORETURN which defaults to zend_error_noreturn but
+ can be overridden when building the module by passing
+ -DSWIG_ZEND_ERROR_NORETURN=zend_error to the compiler. This may
+ result in compiler warnings, but should at least allow a module
+ to be built on those platforms/architectures (SF#3166423).
+
+2011-02-18: wsfulton
+ Fix #3184549 - vararg functions and function overloading when using the -fastdispatch option.
+
+2011-02-18: olly
+ [PHP] An overloaded method which can return an object or a
+ primitive type no longer causes SWIG to segfault. Reported by Paul
+ Colby in SF#3168531.
+
+2011-02-18: olly
+ [PHP] Fix invalid erase during iteration of std::map in generated
+ director code. Reported by Cory Bennett in SF#3175820.
+
+2011-02-17: wsfulton
+ Preprocessing now warns if extra tokens appear after #else and #end.
+
+2011-02-16: wsfulton
+ Fix #1653092 Preprocessor does not error out when #elif is missing an expression.
+ This and other cases of missing preprocessor expressions now result in an error.
+
+2011-02-14: wsfulton
+ [Ocaml] Apply patch #3151788 from Joel Reymont. Brings Ocaml support up to date
+ (ver 3.11 and 3.12), including std::string.
+
+2011-02-13: wsfulton
+ [Ruby] Apply patch #3176274 from James Masters - typecheck typemap for time_t.
+
+2011-02-13: wsfulton
+ Apply patch #3171793 from szager - protected director methods failing when -fvirtual is used.
+
+2011-02-13: wsfulton
+ Fix #1927852 - #include directives don't preprocess the file passed to it. The fix is for
+ #include with -importall or -includeall, %include and %import, for example:
+ #define FILENAME "abc.h"
+ %include FILENAME
+
+2011-02-12: wsfulton
+ Fix #1940536, overactive preprocessor which was expanding defined(...) outside of #if and #elif
+ preprocessor directives.
+
+2011-02-05: wsfulton
+ [MzScheme] SF #2942899 Add user supplied documentation to help getting started with MzScheme.
+ Update chapter name to MzScheme/Racket accounting for the rename of MzScheme to Racket.
+
+2011-02-05: wsfulton
+ [C#] SF #3085906 - Possible fix running test-suite on Mac OS X.
+
+2011-02-05: wsfulton
+ SF #3173367 Better information during configure about Boost prerequisite for running
+ the test-suite.
+
+2011-02-05: wsfulton
+ SF #3127633 Fix infinite loop in recursive typedef resolution.
+
+2011-02-04: wsfulton
+ [R] SF #3168676 Fix %rename not working for member variables and methods.
+
+2011-02-04: wsfulton
+ [clisp] SF #3148200 Fix segfault parsing nested unions.
+
+2011-02-01: wsfulton
+ [C#] Directors - a call to a method being defined in the base class, not
+ overridden in a subclass, but again overridden in a class derived from
+ the first subclass was not being dispatched correctly to the most derived class.
+ See director_alternating.i for an example.
+
+2011-02-01: wsfulton
+ [C#, Java] Any 'using' statements in the protected section of a class were previously
+ ignored with director protected (dirprot) mode.
+
+2011-01-30: wsfulton
+ Fix overloading with const pointer reference (SWIGTYPE *const&) parameters for a
+ number of scripting languages.
+
+2011-01-17: wsfulton
+ New warning for smart pointers if only some of the classes in the inheritance
+ chain are marked as smart pointer, eg, %shared_ptr should be used for all classes
+ in an inheritance hierarchy, so this new warning highlights code where this is
+ not the case.
+
+ example.i:12: Warning 520: Base class 'A' of 'B' is not similarly marked as a smart pointer.
+ example.i:16: Warning 520: Derived class 'C' of 'B' is not similarly marked as a smart pointer.
+
+2011-01-14: wsfulton
+ Added some missing multi-argument typemaps: (char *STRING, size_t LENGTH) and
+ (char *STRING, int LENGTH). Documentation for this updated. Java patch from
+ Volker Grabsch.
+
+2011-01-11: iant
+ Require Go version 7077 or later.
+
+2010-12-30: klickverbot
+ [C#, D, Java] Check for collision of parameter names with target
+ language keywords when generating the director glue code.
+
+ The situation in which the generated could would previously be
+ invalid is illustrated in the new 'director_keywords' test case.
+
+2010-12-23: wsfulton
+ [C#] Fix $csinput special variable not being expanded for csvarin typemaps
+ when used for global variables. Reported by Vadim Zeitlin.
+
+2010-12-14: wsfulton
+ Fix $basemangle expansion in array typemaps. For example if type is int *[3],
+ $basemangle expands to _p_int.
+
+2010-12-07: iant
+ Check that we are using a sufficiently new version of the
+ 6g or 8g Go compiler during configure time. If not, disable Go.
+ Minimum version is now 6707.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2010-12-06: wsfulton
+ Fix #3127394 - use of network paths on Windows/MSys.
+
+2010-11-18: klickverbot
+ [D] Added the D language module.
+
+2010-11-12: vadz
+ Fix handling of multiple regex-using %renames attached to the same
+ declaration. For example, now
+
+ %rename("%(regex:/^Set(.*)/put\\1/)s") "";
+ %rename("%(regex:/^Get(.*)/get\\1/)s") "";
+
+ works as expected whereas before only the last anonymous rename was
+ taken into account.
+
+2010-10-17: drjoe
+ [R] Fix failure in overloaded functions which was breaking
+ QuantLib-SWIG
+
+2010-10-14: olly
+ [PHP] Allow compilation on non-conforming Microsoft C++ compilers
+ which don't accept: return function_returning_void();
+ Reported by Frank Vanden Berghen on the SWIG mailing list.
+
+2010-10-12: wsfulton
+ Fix unary scope operator (::) (global scope) regression introduced in 2.0.0, reported by
+ Ben Walker. The mangled symbol names were incorrect, sometimes resulting in types being
+ incorrectly treated as opaque types.
+
+ Also fixes #2958781 and some other type problems due to better typedef resolution, eg
+ std::vector<T *>::value_type didn't resolve to T * when it should have. The mangled type
+ was incorrectly SWIGTYPE_std__vectorT_Test_p_std__allocatorT_Test_p_t_t__value_type and now
+ it is correctly SWIGTYPE_p_Test.
+
+Version 2.0.1 (4 October 2010)
+==============================
+
+2010-10-03: wsfulton
+ Apply patch #3066958 from Mikael Johansson to fix default smart pointer
+ handling when the smart pointer contains both a const and non-const operator->.
+
+2010-10-01: wsfulton
+ Add -pcreversion option to display PCRE version information.
+
+2010-10-01: olly
+ [Ruby] Avoid segfault when a method node has no parentNode
+ (SF#3034054).
+
+2010-10-01: olly
+ [Python] Allow reinitialisation to work with an embedded Python
+ interpreter (patch from Jim Carroll in SF#3075178).
+
+2010-09-28: wsfulton
+ [C#] Apply patch from Tomas Dirvanauskas for std::map wrappers to avoid
+ throwing exceptions with normal usage of iterators.
+
+2010-09-27: olly
+ [Python] Improve error message given when a parameter of the wrong
+ type is passed to an overloaded method (SF#3027355).
+
+2010-09-25: wsfulton
+ Apply SF patch #3075150 - Java directors using static variables in
+ named namespace.
+
+2010-09-24: wsfulton
+ More file and line error/warning reporting fixes where SWIG macros
+ are used within {} braces (where the preprocessor expands macros),
+ for example macros within %inline {...} and %fragment(...) {...}
+ and nested structs.
+
+2010-09-18: wsfulton
+ More file and line error/warning reporting fixes for various inherited
+ class problems.
+
+2010-09-15: wsfulton
+ A much improved debugging of SWIG source experience is now available and
+ documented in the "Debugging SWIG" section in the Doc/Devel/internals.html
+ file, including a swig.dbg support file for the gdb debugger.
+
+2010-09-11: wsfulton
+ Fix incorrect line number reporting in errors/warnings when a macro
+ definition ends with '/' and it is not the end of a C comment.
+
+2010-09-11: wsfulton
+ Fix incorrect line number reporting in errors/warnings after parsing
+ macro invocations with parameters given over more than one line.
+
+2010-09-10: wsfulton
+ Remove extraneous extra line in preprocessed output after including files
+ which would sometimes lead to error/warning messages two lines after the
+ end of the file.
+
+2010-09-10: wsfulton
+ Fix #2149523 - Incorrect line number reporting in errors after parsing macros
+ containing C++ comments.
+
+2010-09-08: olly
+ [PHP] Fix handling of OUTPUT typemaps (Patch from Ryan in SF#3058394).
+
+2010-09-03: wsfulton
+ Fix erroneous line numbers in error messages for macro expansions, for example,
+ the error message now points to instantiation of the macro, ie the last line here:
+
+ #define MACRO2(a, b)
+
+ #define MACRO1(NAME) MACRO2(NAME,2,3)
+
+ MACRO1(abc)
+
+2010-09-02: wsfulton
+ Fix line numbers in error and warning messages for preprocessor messages within
+ %inline, for example:
+
+ %inline %{
+ #define FOOBAR 1
+ #define FOOBAR "hi"
+ %}
+
+2010-09-02: wsfulton
+ Fix line numbers in error and warning messages which were cumulatively one
+ less than they should have been after parsing each %include/%import - bug
+ introduced in swig-1.3.32. Also fix line numbers in error and warning messages
+ when new line characters appear between the %include / %import statement and
+ the filename.
+
+2010-08-30: wsfulton
+ Fix line number and file name reporting for some macro preprocessor warnings.
+ The line number of the macro argument has been corrected and the line number
+ of the start of the macro instead of one past the end of the macro is used.
+ Some examples:
+ file.h:11: Error: Illegal macro argument name '..'
+ file.h:19: Error: Macro 'DUPLICATE' redefined,
+ file.h:15: Error: previous definition of 'DUPLICATE'.
+ file.h:25: Error: Variable-length macro argument must be last parameter
+ file.h:32: Error: Illegal character in macro argument name
+ file.i:37: Error: Macro 'SIT' expects 2 arguments
+
+2010-08-26: wsfulton
+ Fix __LINE__ and __FILE__ expansion reported by Camille Gillot. Mostly this
+ did not work at all. Also fixes SF #2822822.
+
+2010-08-17: wsfulton
+ [Perl] Fix corner case marshalling of doubles - errno was not being correctly
+ set before calling strtod - patch from Justin Vallon - SF Bug #3038936.
+
+2010-08-17: wsfulton
+ Fix make distclean when some of the more obscure languages are detected by
+ configure - fixes from Torsten Landschoff.
+
+2010-07-28: wsfulton
+ Restore configuring out of source for the test-suite since it broke in 1.3.37.
+ As previously, if running 'make check-test-suite' out of source, it needs to be
+ done by invoking configure with a relative path. Invoking configure with an
+ absolute path will not work. Running the full 'make check' still needs to be
+ done in the source tree.
+
+2010-07-16: wsfulton
+ Fix wrapping of function pointers and member function pointers when the function
+ returns by reference.
+
+2010-07-13: vadz
+ Removed support for the old experimental "rxspencer" encoder and
+ "[not]rxsmatch" in %rename (see the 01/16/2006 entry). The new and
+ officially supported "regex" encoder and "[not]regexmatch" checks
+ should be used instead (see the two previous entries). Please
+ replace "%(rxspencer:[pat][subst])s" with "%(regex:/pat/subst/)s"
+ when upgrading. Notice that you will also need to replace the back-
+ references of form "@1" with the more standard "\\1" and may need to
+ adjust your regular expressions syntax as the new regex encoder uses
+ Perl-compatible syntax and not (extended) POSIX syntax as the old one.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2010-07-13: vadz
+ Add "regexmatch", "regextarget" and "notregexmatch" which can be
+ used to apply %rename directives to the declarations matching the
+ specified regular expression only. The first two can be used
+ interchangeably, both of the %renames below do the same thing:
+
+ %rename("$ignore", regexmatch$name="Old$") "";
+ %rename("$ignore", regextarget=1) "Old$";
+
+ (namely ignore the declarations having "Old" suffix).
+
+ "notregexmatch" restricts the match to only the declarations which
+ do not match the regular expression, e.g. here is how to rename to
+ lower case versions all declarations except those consisting from
+ capital letters only:
+
+ %rename("$(lowercase)s", notregexmatch$name="^[A-Z]+$") "";
+
+2010-07-13: vadz
+ Add the new "regex" encoder that can be used in %rename, e.g.
+
+ %rename("regex:/(\\w+)_(.*)/\\2/") "";
+
+ to remove any alphabetical prefix from all identifiers. The syntax
+ of the regular expressions is Perl-like and PCRE library
+ (http://www.pcre.org/) is used to implement this feature but notice
+ that backslashes need to be escaped as usual inside C strings.
+
+ Original patch from Torsten Landschoff.
+
+2010-07-08: wsfulton
+ Fix #3024875 - shared_ptr of classes with non-public destructors. This also fixes
+ the "unref" feature when used on classes with non-public destructors.
+
+2010-06-17: ianlancetaylor
+ [Go] Add the Go language module.
+
+2010-06-10: wsfulton
+ [Lua] Fix SWIG_lua_isnilstring multiply defined when using multiple
+ modules and wrapping strings. Patch from 'Number Cruncher'.
+
+2010-06-10: olly
+ [PHP] Fix directors to correctly call a method with has a
+ different name in PHP to C++ (we were always using the C++ name
+ in this case).
+
+2010-06-03: wsfulton
+ Fix uncompilable code when %rename results in two enum items
+ with the same name. Reported by Vadim Zeitlin.
+
+Version 2.0.0 (2 June 2010)
+===========================
+
+2010-06-02: wsfulton
+ [C#] Fix SWIG_STD_VECTOR_ENHANCED macro used in std::vector to work with
+ types containing commas, for example:
+
+ SWIG_STD_VECTOR_ENHANCED(std::pair< double, std::string >)
+
+2010-06-01: wsfulton
+ Add in std_shared_ptr.i for wrapping std::shared_ptr. Requires the %shared_ptr
+ macro like in the boost_shared_ptr.i library. std::tr1::shared_ptr can also be
+ wrapped if the following macro is defined:
+
+ #define SWIG_SHARED_PTR_SUBNAMESPACE tr1
+ %include <std_shared_ptr.i>
+
+ shared_ptr is also documented in Library.html now.
+
+2010-05-27: wsfulton
+ Add the ability for $typemap special variable macros to call other $typemap
+ special variable macros, for example:
+
+ %typemap(cstype) CC "CC"
+ %typemap(cstype) BB "$typemap(cstype, CC)"
+ %typemap(cstype) AA "$typemap(cstype, BB)"
+ void hah(AA aa);
+
+ This also fixes C# std::vector containers of shared_ptr and %shared_ptr.
+
+ Also added diagnostics for $typemap with -debug-tmsearch, for example, the
+ above displays additional diagnostic lines starting "Containing: ":
+
+ example.i:34: Searching for a suitable 'cstype' typemap for: AA aa
+ Looking for: AA aa
+ Looking for: AA
+ Using: %typemap(cstype) AA
+ Containing: $typemap(cstype, BB)
+ example.i:31: Searching for a suitable 'cstype' typemap for: BB
+ Looking for: BB
+ Using: %typemap(cstype) BB
+ Containing: $typemap(cstype, CC)
+ example.i:29: Searching for a suitable 'cstype' typemap for: CC
+ Looking for: CC
+ Using: %typemap(cstype) CC
+
+2010-05-26: olly
+ Fix %attribute2ref not to produce a syntax error if the last
+ argument (AccessorMethod) is omitted. Patch from David Piepgras
+ in SF#2235756.
+
+2010-05-26: olly
+ [PHP] When using %throws or %catches, SWIG-generated PHP5 wrappers
+ now throw PHP Exception objects instead of giving a PHP error of
+ type E_ERROR.
+
+ This change shouldn't cause incompatibility issues, since you can't
+ set an error handler for E_ERROR, so previously PHP would just exit
+ which also happens for unhandled exceptions. The benefit is you can
+ now catch them if you want to.
+
+ Fixes SF#2545578 and SF#2955522.
+
+2010-05-25: olly
+ [PHP] Add missing directorin typemap for const std::string &.
+ Fixes SF#3006404 reported by t-Legiaw.
+
+2010-05-23: wsfulton
+ [C#] Fix #2957375 - SWIGStringHelper and SWIGExceptionHelper not always being
+ initialized before use in .NET 4 as the classes were not marked beforefieldinit.
+ A static constructor has been added to the intermediary class like this:
+
+ %pragma(csharp) imclasscode=%{
+ static $imclassname() {
+ }
+ %}
+
+ If you had added your own custom static constructor to the intermediary class in
+ the same way as above, you will have to modify your approach to use static variable
+ initialization or define SWIG_CSHARP_NO_IMCLASS_STATIC_CONSTRUCTOR - See csharphead.swg.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2010-05-23: wsfulton
+ Fix #2408232. Improve shared_ptr and intrusive_ptr wrappers for classes in an
+ inheritance hierarchy. No special treatment is needed for derived classes.
+ The proxy class also no longer needs to be specified, it is automatically
+ deduced. The following macros are deprecated:
+ SWIG_SHARED_PTR(PROXYCLASS, TYPE)
+ SWIG_SHARED_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE)
+ and have been replaced by
+ %shared_ptr(TYPE)
+ Similarly for intrusive_ptr wrappers, the following macro is deprecated:
+ SWIG_INTRUSIVE_PTR(PROXYCLASS, TYPE)
+ SWIG_INTRUSIVE_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE)
+ and have been replaced by
+ %intrusive_ptr(TYPE)
+
+2010-05-21: olly
+ [PHP] Stop generating a bogus line of code in certain constructors.
+ This was mostly harmless, but caused a PHP notice to be issued, if
+ enabled (SF#2985684).
+
+2010-05-18: wsfulton
+ [Java] Fix member pointers on 64 bit platforms.
+
+2010-05-14: wsfulton
+ Fix wrapping of C++ enum boolean values reported by Torsten Landschoff:
+ typedef enum { PLAY = true, STOP = false } play_state;
+
+2010-05-14: olly
+ [PHP] Fix wrapping of global variables which was producing
+ uncompilable code in some cases.
+
+2010-05-12: drjoe
+ [R] Add two more changes from Wil Nolan. Get garbage
+ collection to work. Implement newfree
+
+2010-05-09: drjoe
+ Fix bug reported by Wil Nolan change creation of string so
+ that R 2.7.0+ can use char hashes
+
+2010-05-07: wsfulton
+ Apply patch #2955146 from Sergey Satskiy to fix expressions containing divide by
+ operator in constructor initialization lists.
+
+2010-05-05: wsfulton
+ [R] Memory leak fix handling const std::string & inputs, reported by Will Nolan.
+
+2010-05-01: wsfulton
+ Typemap matching enhancement for non-default typemaps. Previously all
+ qualifiers were stripped in one step, now they are stripped one at a time
+ starting with the left most qualifier. For example, int const*const
+ is first stripped to int *const then int *.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2010-04-25: bhy
+ [Python] Fix #2985655 - broken constructor renaming.
+
+2010-04-14: wsfulton
+ Typemap fragments are now official and documented in Typemaps.html.
+
+2010-04-09: wsfulton
+ [Ruby] Fix #2048064 and #2408020.
+ Apply Ubuntu patch to fix Ruby and std::vector wrappers with -minherit.
+ https://bugs.launchpad.net/ubuntu/+source/swig1.3/+bug/522874
+
+2010-04-09: wsfulton
+ [Mzscheme] Apply Ubuntu patch to fix std::map wrappers:
+ https://bugs.launchpad.net/ubuntu/+source/swig1.3/+bug/203876
+
+2010-04-09: wsfulton
+ [Python] Apply patch #2952374 - fix directors and the -nortti option.
+
+2010-04-09: wsfulton
+ [Lua] Fix #2887254 and #2946032 - SWIG_Lua_typename using wrong stack index.
+
+2010-04-03: wsfulton
+ [Python] Fix exceptions being thrown with the -threads option based on patch from Arto Vuori.
+ Fixes bug #2818499.
+
+2010-04-03: wsfulton
+ Fix Makefile targets: distclean and maintainer-clean
+
+2010-04-02: wsfulton
+ [Lua] Fix char pointers, wchar_t pointers and char arrays so that nil can be passed as a
+ valid value. Bug reported by Gedalia Pasternak.
+
+2010-04-01: wsfulton
+ Numerous subtle typemap matching rule fixes when using the default type. The typemap
+ matching rules are to take a type and find the best default typemap (SWIGTYPE, SWIGTYPE* etc),
+ then look for the next best match by reducing the chosen default type. The type deduction
+ now follows C++ class template partial specialization matching rules.
+
+ Below are the set of changes made showing the default type deduction
+ along with the old reduced type and the new version of the reduced type:
+
+ SWIGTYPE const &[ANY]
+ new: SWIGTYPE const &[]
+ old: SWIGTYPE (&)[ANY]
+
+ SWIGTYPE *const [ANY]
+ new: SWIGTYPE const [ANY]
+ old: SWIGTYPE *[ANY]
+
+ SWIGTYPE const *const [ANY]
+ new: SWIGTYPE *const [ANY]
+ old: SWIGTYPE const *[ANY]
+
+ SWIGTYPE const *const &
+ new: SWIGTYPE *const &
+ old: SWIGTYPE const *&
+
+ SWIGTYPE *const *
+ new: SWIGTYPE const *
+ old: SWIGTYPE **
+
+ SWIGTYPE *const &
+ new: SWIGTYPE const &
+ old: SWIGTYPE *&
+
+ Additionally, a const SWIGTYPE lookup is used now for any constant type. Some examples, where
+ T is some reduced type, eg int, struct Foo:
+
+ T const
+ new: SWIGTYPE const
+ old: SWIGTYPE
+
+ T *const
+ new: SWIGTYPE *const
+ old: SWIGTYPE *
+
+ T const[]
+ new: SWIGTYPE const[]
+ old: SWIGTYPE[]
+
+ enum T const
+ new: enum SWIGTYPE const
+ old: enum SWIGTYPE
+
+ T (*const )[]
+ new: SWIGTYPE (*const )[]
+ old: SWIGTYPE (*)[]
+
+ Reminder: the typemap matching rules can now be seen for any types being wrapped by using
+ either the -debug-tmsearch or -debug-tmused options.
+
+ In practice this leads to some subtle matching rule changes and the majority of users
+ won't notice any changes, except in the prime area of motivation for this change: Improve
+ STL containers of const pointers and passing const pointers by reference. This is fixed
+ because many of the STL containers use a type 'T const&' as parameters and when T is
+ a const pointer, for example, 'K const*', then the full type is 'K const*const&'. This
+ means that the 'SWIGTYPE *const&' typemaps now match when T is either a non-const or
+ const pointer. Furthermore, some target languages incorrectly had 'SWIGTYPE *&' typemaps
+ when these should have been 'SWIGTYPE *const&'. These have been corrected (Java, C#, Lua, PHP).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2010-03-13: wsfulton
+ [Java] Some very old deprecated pragma warnings are now errors.
+
+2010-03-13: wsfulton
+ Improve handling of file names and directories containing double/multiple path separators.
+
+2010-03-10: mutandiz (Mikel Bancroft)
+ [allegrocl] Use fully qualified symbol name of cl::identity in emit_defun().
+
+2010-03-06: wsfulton
+ [Java] The intermediary JNI class modifiers are now public by default meaning these
+ intermediary low level functions are now accessible by default from outside any package
+ used. The proxy class pointer constructor and getCPtr() methods are also now public.
+ These are needed in order for the nspace option to work without any other mods.
+ The previous default of protected access can be restored using:
+
+ SWIG_JAVABODY_METHODS(protected, protected, SWIGTYPE)
+ %pragma(java) jniclassclassmodifiers = "class"
+
+2010-03-06: wsfulton
+ [C#] Added the nspace feature for C#. Documentation for the nspace feature is now available.
+
+2010-03-04: wsfulton
+ Added the nspace feature. This adds some improved namespace support. Currently only Java
+ is supported for target languages, where C++ namespaces are automatically translated into
+ Java packages. The feature only applies to classes,struct,unions and enums declared within
+ a namespace. Methods and variables declared in namespaces still effectively have their
+ namespaces flattened. Example usage:
+
+ %feature(nspace) Outer::Inner1::Color;
+ %feature(nspace) Outer::Inner2::Color;
+
+ namespace Outer {
+ namespace Inner1 {
+ struct Color {
+ ...
+ };
+ }
+ namespace Inner2 {
+ struct Color {
+ ...
+ };
+ }
+ }
+
+ For Java, the -package option is also required when using the nspace feature. Say
+ we use -package com.myco, the two classes can then be accessed as follows from Java:
+
+ com.myco.Outer.Inner1.Color and com.myco.Outer.Inner2.Color.
+
+2010-02-27: wsfulton
+ [Python] Remove -dirvtable from the optimizations included by -O as it this option
+ currently leads to memory leaks as reported by Johan Blake.
+
+2010-02-27: wsfulton
+ License code changes: SWIG Source is GPL-v3 and library code license is now clearer
+ and is provided under a very permissive license. See https://www.swig.org/legal.html.
+
+2010-02-13: wsfulton
+ [Ruby] A few fixes for compiling under ruby-1.9.x including patch from 'Nibble'.
+
+2010-02-13: wsfulton
+ [Ruby] Apply patch from Patrick Bennett to fix RARRAY_LEN and RARRAY_PTR usage for Ruby 1.9.x
+ used in various STL wrappers.
+
+2010-02-13: wsfulton
+ [C#, Java] Fix incorrect multiply defined symbol name error when an enum item
+ and class name have the same name, as reported by Nathan Krieger. Example:
+
+ class Vector {};
+ namespace Text {
+ enum Preference { Vector };
+ }
+
+ This also fixes other incorrect corner case target language symbol name clashes.
+
+2010-02-11: wsfulton
+ Add the -debug-lsymbols option for displaying the target language layer symbols.
+
+2010-02-09: wsfulton
+ Fix -MM and -MMD options on Windows. They were not omitting files in the SWIG library as
+ they should be.
+
+2010-02-08: wsfulton
+ Fix #1807329 - When Makefile dependencies are being generated using the -M family of options
+ on Windows, the file paths have been corrected to use single backslashes rather than double
+ backslashes as path separators.
+
+2010-02-06: wsfulton
+ Fix #2918902 - language specific files not being generated in correct directory on
+ Windows when using forward slashes for -o, for example:
+ swig -python -c++ -o subdirectory/theinterface_wrap.cpp subdirectory/theinterface.i
+
+2010-02-05: wsfulton
+ Fix #2894405 - assertion when using -xmlout.
+
+2010-01-28: wsfulton
+ Fix typemap matching bug when a templated type has a typemap both specialized and not
+ specialized. For example:
+
+ template<typename T> struct XX { ... };
+ %typemap(in) const XX & "..."
+ %typemap(in) const XX< int > & "..."
+
+ resulted in the 2nd typemap being applied for all T in XX< T >.
+
+2010-01-22: wsfulton
+ Fix #2933129 - typemaps not being found when the unary scope operator (::) is used to denote
+ global scope, the typemap is now used in situations like this:
+
+ struct X {};
+ %typemap(in) const X & "..."
+ void m(const ::X &);
+
+ and this:
+
+ struct X {};
+ %typemap(in) const ::X & "..."
+ void m(const X &);
+
+2010-01-20: wsfulton
+ Fix some unary scope operator (::) denoting global scope problems in the types generated
+ into the C++ layer. Previously the unary scope operator was dropped in the generated code
+ if the type had any sort of qualifier, for example when using pointers, references, like
+ ::foo*, ::foo&, bar< ::foo* >.
+
+2010-01-13: olly
+ [PHP] Add datetime to the list of PHP predefined classes (patch
+ from David Fletcher in SF#2931042).
+
+2010-01-11: wsfulton
+ Slight change to warning, error and diagnostic reporting. The warning number is no
+ longer shown within brackets. This is to help default parsing of warning messages by
+ other tools, vim on Unix in particular.
+
+ Example original display using -Fstandard:
+ example.i:20: Warning(401): Nothing known about base class 'B'. Ignored.
+ New display:
+ example.i:20: Warning 401: Nothing known about base class 'B'. Ignored.
+
+ Also subtle fix to -Fmicrosoft format adding in missing space. Example original display:
+ example.i(20): Warning(401): Nothing known about base class 'Base'. Ignored.
+ New display:
+ example.i(20) : Warning 401: Nothing known about base class 'Base'. Ignored.
+
+2010-01-10: wsfulton
+ Fix a few inconsistencies in reporting of file/line numberings including modifying
+ the overload warnings 509, 512, 516, 474, 475 to now be two line warnings.
+
+2010-01-10: wsfulton
+ Modify -debug-tags output to use standard file name/line reporting so that editors
+ can easily navigate to the appropriate lines.
+ Was typically:
+ . top . include . include (/usr/share/swig/temp/trunk/Lib/swig.swg:312)
+ . top . include . include . include (/usr/share/swig/temp/trunk/Lib/swigwarnings.swg:39)
+ now:
+ /usr/share/swig/temp/trunk/Lib/swig.swg:312: . top . include . include
+ /usr/share/swig/temp/trunk/Lib/swigwarnings.swg:39: . top . include . include . include
+
+2010-01-03: wsfulton
+ Fix missing file/line numbers for typemap warnings and in output from the
+ -debug-tmsearch/-debug-tmused options.
+
+2010-01-03: wsfulton
+ Add typemaps used debugging option (-debug-tmused). When used each line displays
+ the typemap used for each type for which code is being generated including the file
+ and line number related to the type. This is effectively a condensed form of the
+ -debug-tmsearch option. Documented in Typemaps.html.
+
+2009-12-23: wsfulton
+ Fix for %javaexception and directors so that all the appropriate throws clauses
+ are generated. Problem reported by Peter Greenwood.
+
+2009-12-20: wsfulton
+ Add -debug-tmsearch option for debugging the typemap pattern matching rules.
+ Documented in Typemaps.html.
+
+2009-12-12: wsfulton
+ [Octave] Remove the -api option and use the new OCTAVE_API_VERSION_NUMBER
+ macro provided in the octave headers for determining the api version instead.
+
+2009-12-04: olly
+ [Ruby] Improve support for Ruby 1.9 under GCC. Addresses part of
+ SF#2859614.
+
+2009-12-04: olly
+ Fix handling of modulo operator (%) in constant expressions
+ (SF#2818562).
+
+2009-12-04: olly
+ [PHP] "empty" is a reserved word in PHP, so rename empty() method
+ on STL classes to "is_empty()" (previously this was automatically
+ renamed to "c_empty()").
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-12-03: olly
+ [PHP] Add typemaps for long long and unsigned long long, and for
+ pointer to method.
+
+2009-12-02: olly
+ [PHP] Fix warning and rename of reserved class name to be case
+ insensitive.
+
+2009-12-01: wsfulton
+ Revert support for %extend and memberin typemaps added in swig-1.3.39. The
+ memberin typemaps are ignored again for member variables within a %extend block.
+ Documentation inconsistency reported by Torsten Landschoff.
+
+2009-11-29: wsfulton
+ [Java, C#] Fix generated quoting when using %javaconst(1)/%csconst(1) for
+ static const char member variables.
+
+ %javaconst(1) A;
+ %csconst(1) A;
+ struct X {
+ static const char A = 'A';
+ };
+
+2009-11-26: wsfulton
+ [Java, C#] Fix %javaconst(1)/%csconst(1) for static const member variables to
+ use the actual constant value if it is specified, rather than the C++ code to
+ access the member.
+
+ %javaconst(1) EN;
+ %csconst(1) EN;
+ struct X {
+ static const int EN = 2;
+ };
+
+2009-11-23: wsfulton
+ C++ nested typedef classes can now be handled too, for example:
+ struct Outer {
+ typedef Foo { } FooTypedef1, FooTypedef2;
+ };
+
+2009-11-18: wsfulton
+ The wrappers for C nested structs are now generated in the same order as declared
+ in the parsed code.
+
+2009-11-18: wsfulton
+ Fix #491476 - multiple declarations of nested structs, for example:
+ struct Outer {
+ struct {
+ int val;
+ } inner1, inner2, *inner3, inner4[1];
+ } outer;
+
+2009-11-17: wsfulton
+ Fix parsing of enum declaration and initialization, for example:
+
+ enum ABC {
+ a,
+ b,
+ c
+ } A = a, *pC = &C, array[3] = {a, b, c};
+
+2009-11-17: wsfulton
+ Fix parsing of struct declaration and initialization, for example:
+
+ struct S {
+ int x;
+ } instance = { 10 };
+
+2009-11-15: wsfulton
+ Fix #1960977 - Syntax error parsing derived nested class declaration and member
+ variable instance.
+
+2009-11-14: wsfulton
+ Fix #2310483 - function pointer typedef within extern "C" block.
+
+2009-11-13: wsfulton
+ Fix usage of nested template classes within templated classes so that compilable code
+ is generated.
+
+2009-11-13: olly
+ [php] Fix place where class prefix (as specified with -prefix)
+ wasn't being used. Patch from gverbruggen in SF#2892647.
+
+2009-11-12: wsfulton
+ Fix usage of nested template classes so that compilable code is generated - the nested
+ template class is now treated like a normal nested classes, that is, as an opaque type
+ unless the nestedworkaround feature is used.
+
+2009-11-12: wsfulton
+ Replace SWIGWARN_PARSE_NESTED_CLASS with SWIGWARN_PARSE_NAMED_NESTED_CLASS and
+ SWIGWARN_PARSE_UNNAMED_NESTED_CLASS for named and unnamed nested classes respectively.
+
+ Named nested class ignored warnings can now be suppressed by name using %warnfilter, eg:
+
+ %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::Inner;
+
+ but clearly unnamed nested classes cannot and the global suppression is still required, eg:
+
+ #pragma SWIG nowarn=SWIGWARN_PARSE_UNNAMED_NESTED_CLASS
+
+2009-11-11: wsfulton
+ Added the nestedworkaround feature as a way to use the full functionality of a nested class
+ (C++ mode only). It removes the nested class from SWIG's type information so it is as if SWIG
+ had never parsed the nested class. The documented nested class workarounds using a global
+ fake class stopped working when SWIG treated the nested class as an opaque pointer, and
+ this feature reverts this behaviour. The documentation has been updated with details of how
+ to use and implement it, see the "Nested classes" section in SWIGPlus.html.
+
+2009-11-11: wsfulton
+ There were a number of C++ cases where nested classes/structs/unions were being handled
+ as if C code was being parsed which would oftentimes lead to uncompilable code as an
+ attempt was made to wrap the nested structs like it is documented for C code. Now all
+ nested structs/classes/unions are ignored in C++ mode, as was always documented. However,
+ there is an improvement as usage of nested structs/classes/unions is now always treated
+ as an opaque type by default, resulting in generated code that should always compile.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-11-09: drjoe
+ Fix R for -fcompact and add std_map.i
+
+2009-11-08: wsfulton
+ Fix inconsistency for nested structs/unions/classes. Uncompilable code was being
+ generated when inner struct and union declarations were used as types within the
+ inner struct. The inner struct/union is now treated as a forward declaration making the
+ behaviour the same as an inner class. (C++ code), eg:
+
+ struct Outer {
+ struct InnerStruct { int x; };
+ InnerStruct* getInnerStruct();
+ };
+
+2009-11-08: wsfulton
+ Ignored nested class/struct warnings now display the name of the ignored class/struct.
+
+2009-11-07: wsfulton
+ Bug #1514681 - Fix nested template classes within a namespace generated uncompilable
+ code and introduced strange side effects to other wrapper code especially code
+ after the nested template class. Note that nested template classes are still ignored.
+
+2009-11-07: wsfulton
+ Add new debug options:
+ -debug-symtabs - Display symbol tables information
+ -debug-symbols - Display target language symbols in the symbol tables
+ -debug-csymbols - Display C symbols in the symbol tables
+
+2009-11-03: wsfulton
+ Fix some usage of unary scope operator (::) denoting global scope, for example:
+
+ namespace AA { /* ... */ }
+ using namespace ::AA;
+
+ and bug #1816802 - SwigValueWrapper should be used:
+
+ struct CC {
+ CC(int); // no default constructor
+ };
+ ::CC x();
+
+ and in template parameter specializations:
+
+ struct S {};
+ template <typename T> struct X { void a() {} };
+ template <> struct X<S> { void b() {} };
+ %template(MyTConcrete) X< ::S >;
+
+ plus probably some other corner case usage of ::.
+
+2009-11-02: olly
+ [Python] Fix potential memory leak in initialisation code for the
+ generated module.
+
+2009-10-23: wsfulton
+ Fix seg fault when using a named nested template instantiation using %template(name)
+ within a class. A warning that these are not supported is now issued plus processing
+ continues as if no name was given.
+
+2009-10-20: wsfulton
+ [Python] Fix std::vector<const T*>. This would previously compile, but not run correctly.
+
+2009-10-20: wsfulton
+ Fixed previously fairly poor template partial specialization and explicit
+ specialization support. Numerous bugs in this area have been fixed including:
+
+ - Template argument deduction implemented for template type arguments, eg this now
+ works:
+ template<typename T> class X {};
+ template<typename T> class X<T *> {};
+ %template(X1) X<const int *>; // Chooses T * specialization
+
+ and more complex cases with multiple parameters and a mix of template argument
+ deduction and explicitly specialised parameters, eg:
+ template <typename T1, typename T2> struct TwoParm { void a() {} };
+ template <typename T1> struct TwoParm<T1 *, int *> { void e() {} };
+ %template(E) TwoParm<int **, int *>;
+
+ Note that the primary template must now be in scope, like in C++, when
+ an explicit or partial specialization is instantiated with %template.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-09-14: wsfulton
+ [C#] Add %csattributes for adding C# attributes to enum values, see docs for example.
+
+2009-09-11: wsfulton
+ Fix memmove regression in cdata.i as reported by Adriaan Renting.
+
+2009-09-07: wsfulton
+ Fix constant expressions containing <= or >=.
+
+2009-09-02: wsfulton
+ The following operators in constant expressions now result in type bool for C++
+ wrappers and remain as type int for C wrappers, as per each standard:
+
+ && || == != < > <= >= (Actually the last 4 are still broken). For example:
+
+ #define A 10
+ #define B 10
+ #define A_EQ_B A == B // now wrapped as type bool for C++
+ #define A_AND_B A && B // now wrapped as type bool for C++
+
+2009-09-02: wsfulton
+ Fix #2845746. true and false are now recognised keywords (only when wrapping C++).
+ Constants such as the following are now wrapped (as type bool):
+ #define FOO true
+ #define BAR FOO && false
+
+Version 1.3.40 (18 August 2009)
+===============================
+
+2009-08-17: olly
+ [Perl] Add "#undef do_exec" to our clean up of Perl global
+ namespace pollution.
+
+2009-08-17: olly
+ [PHP] Fix to wrap a resource returned by __get() in a PHP object (SF#2549217).
+
+2009-08-17: wsfulton
+ Fix #2797485 After doing a 'make clean', install fails if yodl2man or yodl2html
+ is not available.
+
+2009-08-16: wsfulton
+ [Octave] Caught exceptions display the type of the C++ exception instead of the
+ generic "c++-side threw an exception" message.
+
+2009-08-16: wsfulton
+ [Java] When %catches is used, fix so that any classes specified in the "throws"
+ attribute of the "throws" typemap are generated into the Java method's throws clause.
+
+2009-08-16: wsfulton
+ [C#] Fix exception handling when %catches is used, reported by Juan Manuel Alvarez.
+
+2009-08-15: wsfulton
+ Fix %template seg fault on some cases of overloading the templated method.
+ Bug reported by Jan Kupec.
+
+2009-08-15: wsfulton
+ [Ruby] Add numerous missing wrapped methods for std::vector<bool> specialization
+ as reported by Youssef Jones.
+
+2009-08-14: wsfulton
+ [Perl] Add SWIG_ConvertPtrAndOwn() method into the runtime for smart pointer
+ memory ownership control. shared_ptr support still to be added. Patch from
+ David Fletcher.
+
+2009-08-14: olly
+ [PHP] PHP5 now wraps static member variables as documented.
+
+2009-08-14: olly
+ [PHP] Update the PHP "class" example to work with PHP5 and use
+ modern wrapping features.
+
+2009-08-13: wsfulton
+ [PHP] std::vector wrappers overhaul. They no longer require the
+ specialize_std_vector() macro. Added wrappers for capacity() and reserve().
+
+2009-08-13: wsfulton
+ [PHP] Add const reference typemaps. const reference primitive types are
+ now passed by value rather than pointer like the other target languages.
+ Fixes SF#2524029.
+
+2009-08-08: wsfulton
+ [Python] More user friendly AttributeError is raised when there are
+ no constructors generated for the proxy class in the event that the
+ class is abstract - the error message is now
+ "No constructor defined - class is abstract" whereas if there are no
+ public constructors for any other reason and the class is not abstract,
+ the message remains
+ "No constructor defined".
+ [tcl] Similarly for tcl when using -itcl.
+
+2009-08-04: olly
+ [PHP] Fix generated code to work with PHP 5.3.
+
+2009-08-04: vmiklos
+ [PHP] Various mathematical functions (which would conflict
+ with the built-in PHP ones) are now automatically handled by
+ adding a 'c_' prefix.
+
+2009-08-03: wsfulton
+ [C#] The std::vector<T> implementation is improved and now uses $typemap such
+ that the proxy class for T no longer has to be specified in some macros
+ for correct C# compilation; the following macros are deprecated, where
+ CSTYPE was the C# type for the C++ class CTYPE:
+
+ SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE)
+ usage should be removed altogether
+
+ SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE)
+ should be replaced with:
+ SWIG_STD_VECTOR_ENHANCED(CTYPE)
+
+ Some more details in csharp/std_vector.i
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-07-31: olly
+ [Python] Fix indentation so that we give a useful error if the
+ module can't be loaded. Patch from Gaetan Lehmann in SF#2829853.
+
+2009-07-29: wsfulton
+ Add $typemap(method, typelist) special variable macro. This allows
+ the contents of a typemap to be inserted within another typemap.
+ Fully documented in Typemaps.html.
+
+2009-07-29: vmiklos
+ [PHP] Static member variables are now prefixed with the
+ class name. This allows static member variables with the
+ same name in different classes.
+
+2009-07-29: olly
+ [Python] Add missing locks to std::map wrappers. Patch from
+ Paul Hampson in SF#2813836.
+
+2009-07-29: olly
+ [PHP] Fix memory leak in PHP OUTPUT typemaps. Reported by Hitoshi
+ Amano in SF#2826322.
+
+2009-07-29: olly
+ [PHP] Fix memory leak in PHP resource destructor for classes
+ without a destructor and non-class types. Patch from Hitoshi Amano
+ in SF#2825303.
+
+2009-07-28: olly
+ [PHP] Update warnings about clashes between identifiers and PHP
+ keywords and automatic renaming to work with the PHP5 class
+ wrappers. Fixes SF#1613679.
+
+2009-07-28: vmiklos
+ [PHP] If a member function is not public but it has a base
+ which is public, then now a warning is issued and the member
+ function will be public, as PHP requires this.
+
+2009-07-21: vmiklos
+ [PHP] Director support added.
+
+2009-07-15: olly
+ [Perl] Don't specify Perl prototype "()" for a constructor with a
+ different name to the class, as such constructors can still take
+ parameters.
+
+2009-07-12: xavier98
+ [Octave] Add support for Octave 3.2 API
+
+2009-07-05: olly
+ [PHP] Update the list of PHP keywords - "cfunction" is no longer a
+ keyword in PHP5 and PHP 5.3 added "goto", "namespace", "__DIR__",
+ and "__NAMESPACE__".
+
+2009-07-03: olly
+ [Tcl] To complement USE_TCL_STUBS, add support for USE_TK_STUBS
+ and SWIG_TCL_STUBS_VERSION. Document all three in the Tcl chapter
+ of the manual. Based on patch from SF#2810380 by Christian
+ Gollwitzer.
+
+2009-07-02: vmiklos
+ [PHP] Added factory.i for PHP, see the li_factory testcase
+ for more info on how to use it.
+
+2009-07-02: wsfulton
+ Fix -Wallkw option as reported by Solomon Gibbs.
+
+2009-07-02: wsfulton
+ Fix syntax error when a nested struct contains a comment containing a * followed
+ eventually by a /. Regression from 1.3.37, reported by Solomon Gibbs.
+
+2009-07-01: vmiklos
+ [PHP] Unknown properties are no longer ignored in proxy
+ classes.
+
+2009-07-01: vmiklos
+ [PHP] Fixed %newobject behaviour, previously any method
+ marked with %newobject was handled as a constructor.
+
+2009-06-30: olly
+ [Ruby] Undefine close and connect macros defined by Ruby API
+ headers as we don't need them and they can clash with C++ methods
+ being wrapped. Patch from Vit Ondruch in SF#2814430.
+
+2009-06-26: olly
+ [Ruby] Fix to handle FIXNUM values greater than MAXINT passed for a
+ double parameter.
+
+2009-06-24: wsfulton
+ Fix wrapping methods with default arguments and the compactdefaultargs feature
+ where a class is passed by value and is assigned a default value. The SwigValueWrapper
+ template workaround for a missing default constructor is no longer used as the code
+ generated does not call the default constructor.
+
+2009-06-16: wsfulton
+ [Java,C#] Fix enum marshalling when %ignore is used on one of the enum items.
+ Incorrect enum values were being passed to the C++ layer or compilation errors resulted.
+
+2009-06-02: talby
+ [Perl] Resolved reference.i overload support problem
+ identified by John Potowsky.
+
+2009-05-26: wsfulton
+ [C#] Improved std::map wrappers based on patch from Yuval Baror. The C# proxy
+ now implements System.Collections.Generic.IDictionary<>.
+
+ These std:map wrappers have a non-backwards compatible overhaul to make them
+ like a .NET IDictionary. Some method names have changed as following:
+ set -> setitem (use this[] property now)
+ get -> getitem (use this[] property now)
+ has_key -> ContainsKey
+ del -> Remove
+ clear -> Clear
+
+ The following macros used for std::map wrappers are deprecated and will no longer work:
+ specialize_std_map_on_key
+ specialize_std_map_on_value
+ specialize_std_map_on_both
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-05-20: vmiklos
+ [PHP] Add the 'thisown' member to classes. The usage of it
+ is the same as the Python thisown one: it's 1 by default and
+ you can set it to 0 if you want to prevent freeing it. (For
+ example to prevent a double free.)
+
+2009-05-14: bhy
+ [Python] Fix the wrong pointer value returned by SwigPyObject_repr().
+
+2009-05-13: mutandiz (Mikel Bancroft)
+ [allegrocl] Minor tweak when wrapping in -nocwrap mode.
+
+2009-05-11: wsfulton
+ [C#] Improved std::vector wrappers on the C# proxy side from Yuval Baror. These
+ implement IList<> instead of IEnumerable<> where possible.
+
+2009-04-29: wsfulton
+ [Java, C#] Add the 'notderived' attribute to the javabase and csbase typemaps.
+ When this attribute is set, the typemap will not apply to classes that are derived
+ from a C++ base class, eg
+ %typemap(csbase, notderived="1") SWIGTYPE "CommonBase"
+
+2009-04-29: olly
+ [Python] Don't attempt to acquire the GIL in situations where we
+ know that it will already be locked. This avoids some dead-locks
+ with mod_python (due to mod_python bugs which are apparently
+ unlikely to ever be fixed), and results in smaller wrappers which
+ run a little faster (in tests with Xapian on x86-64 Ubuntu 9.04,
+ the stripped wrapper library was 11% smaller and ran 2.7% faster).
+
+2009-04-21: wsfulton
+ [C#] Fix #2753469 - bool &OUTPUT and bool *OUTPUT typemaps initialisation.
+
+2009-04-09: wsfulton
+ Fix #2746858 - C macro expression using floating point numbers
+
+2009-03-30: olly
+ [PHP] The default out typemap for char[ANY] now returns the string up to a
+ zero byte, or the end of the array if there is no zero byte. This
+ is the same as Python does, and seems more generally useful than
+ the previous behaviour of returning the whole contents of the array
+ including any zero bytes. If you want the old behaviour, you can provide
+ your own typemap to do this:
+
+ %typemap(out) char [ANY]
+ %{
+ RETVAL_STRINGL($1, $1_dim0, 1);
+ %}
+
+Version 1.3.39 (21 March 2009)
+==============================
+
+2009-03-19: bhy
+ [Python] Fix the memory leak related to Python 3 unicode and C char* conversion,
+ which can be shown in the following example before this fix:
+
+ from li_cstring import *
+ i=0
+ while True:
+ i += 1
+ n = str(i)*10
+ test3(n)
+
+ This fix affected SWIG_AsCharPtrAndSize() so you cannot call this function with
+ a null alloc and non-null cptr argument in Python 3, otherwise a runtime error
+ will be raised.
+
+2009-03-18: wsfulton
+ [C#] std::vector<T> wrapper improvements for .NET 2 and also providing the
+ necessary machinery to use the std::vector<T> wrappers with more advanced features such
+ as LINQ - the C# proxy class now derives from IEnumerable<>. The default is now to
+ generate code requiring .NET 2 as a minimum, although the C# code can be compiled
+ for .NET 1 by defining the SWIG_DOTNET_1 C# preprocessor constant. See the
+ std_vector.i file for more details.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2009-03-12: wsfulton
+ [Ruby] Fix #2676738 SWIG generated symbol name clashes.
+
+2009-03-01: bhy
+ [Python] Some fixes for Python 3.0.1 and higher support. In 3.0.1, the C API function
+ PyObject_Compare is removed, so PyObject_RichCompareBool is used for replacement.
+ Struct initilization of SwigPyObject and SwigPyObject_as_number changed to reflect
+ the drop of tp_compare and nb_long.
+
+2009-03-01: bhy
+ [Python] Fix SF#2583160. Now the importer in Python shadow wrapper take care of the
+ case that module already imported at other place.
+
+2009-02-28: bhy
+ [Python] Fix SF#2637352. Move struct declaration of SWIG_module in pyinit.swg before
+ the method calls, since some C compiler don't allow declaration in middle of function
+ body.
+
+2009-02-21: wsfulton
+ [Allegrocl] Fix seg fault wrapping some constant variable (%constant) types.
+
+2009-02-20: wsfulton
+ [CFFI] Fix seg faults when for %extend and using statements.
+
+2009-02-20: wsfulton
+ Fix SF #2605955: -co option which broke in 1.3.37.
+
+2009-02-20: wsfulton
+ New %insert("begin") section added. Also can be used as %begin. This is a new
+ code section reserved entirely for users and the code within the section is generated
+ at the top of the C/C++ wrapper file and so provides a means to put custom code
+ into the wrapper file before anything else that SWIG generates.
+
+2009-02-17: wsfulton
+ 'make clean-test-suite' will now run clean on ALL languages. Previously it only
+ ran the correctly configured languages. This way it is now possible to clean up
+ properly after running 'make partialcheck-test-suite'.
+
+2009-02-14: wsfulton
+ Extend attribute library support for structs/classes and the accessor functions use
+ pass/return by value semantics. Two new macros are available and usage is identical
+ to %attribute. These are %attributeval for structs/classes and %attributestring for
+ string classes, like std::string. See attribute.swg for more details.
+
+2009-02-13: wsfulton
+ Add support for %extend and memberin typemaps. Previously the memberin typemaps were
+ ignored for member variables within a %extend block.
+
+2009-02-12: wsfulton
+ Remove unnecessary temporary variable when wrapping return values that are references.
+ Example of generated code for wrapping:
+
+ struct XYZ {
+ std::string& refReturn();
+ };
+
+ used to be:
+
+ std::string *result = 0 ;
+ ...
+ {
+ std::string &_result_ref = (arg1)->refReturn();
+ result = (std::string *) &_result_ref;
+ }
+
+ Now it is:
+
+ std::string *result = 0 ;
+ ...
+ result = (std::string *) &(arg1)->refReturn();
+
+2009-02-08: bhy
+ Change the SIZE mapped by %pybuffer_mutable_binary and %pybuffer_binary in pybuffer.i from
+ the length of the buffer to the number of items in the buffer.
+
+2009-02-08: wsfulton
+ Fix %feature not working for conversion operators, reported by Matt Sprague, for example:
+ %feature("cs:methodmodifiers") operator bool "protected";
+
+2009-02-07: wsfulton
+ [MzScheme] Apply #2081967 configure changes for examples to build with recent PLT versions.
+ Also fixes Makefile errors building SWIG executable when mzscheme package is installed
+ (version 3.72 approx and later).
+
+2009-02-04: talby
+ [Perl] Fix SF#2564192 reported by David Kolovratnk.
+ SWIG_AsCharPtrAndSize() now handles "get" magic.
+
+Version 1.3.38 (31 January 2009)
+================================
+
+2009-01-31: bhy
+ [Python] Fix SF#2552488 reported by Gaetan Lehmann. Now %pythonprepend
+ and %pythonappend have correct indentation.
+
+2009-01-31: bhy
+ [Python] Fix SF#2552048 reported by Gaetan Lehmann. The parameter list
+ of static member function in generated proxy code should not have the
+ 'self' parameter.
+
+2009-01-29: wsfulton
+ Fix regression introduced in 1.3.37 where the default output directory
+ for target language specific files (in the absence of -outdir) was no
+ longer the same directory as the generated c/c++ file.
+
+2009-01-28: wsfulton
+ [Java, C#] Fix proxy class not being used when the global scope operator
+ was used for parameters passed by value. Reported by David Piepgrass.
+
+2009-01-15: wsfulton
+ [Perl] Fix seg fault when running with -v option, reported by John Ky.
+
+Version 1.3.37 (13 January 2009)
+================================
+
+2009-01-13: mgossage
+ [Lua] Added contract support for requiring that unsigned numbers are >=0
+ Rewrote much of Examples/Lua/embed3.
+ Added a lot to the Lua documentation.
+
+2009-01-13: wsfulton
+ Fix compilation error when using directors on protected virtual overloaded
+ methods reported by Sam Hendley.
+
+2009-01-12: drjoe
+ [R] Fixed handling of integer arrays
+
+2009-01-10: drjoe
+ [R] Fix integer handling in r to deal correctly with signed
+ and unsigned issues
+
+2009-01-10: wsfulton
+ Patch #1992756 from Colin McDonald - %contract not working for classes
+ in namespace
+
+2009-01-05: olly
+ Mark SWIGPERL5, SWIGPHP5, and SWIGTCL8 as deprecated in the source
+ code and remove documentation of them.
+
+2008-12-30: wsfulton
+ Bug #2430756. All the languages now define a macro in the generated C/C++
+ wrapper file indicating which language is being wrapped. The macro name is the
+ same as those defined when SWIG is run, eg SWIGJAVA, SWIGOCTAVE, SWIGCSHARP etc
+ and are listed in the "Conditional Compilation" section in the documentation.
+
+2008-12-23: wsfulton
+ [Java] Fix #2153773 - %nojavaexception was clearing the exception feature
+ instead of disabling it. Clearing checked Java exceptions also didn't work.
+ The new %clearjavaexception can be used for clearing the exception feature.
+
+2008-12-22: wsfulton
+ Fix #2432801 - Make SwigValueWrapper exception safe for when copy constructors
+ throw exceptions.
+
+2008-12-21: wsfulton
+ Apply patch #2440046 which fixes possible seg faults for member and global
+ variable char arrays when the strings are larger than the string array size.
+
+2008-12-20: wsfulton
+ The ccache compiler cache has been adapted to work with SWIG and
+ named ccache-swig. It now works with C/C++ compilers as well as SWIG
+ and can result in impressive speedups when used to recompile unchanged
+ code with either a C/C++ compiler or SWIG. Documentation is in CCache.html
+ or the installed ccache-swig man page.
+
+2008-12-12: wsfulton
+ Apply patch from Kalyanov Dmitry which fixes parsing of nested structs
+ containing comments.
+
+2008-12-12: wsfulton
+ Fix error message in some nested struct and %inline parsing error situations
+ such as unterminated strings and comments.
+
+2008-12-07: olly
+ [PHP] Fix warnings when compiling generated wrapper with GCC 4.3.
+
+2008-12-06: wsfulton
+ [PHP] Deprecate %pragma(php4). Please use %pragma(php) instead.
+ The following two warnings have been renamed:
+ WARN_PHP4_MULTIPLE_INHERITANCE -> WARN_PHP_MULTIPLE_INHERITANCE
+ WARN_PHP4_UNKNOWN_PRAGMA -> WARN_PHP_UNKNOWN_PRAGMA
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-12-04: bhy
+ [Python] Applied patch SF#2158938: all the SWIG symbol names started with Py
+ are changed, since they are inappropriate and discouraged in Python
+ documentation (from http://www.python.org/doc/2.5.2/api/includes.html):
+
+ "All user visible names defined by Python.h (except those defined by
+ the included standard headers) have one of the prefixes "Py" or "_Py".
+ Names beginning with "_Py" are for internal use by the Python implementation
+ and should not be used by extension writers. Structure member names do
+ not have a reserved prefix.
+
+ Important: user code should never define names that begin with "Py" or "_Py".
+ This confuses the reader, and jeopardizes the portability of the user
+ code to future Python versions, which may define additional names beginning
+ with one of these prefixes."
+
+ Here is a brief list of what changed:
+
+ PySwig* -> SwigPy*
+ PyObject_ptr -> SwigPtr_PyObject
+ PyObject_var -> SwigVar_PyObject
+ PySequence_Base, PySequence_Cont, PySequence_Ref ->
+ SwigPySequence_Base, SwigPySequence_Cont, SwigPySequence_Ref
+ PyMap* -> SwigPyMap*
+
+ We provided a pyname_compat.i for backward compatibility. Users whose code having
+ these symbols and do not want to change it could simply include this file
+ at front of your code. A better solution is to run the converting tool on
+ your code, which has been put in SWIG's SVN trunk (Tools/pyname_patch.py) and
+ you can download it here:
+ https://swig.svn.sourceforge.net/svnroot/swig/trunk/Tools/pyname_patch.py
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2008-12-02: wsfulton
+ [Python] Apply patch #2143727 from Serge Monkewitz to fix importing base classes
+ when the package option is specified in %module and that module is %import'ed.
+
+2008-11-28: wsfulton
+ [UTL] Fix #2080497. Some incorrect acceptance of types in the STL, eg a double * element
+ passed into a vector<int *> constructor would be accepted, but the ensuing behaviour
+ was undefined. Now the type conversion correctly raises an exception.
+
+2008-11-24: wsfulton
+ Add -outcurrentdir option. This sets the default output directory to the current
+ directory instead of the path specified by the input file. This option enables
+ behaviour similar to c/c++ compilers. Note that this controls the output directory,
+ but only in the absence of the -o and/or -outdir options.
+
+2008-11-23: wsfulton
+ [ruby] Apply patch #2263850 to fix ruby/file.i ... rubyio.h filename change in
+ ruby 1.9.
+
+2008-11-23: wsfulton
+ Apply patch #2319790 from Johan Hake to fix shared_ptr usage in std::tr1 namespace.
+
+2008-11-21: wsfulton
+ The use of the include path to find the input file is now deprecated.
+ This makes the behaviour of SWIG the same as C/C++ compilers in preparation
+ for use with ccache.
+
+2008-11-16: wsfulton
+ Fix -nopreprocess option to:
+ - correctly report file names in warning and error messages.
+ - use the original input filename that created the preprocessed output when
+ determining the C++ wrapper file name (in the absence of -o). Previously
+ the name of the input file containing the preprocessed output was used.
+
+2008-11-11: wsfulton
+ [Java] Add patch #2152691 from MATSUURA Takanori which fixes compiles using the
+ Intel compiler
+
+2008-11-01: wsfulton
+ Add patch #2128249 from Anatoly Techtonik which corrects the C/C++ proxy
+ class being reported for Python docstrings when %rename is used.
+
+2008-11-01: wsfulton
+ Add the strip encoder patch from Anatoly Techtonik #2130016. This enables an
+ easy way to rename symbols by stripping a commonly used prefix in all the
+ function/struct names. It works in the same way as the other encoders, such as
+ title, lower, command etc outlined in CHANGES file dated 12/30/2005. Example
+ below will rename wxAnotherWidget to AnotherWidget and wxDoSomething to
+ DoSomething:
+
+ %rename("%(strip:[wx])s") "";
+
+ struct wxAnotherWidget {
+ void wxDoSomething();
+ };
+
+2008-09-26: mutandiz
+ [allegrocl]
+ Lots of test-suite work.
+ - Fix ordering of wrapper output and %{ %} header output.
+ - Fix declarations of local vars in C wrappers.
+ - Fix declaration of defined constants in C wrappers.
+ - Fix declaration of EnumValues in C wrappers.
+ - add some const typemaps to allegrocl.swg
+ - add rename for operator bool() overloads.
+
+2008-09-25: olly
+ [PHP5] Fill in typemaps for SWIGTYPE and void * (SF#2095186).
+
+2008-09-22: mutandiz (Mikel Bancroft)
+ [allegrocl]
+ - Support wrapping of types whose definitions are not seen by
+ SWIG. They are treated as forward-referenced classes and if a
+ definition is not seen are treated as (* :void).
+ - Don't wrap the contents of unnamed namespaces.
+ - More code cleanup. Removed some extraneous warnings.
+ - start work on having the allegrocl mod pass the cpp test-suite.
+
+2008-09-19: olly
+ [PHP5] Add typemaps for long long and unsigned long long.
+
+2008-09-18: wsfulton
+ [C#] Added C# array typemaps provided by Antti Karanta.
+ The arrays provide a way to use MarshalAs(UnmanagedType.LPArray)
+ and pinning the array using 'fixed'. See arrays_csharp.i library file
+ for details.
+
+2008-09-18: wsfulton
+ Document the optional module attribute in the %import directive,
+ see Modules.html. Add a warning for Python wrappers when the
+ module name for an imported base class is missing, requiring the
+ module attribute to be added to %import, eg
+
+ %import(module="FooModule") foo.h
+
+2008-09-18: olly
+ [PHP5] Change the default input typemap for char * to turn PHP
+ Null into C NULL (previously it was converted to an empty string).
+ The new behaviour is consistent with how the corresponding output
+ typemap works (SF#2025719).
+
+ If you want to keep the old behaviour, add the following typemap
+ to your interface file (PHP's convert_to_string_ex() function does
+ the converting from PHP Null to an empty string):
+
+ %typemap(in) char * {
+ convert_to_string_ex($input);
+ $1 = Z_STRVAL_PP($input);
+ }
+
+2008-09-18: olly
+ [PHP5] Fix extra code added to proxy class constructors in the case
+ where the only constructor takes no arguments.
+
+2008-09-18: olly
+ [PHP5] Fix wrapping of a renamed enumerated value of an enum class
+ member (SF#2095273).
+
+2008-09-17: mutandiz (Mikel Bancroft)
+ [allegrocl]
+ - Fix how forward reference typedefs are handled, so as not to conflict
+ with other legit typedefs.
+ - Don't (for now) perform an ffitype typemap lookup when trying to
+ when calling compose_foreign_type(). This is actually a useful thing
+ to do in certain cases, the test cases for which I can't currently
+ locate :/. It's breaking some wrapping behavior that is more commonly
+ seen, however. I'll readd in a more appropriate way when I can
+ recreate the needed test case, or a user complains (which means
+ they probably have a test case).
+ - document the -isolate command-line arg in the 'swig -help' output.
+ It was in the html docs, but not there.
+ - small amount of code cleanup, removed some unused code.
+ - some minor aesthetic changes.
+
+2008-09-12: bhy
+ [Python] Python 3.0 support branch merged into SWIG trunk. Thanks to
+ Google Summer of Code 2008 for supporting this project! By default
+ SWIG will generate interface files compatible with both Python 2.x
+ and 3.0. And there's also some Python 3 new features that can be
+ enabled by passing a "-py3" command line option to SWIG. These
+ features are:
+
+ - Function annotation support
+ Also, the parameter list of proxy function will be generated,
+ even without the "-py3" option. However, the parameter list
+ will fallback to *args if the function (or method) is overloaded.
+ - Buffer interface support
+ - Abstract base class support
+
+ For details of Python 3 support and these features, please see the
+ "Python 3 Support" section in the "SWIG and Python" chapter of the SWIG
+ documentation.
+
+ The "-apply" command line option and support of generating codes
+ using apply() is removed. Since this is only required by very old
+ Python.
+
+ This merge also patched SWIG's parser to solve a bug. By this patch,
+ SWIG features able to be correctly applied on C++ conversion operator,
+ such like this:
+
+ %feature("shadow") *::operator bool %{ ... %}
+
+2008-09-02: richardb
+ [Python] Commit patch #2089149: Director exception handling mangles
+ returned exception. Exceptions raised by Python code in directors
+ are now passed through to the caller without change. Also, remove
+ the ": " prefix which used to be added to other director exceptions
+ (eg, those due to incorrect return types).
+
+2008-09-02: wsfulton
+ [Python] Commit patch #1988296 GCItem multiple module linking issue when using
+ directors.
+
+2008-09-02: wsfulton
+ [C#] Support for 'using' and 'fixed' blocks in the 'csin' typemap is now
+ possible through the use of the pre attribute and the new terminator attribute, eg
+
+ %typemap(csin,
+ pre=" using (CDate temp$csinput = new CDate($csinput)) {",
+ terminator=" } // terminate temp$csinput using block",
+ ) const CDate &
+ "$csclassname.getCPtr(temp$csinput)"
+
+ See CSharp.html for more info.
+
+2008-09-01: wsfulton
+ [CFFI] Commit patch #2079381 submitted by Boris Smilga - constant exprs put into
+ no-eval context in DEFCENUM
+
+2008-08-02: wuzzeb
+ [Chicken,Allegro] Commit Patch 2019314
+ Fixes a build error in chicken, and several build errors and other errors
+ in Allegro CL
+
+2008-07-19: wsfulton
+ Fix building of Tcl examples/test-suite on Mac OS X reported by Gideon Simpson.
+
+2008-07-17: wsfulton
+ Fix SF #2019156 Configuring with --without-octave or --without-alllang
+ did not disable octave.
+
+2008-07-14: wsfulton
+ [Java, C#] Fix director typemaps for pointers so that NULL pointers are correctly
+ marshalled to C#/Java null in director methods.
+
+2008-07-04: olly
+ [PHP] For std_vector.i and std_map.i, rename empty() to is_empty()
+ since "empty" is a PHP reserved word. Based on patch from Mark Klein
+ in SF#1943417.
+
+2008-07-04: olly
+ [PHP] The deprecated command line option "-make" has been removed.
+ Searches on Google codesearch suggest that nobody is using it now
+ anyway.
+
+2008-07-04: olly
+ [PHP] The SWIG cdata.i library module is now supported.
+
+2008-07-03: olly
+ [PHP] The deprecated command line option "-phpfull" has been
+ removed. We recommend building your extension as a dynamically
+ loadable module.
+
+2008-07-02: olly
+ [PHP4] Support for PHP4 has been removed. The PHP developers are
+ no longer making new PHP4 releases, and won't even be providing
+ patches for critical security issues after 2008-08-08.
+
+2008-07-02: olly
+ [Python] Import the C extension differently for Python 2.6 and
+ later so that an implicit relative import doesn't produce a
+ deprecation warning for 2.6 and a failure for 2.7 and later.
+ Patch from Richard Boulton in SF#2008229, plus follow-up patches
+ from Richard and Haoyu Bai.
+
+Version 1.3.36 (24 June 2008)
+=============================
+
+06/24/2008: wsfulton
+ Remove deprecated -c commandline option (runtime library generation).
+
+06/24/2008: olly
+ [PHP] Fix assertion failure when handling %typemap(in,numinputs=0)
+ (testcase ignore_parameter).
+
+06/24/2008: olly
+ [PHP] Fix segfault when wrapping a non-class function marked with
+ %newobject (testcase char_strings).
+
+06/22/2008: wsfulton
+ [Java] Add a way to use AttachCurrentThreadAsDaemon instead of AttachCurrentThread
+ in director code. Define the SWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON macro, see
+ Lib/java/director.swg.
+
+06/21/2008: wsfulton
+ [Ruby] Fix crashing in the STL wrappers (reject! and delete_if methods)
+
+06/19/2008: wsfulton
+ [Java, C#] C# and Java keywords will be renamed instead of just issuing a warning
+ and then generating uncompilable code. Warning 314 gives the new name when a
+ keyword is found.
+
+06/19/2008: wsfulton
+ [R] Keyword handling added. R Keywords will be renamed as necessary.
+ Warning 314 gives the new name when a keyword is found.
+
+06/17/2008: mgossage
+ [Lua] Added missing support for bool& and bool*. Added runtest for li_typemaps testcase.
+ (Bug #1938142)
+
+06/07/2008: bhy
+ Added test case keyword_rename, then made the keyword renaming works properly
+ by fixing Swig_name_make() for a incomplete condition checking.
+
+06/02/2008: wsfulton
+ [Java, C#] Fix enum wrappers when using -noproxy.
+
+05/30/2008: bhy
+ Added std::wstring into Lib/typemaps/primtypes.swg, since it is also a primitive
+ type in SWIG - fixed SF #1976978.
+
+05/29/2008: wsfulton
+ [Java, C#] Fix variable wrappers when using -noproxy.
+
+05/29/2008: bhy
+ [Python] Fixed a typo of %#ifdef in Lib/python/pycontainer.swg, which is related
+ to -extranative SWIG option - SF #1971977.
+
+05/20/2008: wsfulton
+ New partialcheck makefile targets for partial testing of the test-suite. These
+ just invoke SWIG, ie no compilation and no runtime testing. It can be faster
+ when developing by just doing a directory diff of the files SWIG generates
+ against those from a previous run. Example usage from the top level directory:
+
+ make partialcheck-test-suite
+ make partialcheck-java-test-suite
+
+ This change also encompasses more flexibility in running the test-suite, eg
+ it is possible to prefix the command line which runs any target language test
+ with a tool. See the RUNTOOL, COMPILETOOL and SWIGTOOL targets in the common.mk
+ file and makefiles in the test-suite directory. For example it is possible to
+ run the runtime tests through valgrind using:
+
+ make check RUNTOOL="valgrind --leak-check=full"
+
+ or invoke SWIG under valgrind using:
+
+ make check SWIGTOOL="valgrind --tool=memcheck"
+
+05/19/2008: drjoe
+ [R] Fixed define that was breaking pre-2.7. Checked in
+ patch from Soren Sonnenburg that creates strings in
+ version independent way
+
+05/15/2008: wsfulton
+ [Java] Fix variable name clash in directors - SF #1963316 reported by Tristan.
+
+05/14/2008: wsfulton
+ Add an optimisation for functions that return objects by value, reducing
+ the number of copies of the object that are made. Implemented using an
+ optional attribute in the "out" typemap called "optimal". Details in
+ Typemaps.html.
+
+05/11/2008: olly
+ [PHP] Check for %feature("notabstract") when generating PHP5 class
+ wrapper.
+
+05/11/2008: wsfulton
+ Fix SF #1943608 - $self substitution in %contract, patch submitted by
+ Toon Verstraelen.
+
+05/09/2008: olly
+ [PHP] Fix char * typemaps to work when applied to signed char * and
+ unsigned char * (uncovered by testcase apply_strings).
+
+05/09/2008: wsfulton
+ Fix wrapping of char * member variables when using allprotected mode.
+ Bug reported by Warren Wang.
+
+05/09/2008: olly
+ [PHP] Fix bad PHP code generated when wrapping an enum in a
+ namespace (uncovered by testcase arrays_scope).
+
+05/09/2008: olly
+ [PHP] SWIG now runs the PHP testsuite using PHP5, not PHP4. PHP4
+ is essentially obsolete now, so we care much more about solid PHP5
+ support.
+
+05/07/2008: wsfulton
+ STL fixes when using %import rather than %include and the Solaris Workshop
+ compiler and the Roguewave STL.
+
+05/07/2008: wsfulton
+ Fix wrapping of overloaded protected methods when using allprotected mode.
+ Bug reported by Warren Wang.
+
+05/03/2008: wsfulton
+ Commit patch #1956607 to add -MT support from Richard Boulton.
+ This patch mirrors the gcc -MT option which allows one to change the default
+ Makefile target being generated when generating makefiles with the -M family
+ of options. For example:
+
+ $ swig -java -MM -MT overriddenname -c++ example.i
+ overriddenname: \
+ example.i \
+ example.h
+
+04/30/2008: mgossage
+ [Lua] Removed generation of _wrap_delete_XXXXX (wrappered destructor)
+ which was unused and causing warning with g++ -Wall.
+ Removed other unused warning in typemaps.i and other places.
+ Added Examples/lua/embed3, and run tests a few test cases.
+
+04/24/2008: olly
+ [Python] Fix generated code for IBM's C++ compiler on AIX (patch
+ from Goeran Uddeborg in SF#1928048).
+
+04/24/2008: olly
+ Rename BSIZE in Examples/test-suite/arrays_scope.i to BBSIZE to
+ avoid a clash with BSIZE defined by headers on AIX with Perl
+ (reported in SF#1928048).
+
+04/20/2008: wsfulton
+ Add the ability to wrap all protected members when using directors.
+ Previously only the virtual methods were available to the target language.
+ Now all protected members, (static and non-static variables, non-virtual methods
+ and static methods) are wrapped when using the allprotected mode. The allprotected
+ mode is turned on in the module declaration:
+
+ %module(directors="1", allprotected="1") modulename
+
+Version 1.3.35 (7 April 2008)
+=============================
+
+04/07/2008: wsfulton
+ [Lua] Add missing pointer reference typemaps
+
+04/06/2008: wsfulton
+ Fix stack overflow when using typemap warning suppression, eg
+ %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG)
+
+04/05/2008: wsfulton
+ [Python] Fix shared_ptr typemaps so that %pythonnondynamic can be used. Also corrects
+ display of the proxy class type. Reported by Robert Lupton.
+
+04/04/2008: olly
+ [Python] Add %newobject reference to python memory management subsection of manual
+ (patch from mdbeachy in SF#1894610).
+
+03/27/2008: wsfulton
+ [Python] Fix shared_ptr typemaps where the pointer type is a templated type with
+ with more than one parameter. Reported by Robert Lupton.
+
+03/27/2008: mgossage
+ [Lua] Added a typemap DISOWN for SWIGTYPE* and SWIGTYPE[], and support for %delobject feature.
+ Added Examples/lua/owner which demonstrates the use of the memory management.
+
+03/26/2008: wsfulton
+ [Java] Apply patch #1844301 from Monty Taylor to suppress enum constructor
+ unused warnings.
+
+03/26/2008: wsfulton
+ [Python] Apply patch #1924524 from Casey Raymondson which ensures the
+ "No constructor defined" message is displayed when attempting to call a
+ constructor on a class that doesn't have a constructor wrapper, eg if
+ the C++ class is abstract.
+
+03/26/2008: wsfulton
+ [Python] Apply patch #1925702 from Casey Raymondson which removes warning 512
+ for std::vector wrappers.
+
+03/26/2008: olly
+ [Python] Apply GCC 4.3 warnings patch from Philipp Thomas
+ (SF#1925122).
+
+03/21/2008: wsfulton
+ [Python] Thread safety patch for STL iterators from Abhinandan Jain.
+
+03/17/2008: mgossage
+ [Lua] Added %luacode feature to add source code into wrappers.
+ Updated documentation to document this.
+ Added Examples/lua/arrays to show its use (and typemaps)
+
+03/17/2008: olly
+ Fix nonportable sed usage which failed on Mac OS X (and probably
+ other platforms). Fixes SF#1903612.
+
+03/17/2008: olly
+ Fix memory leak in SWIG's parser (based on patch from Russell
+ Bryant in SF#1914023).
+
+03/12/2008: wsfulton
+ Fix bug #1878285 - unnecessary cast for C struct creation wrappers.
+
+03/12/2008: wsfulton
+ [Python] Remove debugging info when using shared_ptr support
+
+03/06/2008: mgossage
+ [Lua] Updated documentation for Lua exceptions.
+ Added Examples/lua/exception and Examples/lua/embed2.
+ Small updates to the typemaps.
+
+03/04/2008: wsfulton
+ [Java, C#] Add char *& typemaps.
+
+03/04/2008: wsfulton
+ Fix occasional seg fault when attempting to report overloaded methods as being ignored.
+
+02/29/2008: wsfulton
+ [Perl] Fix #1904537 Swig causes a Perl warning "x used only once" in Perl 5.10
+ reported by Ari Jolma
+
+02/29/2008: wsfulton
+ [Python] Add shared_ptr varin/varout typemaps for wrapping global variables.
+
+02/25/2008: wsfulton
+ Fix $wrapname to work in %exception (fixes some wrap:name assertions)
+
+Version 1.3.34 (27 February 2008)
+=================================
+
+02/13/2008: wsfulton
+ [R] Fix wrapping of global function pointer variables.
+
+02/13/2008: wsfulton
+ Add new special variables for use within %exception:
+ $wrapname - language specific wrapper name
+ $overname - if a method is overloaded this contains the extra mangling used on
+ the overloaded method
+ $decl - the fully qualified C/C++ declaration of the method being wrapped
+ without the return type
+ $fulldecl - the fully qualified C/C++ declaration of the method being wrapped
+ including the return type
+
+02/12/2008: drjoe
+ [R] Now setting S4 flag in SWIG created objects. This
+ fixes R-SWIG for 2.6 and warning for 2.6 failure has been removed.
+
+02/11/2008: mgossage
+ [Lua] Added a patch by Torsten Landschoff to fix the unary minus issue
+ Ran 'astyle --style=kr -2' across lua.cxx to neaten it up
+
+02/10/2008: wsfulton
+ Bump SWIG_RUNTIME_VERSION to 4. This is because of the recently introduced API
+ change in the conversion functions, ie change in definition of swig_converter_func.
+ Anyone calling SWIG_TypeCast must pass in a valid value for the new additional
+ (third) parameter and then handle the newly created memory if the returned value
+ is set to SWIG_CAST_NEW_MEMORY else a memory leak will ensue.
+
+02/09/2008: wsfulton
+ [Python] Experimental shared_ptr typemaps added. Usage is the same as the recently
+ added Java and C# shared_ptr typemaps. Two macros are available, although these
+ may well change in a future version:
+
+ For base classes or classes not in an inheritance chain:
+ SWIG_SHARED_PTR(PROXYCLASS, TYPE)
+ For derived classes:
+ SWIG_SHARED_PTR_DERIVED(PROXYCLASS, BASECLASSTYPE, TYPE)
+
+ The PROXYCLASS is the name of the proxy class, but is only required for Java/C#.
+ Example usage:
+
+ %include "boost_shared_ptr.i"
+
+ SWIG_SHARED_PTR(Klass, Space::Klass)
+ SWIG_SHARED_PTR_DERIVED(KlassDerived, Space::Klass, Space::KlassDerived)
+
+ namespace Space {
+ struct Klass { ... };
+ struct KlassDerived : Klass { ... };
+ }
+
+ Further details to follow in future documentation, but the following features
+ should be noted:
+
+ - Not restricted to boost::shared_ptr, eg std::tr1::shared_ptr can also be used.
+ - Available typemap groups:
+ (a) Typemaps for shared_ptr passed by value, reference, pointer and pointer
+ reference.
+ - (b) Typemaps for passing by raw value, raw pointer, raw reference, raw pointer
+ reference.
+ - The code being wrapped does not even have to use shared_ptr, SWIG can use
+ shared_ptr as the underlying storage mechanism instead of a raw pointer due to
+ the typemaps in group (b) above.
+ - No array support as shared_ptr does not support arrays.
+ - This works quite differently to the usual SWIG smart pointer support when
+ operator-> is parsed by SWIG:
+ - An additional smart pointer class is not generated reducing code bloat in
+ the wrappers.
+ - Using smart pointers and raw pointers can be mixed seamlessly.
+ - Missing constructors for the smart pointers is no longer a problem and so
+ separate factory type functions do not have to be written and wrapped.
+ - The implicit C++ shared_ptr< derived class > to shared_ptr< base class >
+ cast also works in the target language. This negates the necessity to write
+ an explicit helper cast function providing the upcast which would need
+ calling prior to passing a derived class to a method taking a shared_ptr to
+ a base class.
+
+02/09/2008: wsfulton
+ [Python] Add support for overriding the class registration function via a new
+ "smartptr" feature. This is a very low level of customisation most users
+ would never need to know. The feature will typically be used for intrusive
+ smart pointers along with additional typemaps. Example usage of the feature:
+
+ %feature("smartptr", noblock=1) Foo { boost::shared_ptr< Foo > }
+ class Foo {};
+
+ The generated Foo_swigregister function will then register boost::shared < Foo >
+ (SWIGTYPE_p_boost__shared_ptrTFoo_t instead of SWIGTYPE_p_Foo) as the underlying
+ type for instantiations of Foo.
+
+02/09/2008: wsfulton
+ Features now supports the optional 'noblock' attribute for all usage of %feature.
+ When specified, the { } braces are removed from the feature code. This is identical
+ in behaviour to usage of 'noblock' in typemaps and is used when the preprocessor
+ is required to operate on the code in the feature and the enclosing { } braces
+ are not required. Example:
+
+ #define FOO foo
+ %feature("smartptr", noblock="1") { FOO::bar }
+
+ The preprocessor then reduces this as if this had been used instead:
+
+ %feature("smartptr") "foo::bar"
+
+02/01/2008: olly
+ [Python] Fix format string bug (SF#1882220).
+
+01/31/2008: wsfulton
+ Additions to the %types directive. Now the conversion / casting code can be
+ overridden to some custom code in the %types directive, like so:
+
+ %types(fromtype = totype) %{
+ ... code to convert fromtype to totype and return ...
+ %}
+
+ The special variable $from will be replaced by the name of the parameter of the
+ type being converted from. The code must return the totype cast to void *. Example:
+
+ class Time;
+ class Date;
+ Date &Time::dateFromTime();
+
+ %types(Time = Date) %{
+ Time *t = (Time *)$from;
+ Date &d = t->dateFromTime();
+ return (void *) &d;
+ %}
+
+ resulting in the conversion / casting code looking something like:
+
+ static void *_p_TimeTo_p_Date(void *x) {
+ Time *t = (Time *)x;
+ Date &d = t->dateFromTime();
+ return (void *) &d;
+ }
+
+ This is advanced usage, please use only if you understand the runtime type system.
+
+01/30/2008: mgossage
+ Small update to documentation in Typemaps.html, to warn about use of local
+ variables in typemaps for multiple types.
+
+01/25/2008: wsfulton
+ [Java] Fix bug reported by Kevin Mills in ARRAYSOFCLASSES typemaps where any
+ changes made to an array element passed from Java to C are not reflected back
+ into Java.
+
+01/24/2008: mgossage
+ More updates to the configure script for detecting lua.
+ Also looks in /usr/include/lua*
+ Also changed typemaps.i not to check for NULL before freeing a pointer
+
+01/21/2008: wsfulton
+ [Python] For STL containers, SWIG no longer attempts to convert from one
+ STL container to another, eg from std::vector<int> to std::vector<double>
+ or std::list<int> to std::vector<int> or even std::vector<Foo> to
+ std::vector<Bar> as it previously did. In fact SWIG no longer attempts to
+ convert any SWIG wrapped C++ proxy class that is also a Python sequence,
+ whereas previously it would. Any non-SWIG Python sequence will still be
+ accepted wherever an STL container is accepted. Overloaded methods using
+ containers should be faster.
+
+01/18/2008: wsfulton
+ [C#] Add 'directorinattributes' and 'directoroutattributes' typemap attributes
+ for the imtype typemap. These should contain C# attributes which will
+ be generated into the C# director delegate methods.
+
+01/18/2008: olly
+ Fix handling of byte value 255 in input files on platforms where
+ char is signed (it was getting mapped to EOF). Fixes SF#1518219.
+
+01/16/2008: wsfulton
+ Fix template member variables wrapped by a smart pointer. Bug reported
+ by Robert Lupton.
+
+01/14/2008: mgossage
+ Substantial changes to configure script for detecting lua.
+ Code can now link to liblua.a, liblua50.a or liblua51.a
+ It's also a lot neater now.
+
+12/16/2007: wsfulton
+ [Perl] Backed out #1798728 - numbers can be passed to functions taking char *
+
+12/16/2007: wsfulton
+ Fix #1832613 - Templates and some typedefs involving pointers or function pointers
+
+12/12/2007: wsfulton
+ [Java] Fix #1632625 - Compilation errors on Visual C++ 6 when using directors.
+
+12/12/2007: wsfulton
+ [Perl] Fix #1798728 - numbers can be passed to functions taking char *.
+
+12/12/2007: wsfulton
+ Fix #1819847 %template with just one default template parameter
+
+ template<typename T = int> class Foo {...};
+ %template(FooDefault) Foo<>;
+
+12/12/2007: mgossage
+ [Lua] Small correction on Lua.html
+
+12/09/2007: wsfulton
+ Apply patch #1838248 from Monty Taylor for vpath builds of SWIG.
+
+12/08/2007: wsfulton
+ [Lua] Fixes to remove gcc-4.2 warnings
+
+12/06/2007: wsfulton
+ Fix #1734415 - template template parameters with default arguments such as:
+
+ template<typename t_item, template<typename> class t_alloc = pfc::alloc_fast >
+ class list_t : public list_impl_t<t_item,pfc::array_t<t_item,t_alloc> > { ... };
+
+12/04/2007: mgossage
+ [lua] Fix a bug in the class hierachy code, where the methods were not propagated,
+ if the name ordering was in a certain order.
+ Added new example programs (dual, embed) and runtime tests for test-suite.
+
+11/30/2007: wsfulton
+ Fix using statements using a base class method where the methods were overloaded.
+ Depending on the order of the using statements and method declarations, these
+ were previously generating uncompilable wrappers, eg:
+
+ struct Derived : Base {
+ virtual void funk();
+ using Base::funk;
+ };
+
+Version 1.3.33 (November 23, 2007)
+==================================
+
+11/21/2007: mikel
+ [allegrocl] omit private slot type info in the classes/types
+ defined on the lisp side. Fix bug in mapping of C/++ types
+ to lisp types. Fix typo in modules generated defpackage form.
+ Have std::string *'s automatically marshalled between foreign
+ and lisp strings.
+
+11/20/2007: olly
+ [Python] Fill in Python Dictionary functions list (patch from
+ Jelmer Vernooij posted to swig-devel).
+
+11/20/2007: beazley
+ Fixed a bug in the C scanner related to backslash characters.
+
+11/19/2007: wsfulton
+ [Perl] Fix broken compilation of C++ wrappers on some compilers.
+
+11/16/2007: olly
+ [Python] Don't pass Py_ssize_t for a %d printf-like format as
+ that's undefined behaviour when sizeof(Py_ssize_t) != sizeof(int).
+
+Version 1.3.32 (November 15, 2007)
+==================================
+
+11/14/2007: wsfulton
+ [R] Package name and dll name is now the same as the SWIG module
+ name. It used to be the module name with _wrap as a suffix. The package
+ and dll names can be modified using the -package and -dll commandline
+ options.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/11/2007: wsfulton
+ [R] Add support for Windows (Visual C++ 8 tested)
+
+11/10/2007: olly
+ [php] Fix makefile generated by -make (SF#1633679). Update
+ documentation to mark "-make" as deprecated (none of the other
+ SWIG backends seem to offer such a feature, it can't realistically
+ generate a fully portable makefile, and the commands to build an
+ extension are easy enough to write for the user's preferred build
+ tool). Also recommend against the use of "-phpfull" (it's only
+ really useful when static linking, and a dynamically loadable
+ module is virtually always the better approach).
+
+11/09/2007: olly
+ Fix --help output to note that `export SWIG_FEATURES' is required.
+
+10/29/2007: wsfulton
+ [R] Fix seg fault on Windows
+ [R] Examples R scripts are now platform independent
+
+10/30/2007: mgossage
+ [lua] fixed bug in template classes which cases template_default2
+ and template_specialization_defarg to fail.
+ Added several warning filters into the overload's test cases.
+ Added runtime tests for several codes.
+ You can now make check-lua-test-suite with no errors and only a few warnings.
+
+10/30/2007: olly
+ [guile] Fix the configure test to put GUILELINK in LIBS not LDFLAGS
+ (SF#1822430).
+
+10/30/2007: olly
+ [guile] Fix the guile examples on 64-bit platforms.
+
+10/29/2007: wsfulton
+ [C#] Fix member pointers on 64 bit platforms.
+
+10/28/2007: olly
+ [lua] Fix swig_lua_class instances to be static to allow multiple
+ SWIG wrappers to be compiled into the same executable statically.
+ Patch from Andreas Fredriksson (posted to the swig mailing list).
+
+10/28/2007: olly
+ [lua] Fix Examples/lua to pass SRCS for C tests rather than CXXSRCS.
+ The code as it was happened to work on x86, but broke on x86_64 (and
+ probably any other platforms which require -fPIC).
+
+10/28/2007: wsfulton
+ [Java, C#] New approach for fixing uninitialised variable usage on error in director
+ methods using the new templated initialisation function SwigValueInit().
+
+10/28/2007: wsfulton
+ [Perl] Use more efficient SvPV_nolen(x) instead of SvPV(x,PL_na) if SvPV_nolen is
+ supported.
+
+10/26/2007: wuzzeb
+ [Chicken] Fix global variables of class member function pointers.
+ Other minor fixes, so all tests in the chicken test suite now pass
+
+10/25/2007: olly
+ Fix UTL typecheck macro for a function taking char[] or const
+ char[] (SF#1820132).
+
+10/22/2007: mkoeppe
+ [Guile] Filter out -ansi -pedantic from CFLAGS while compiling test programs for Guile
+ in configure. This enables running the test suite for Guile if it is installed and
+ usable.
+
+10/22/2007: mkoeppe
+ [Guile -scm] Fix testcases apply_signed_char and apply_strings
+ by adding explicit casts to the appropriate $ltype.
+
+10/22/2007: wsfulton
+ [Java, C#] Fix uninitialised variable usage on error in director methods.
+
+10/19/2007: wsfulton
+ [Java, C#] Bug #1794247 - fix generated code for derived classes when csbase or javabase
+ typemaps are used with the replace="1" attribute.
+
+10/19/2007: wsfulton
+ [Python] Docs updated to suggest using distutils. Patch #1796681 from Christopher Barker.
+
+10/19/2007: olly
+ [perl5] Clear errno before calls to strtol(), strtoul(), strtoll()
+ and strtoull() which we check errno after to avoid seeing a junk
+ value of errno if there isn't an error in the call.
+
+10/16/2007: wsfulton
+ Deprecate %attribute_ref and replace with %attributeref. There is just an argument
+ order change in order to maintain consistency with %attribute, from:
+
+ %attribute_ref(Class, AttributeType, AccessorMethod, AttributeName)
+ to
+ %attributeref(Class, AttributeType, AttributeName, AccessorMethod)
+
+10/16/2007: olly
+ [Tcl] Fix several occurrences of "warning: deprecated conversion
+ from string constant to 'char*'" from GCC 4.2 in generated C/C++
+ code.
+
+10/16/2007: olly
+ [PHP] Fix many occurrences of "warning: deprecated conversion from
+ string constant to 'char*'" from GCC 4.2 in generated C/C++ code
+ when compiling with a new enough version of PHP 5 (tested with
+ PHP 5.2.3, but PHP 5.2.1 is probably the minimum requirement).
+
+10/15/2007: wsfulton
+ Patch #1797133 from David Piepgrass fixes %attribute when the getter has the same name
+ as the attribute name and no longer generate non-functional setter for read-only attributes.
+
+10/15/2007: olly
+ [Tcl] Prevent SWIG_Tcl_ConvertPtr from calling the unknown proc.
+ Add Examples/tcl/std_vector/ which this change fixes. Patch
+ is from "Cliff C" in SF#1809819.
+
+10/12/2007: wsfulton
+ [Java] Add DetachCurrentThread back in for directors. See entry dated 08/11/2006 and
+ search for DetachCurrentThread on the mailing lists for details. The crashes on Solaris
+ seem to be only present in jdk-1.4.2 and lower (jdk-1.5.0 and jdk-1.6.0 are okay), so
+ anyone using directors should use a recent jdk on Solaris, or define (see director.swg)
+ SWIG_JAVA_NO_DETACH_CURRENT_THREAD to the C++ compiler to get old behaviour.
+
+10/12/2007: wsfulton
+ [Java] Ensure the premature garbage collection prevention parameter (pgcpp) is generated
+ when there are C comments in the jtype and jstype typemaps.
+
+10/12/2007: wuzzeb
+ Added a testsuite entry for Bug #1735931
+
+10/09/2007: olly
+ Automatically rerun autogen.sh if configure.in is modified.
+
+10/09/2007: olly
+ Enhance check-%-test-suite rule and friends to give a more helpful
+ error message if you try them for a language which doesn't exist
+ (e.g. "make check-php-test-suite" rather than the correct
+ "make check-php4-test-suite").
+
+10/09/2007: olly
+ Add make rule to regenerate Makefile from Makefile.in if it has
+ changed.
+
+10/09/2007: olly
+ [php] Fix long-standing memory leak in wrapped constructors and
+ wrapped functions/methods which return an object.
+
+10/08/2007: olly
+ Fix Makefile.in to read check.list files correctly in a VPATH
+ build.
+
+10/07/2007: wsfulton
+ [C#, Java] Experimental shared_ptr typemaps added
+
+09/27/2007: mgossage
+ [lua] added more verbose error messages for incorrect typechecks.
+ Added a routine which checks the exact number of parameters passed to a function
+ (breaks operator_overloading for unary minus operator, currently disabled).
+ Reorganised the luatypemaps.swg to tidy it up.
+ Added a lot of %ignores on the operators not supported by lua.
+ Added support for constant member function pointers & runtest for member_pointer.i
+ Added first version of wchar.i
+
+09/25/2007: wsfulton
+ [C#, Java] throws typemaps for std::wstring using C# patch #1799064 from David Piepgrass
+
+09/24/2007: wsfulton
+ [Tcl] Apply #1771313 to fix bug #1650229 - fixes long long and unsigned long long
+ handling.
+
+09/20/2007: olly
+ [Java] Eliminate some unnecessary uses of a temporary buffer
+ allocated using new[]. SF#1796609.
+
+09/19/2007: wsfulton
+ [C#] The $csinput special variable can be used in the csvarin typemap where it is always
+ expanded to 'value'.
+
+09/19/2007: wsfulton
+ [C#] Fix bug reported by Glenn A Watson and #1795260 where the cstype typemap used the 'ref'
+ keyword in the typemap body, it produced uncompilable C# properties (variable wrappers).
+ The type for the property now correctly comes from the 'out' attribute in the cstype typemap.
+
+09/19/2007: wsfulton
+ [Java] Fix const std::wstring& typemaps
+
+09/19/2007: wsfulton
+ [Java] Ensure the premature garbage collection prevention parameter (pgcpp) is generated
+ where a parameter is passed by pointer reference, eg in the std::vector wrappers. The pgcpp
+ is also generated now when user's custom typemaps use a proxy class in the jstype typemap
+ and a 'long' in the jtype typemap.
+
+09/18/2007: olly
+ [php] Add typemaps for handling parameters of type std::string &
+ which are modified by the wrapped function.
+
+09/17/2007: olly
+ [python] Split potentially long string literals to avoid hitting
+ MSVC's low fixed limit on string literal length - patch from
+ SF#1723770, also reported as SF#1630855.
+
+09/17/2007: olly
+ [ocaml] Fix renaming of overloaded methods in the method_table -
+ my patch from SF#940399.
+
+09/17/2007: olly
+ [python] Simpler code for SWIG_AsVal_bool() which fixes a "strict
+ aliasing" warning from GCC - patch from SF#1724581 by Andrew
+ Baumann.
+
+09/17/2007: olly
+ [perl5] Use sv_setpvn() to set a scalar from a pointer and length
+ - patch from SF#174460 by "matsubaray".
+
+09/17/2007: olly
+ When wrapping C++ code, generate code which uses
+ std::string::assign(PTR, LEN) rather than assigning
+ std::string(PTR, LEN). Using assign generates more efficient code
+ (tested with GCC 4.1.2).
+
+09/07/2007: wsfulton
+ Fix %ignore on constructors which are not explicitly declared [SF #1777712]
+
+09/05/2007: wuzzeb (John Lenz)
+ - Change r_ltype in typesys.c to store a hashtable instead of a single value.
+ several very subtle bugs were being caused by multiple ltypes being mapped
+ to a single mangled type, mostly when using typedefed template parameters.
+ Now, r_ltype stores a hashtable of possible ltypes, and when generating the
+ type table, all the ltypes are added into the swig_type_info structure.
+
+08/31/2007: wsfulton
+ SF #1754967 from James Bigler.
+ - Fix bug in turning on warnings that were turned off by default. Eg 'swig -w+309' will now
+ turn on the normally suppressed warning 309.
+
+ - New -Wextra commandline option which enables the extra warning numbers:
+ 202,309,403,512,321,322 (this is the list of warnings that have always been suppressed by
+ default). By specifying -Wextra, all warnings will be turned on, but unlike -Wall,
+ warnings can still be selectively turned on/off using %warnfilter,
+ #pragma SWIG nowarn or further -w commandline options, eg:
+ swig -Wextra -w309
+ will turn on all warnings except 309.
+
+08/28/2007: wsfulton
+ - New debugging options, -debug-module <n> and -debug-top <n> to display the parse tree at
+ various stages, where <n> is a comma separated list of stages 1-4.For example, to
+ display top of parse tree at stages 1 and 3:
+ swig -debug-top 1,3
+
+ - Deprecate the following options which have equivalents below:
+ -dump_parse_module => -debug-module 1
+ -dump_module => -debug-module 4
+ -dump_parse_top => -debug-top 1
+ -dump_top => -debug-top 4
+
+ - Renamed some commandline options for naming consistency across all options:
+ -debug_template => -debug-template
+ -debug_typemap => -debug-typemap
+ -dump_classes => -debug-classes
+ -dump_tags => -debug-tags
+ -dump_typedef => -debug-typedef
+ -dump_memory => -debug-memory
+
+08/25/2007: olly
+ [PHP5] Fix handling of double or float parameters with an integer
+ default value.
+
+08/25/2007: olly
+ [PHP5] Generate __isset() methods for setters for PHP 5.1 and later.
+
+08/20/2007: wsfulton
+ [Java C#] Fix director bug #1776651 reported by Stephane Routelous which occurred when
+ the director class name is the same as the start of some other symbols used within
+ the director class.
+
+08/17/2007: wsfulton
+ Correct behaviour for templated methods used with %rename or %ignore and the empty
+ template declaration - %template(). A warning is issued if the method has not been
+ renamed.
+
+08/16/2007: mutandiz (Mikel Bancroft)
+ [allegrocl] Name generated cl file based on input file rather than by
+ module name. It was possible to end up with a mypackage.cl and a test_wrap.c
+ when parsing a test.i input file. Confusing. Also, include external-format
+ templates for :fat and :fat-le automatically to avoid these being compiled
+ at runtime.
+
+08/15/2007: efuzzyone
+ [cffi] Apply patch #1766076 from Leigh Smith adding support for newly introduced
+ in cffi :long-long and :unsigned-long-long.
+
+08/10/2007: wsfulton
+ [Java] Add documentation patch #1743573 from Jeffrey Sorensen. It contains a neat
+ idea with respect to better memory management by the JVM of C++ allocated memory.
+
+08/10/2007: wsfulton
+ [Perl] Apply patch #1771410 from Wade Brainerd to fix typedef XS(SwigPerlWrapper) in
+ perlrun.swg for ActiveState Perl build 822 and Perl 5.8.9 and 5.10 branches.
+
+08/10/2007: wsfulton
+ [Lua] const enum reference typemaps fixed.
+
+08/09/2007: wsfulton
+ [C#] Added missing support for C++ class member pointers.
+
+08/09/2007: wsfulton
+ [C#, Java] Add support for $owner in the "out" typemaps like in the scripting
+ language modules. Note that $owner has always been supported in the "javaout" / "csout"
+ typemaps.
+
+08/01/2007: wsfulton
+ Fix smart pointer handling for classes that have templated methods within the smart
+ pointer type. Problem reported by craigdo at ee.washington.edu.
+
+07/31/2007: efuzzyone
+ [cffi] fixed memory access after being freed bug. thanks to Martin Percossi.
+ package name clos changed to cl. thanks to Ralf Mattes
+
+07/24/2007: wsfulton
+ Parallel make support added for the examples and test-suite for developers who have
+ more than one CPU. Now parallel make can be used for checking in addition to building
+ the SWIG executable. Some typical checking examples:
+
+ make -j8 -k check
+ make -j4 check-java-test-suite
+ make -j2 check-java-examples
+
+07/19/2007: mgossage
+ Fixed bug that stopped configure working on mingw (applied dos2unix to configure.in)
+
+07/10/2007: mgossage
+ [lua] Extra compatibility with Lua 5.1 (updated SWIG_init, docs, examples, test suite)
+ Removed name clash for static link of multiple modules
+
+07/05/2007: mgossage
+ [lua] Fix a bug in SWIG_ALLOC_ARRAY()
+ improved the error messages for incorrect arguments.
+ Changed the output of swig_type() to use the human readable form of the type,
+ rather than the raw swig type.
+
+07/03/2007: wsfulton
+ [C#] Fix directors for some overloaded methods where the imtype resulted in identical
+ methods being generated in the C# director class, eg void foo(int *) and void foo(double *)
+ used to generated two of these:
+
+ private void SwigDirectorfoo(IntPtr p) { ... }
+
+06/25/2007: wsfulton
+ [Java, C#] Some parameter name changes in std_vector.i allowing better targeting
+ of typemaps for method parameters (for memory management of containers of pointers).
+
+06/07/2007: mutandiz (Mikel Bancroft)
+ [allegrocl]
+ fix foreign-type constructor to properly look for ffitype typemap
+ bindings. fix inout_typemaps.i for strings.
+
+06/06/2007: olly
+ [Ruby]
+ Use whichever of "long" or "long long" is the same size as "void*"
+ to hold pointers as integers, rather than whichever matches off_t.
+ Fixes compilation on OS X and GCC warnings on platforms where
+ sizeof(void*) < sizeof(off_t) (SF patch #1731979).
+
+06/06/2007: olly
+ [PHP5]
+ Fix handling of a particular case involving overloaded functions
+ with default parameters.
+
+06/05/2007: mutandiz (Mikel Bancroft)
+ [allegrocl]
+ Fix case where we'd pass fully qualified identifiers
+ (i.e. NS1::NS2::FOO) to swig-insert-id. All namespaces
+ should be stripped.
+
+ Fix bug in TypedefHandler introduced by last fix.
+
+06/05/2007: olly
+ Fix reporting of filenames in errors after %include (patch from
+ Leigh Smith in #1731040; also reported as #1699940).
+
+05/31/2007: olly
+ [Python]
+ Fix "missing initialiser" warning when compiling generated C/C++
+ wrapper code with Python 2.5 with warnings enabled (patch from
+ bug#1727668 from Luke Moore).
+
+05/29/2007: olly
+ [Python]
+ Split docstrings into separate string literals at each newline when
+ generating C/C++ wrapper code (the C/C++ compiler will just combine
+ them back into a single string literal). This avoids MSVC
+ complaining that the strings are too long (problem reported by
+ Bo Peng on the mailing list).
+
+05/28/2007: olly
+ [Python]
+ Escape backslashes in docstrings.
+
+05/26/2007: olly
+ [Python]
+ Fix autodoc generation of enums to be more consistent with how the
+ enums are wrapped - patch #1697226 from Josh Cherry.
+
+05/26/2007: olly
+ [PHP5]
+ Fix wrapping of methods and functions which return a pointer to a
+ class (bug#1700788) and those which have overloaded forms returning
+ both classes and non-classes (bug#1712717, thanks to Simon
+ Berthiaume for the patch).
+
+05/25/2007: wsfulton
+ Fixed %rename inconsistency in conversion operators as reported by Zhong Ren. The matching
+ is now done on the operator name in the same way as it is done for parameters. For example:
+
+ %rename(opABC) Space::ABC::operator ABC() const;
+ %rename(methodABC) Space::ABC::method(ABC a) const;
+ namespace Space {
+ class ABC {
+ public:
+ void method(ABC a) const {}
+ operator ABC() const { ABC a; return a; }
+ };
+ }
+
+ Note that qualifying the conversion operator previously may or may not have matched.
+ Now it definitely won't, so this will not match:
+
+ %rename(opABC) Space::ABC::operator Space::ABC() const;
+
+ in the same way that this does not match:
+
+ %rename(methodABC) Space::ABC::method(Space::ABC a) const;
+
+ The documentation has been improved with respect to %rename, namespaces and templates.
+ Conversion operators documentation too.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+05/16/2007: mutandiz
+ [allegrocl]
+ Fix bad generation of local var ltype's in functionWrapper().
+ Try to work better with the backward order in which swig
+ unrolls nested class definitions.
+ cleaned up a little unnecessary code/debug printf's.
+ Remove warning when replacing $ldestructor for ff:foreign-pointer
+
+05/12/2007: olly
+ [Python]
+ swig -python -threads now generates C/C++ code which uses Python's
+ own threading abstraction (from pythread.h) rather than OS specific
+ code. The old code failed to compile on MS Windows. (See SF patch
+ tracker #1710341).
+
+05/04/2007: gga
+ [Ruby]
+ Changed STL renames to be global renames. This fixes
+ STL functions not being renamed when autorename is on.
+ This is a not a totally perfect work-around, but better.
+ Someone really needs to fix the template renaming code.
+ (See bug #1545634)
+
+05/04/2007 gga
+ [All]
+ Changed %rename("%(undercase)s") a little so that single
+ numbers at the end of a function are not undercased. That is:
+ getSomething -> get_something
+ get2D -> get_2d
+ get234 -> get_234
+ BUT:
+ asFloat2 -> as_float2
+ (Bug #1699714)
+
+05/03/2007: gga
+ [Ruby]
+ Made __swigtype__ => @__swigtype__ so it can be accessed
+ from the scripting language (and follows Ruby's official
+ documentation, just in case).
+ Made tracking => @__trackings__ for same reason.
+ Currently storing ivars without the @ seems valid, but
+ the PickAxe says this is not correct, so just in case...
+
+05/03/2007: gga
+ [Ruby]
+ Applied patch for -minherit bug and exception classes.
+ This issue should be revisited more closely, as Multiple
+ Inheritance in Ruby is still problematic.
+ (patch/bug #1604878)
+
+05/03/2007: gga
+ [Ruby]
+ Overloaded functions in ruby will now report to the user
+ the possible prototypes when the user mistypes the number or
+ type of a parameter.
+
+05/03/2007: gga
+ [Ruby]
+ Forgot to document the bug fixing of an old bug regarding
+ exceptions.
+ (bug #1458247)
+
+05/03/2007: gga
+ [Ruby]
+ Fixed Ruby documentation to use the proper css styles for
+ each section. Added autodoc section to Ruby's docs to
+ document the features supported by Ruby in documenting its modules.
+ Made rdoc documentation spit out the full name of the class +
+ method name. Albeit this will make the current rdoc not recognize
+ the method, this is still needed to disambiguate between different
+ classes with similar methods (rdoc was created to document the
+ ruby source which only contains one class per c file, unlike swig)
+ I have patched rdoc to make it more friendly to swig. This
+ patch needs to be merged in the ruby std library now.
+
+05/03/2007: gga
+ [Ruby]
+ Changed flag -feature to be -init_name to better reflect its
+ purpose and avoid confusion with -features.
+
+05/03/2007: gga
+ [Ruby]
+ Improved autodoc generation.
+ Added autodoc .swg files to Ruby library for easily adding
+ documentation to common Ruby methods and STL methods.
+ Fixed autodoc documenting of getters and setters and module.
+ Made test suite always generate autodocs.
+
+05/03/2007: gga
+ [Ruby]
+ Removed some warnings from STL and test suite.
+
+05/02/2007: mgossage
+ [Lua] Fixed issues with C++ classes and hierachies across multiple
+ source files. Fixed imports test case & added run test.
+ Added Examples/imports.
+ Added typename for raw lua_State*
+ Added documentation on native functions.
+
+05/02/2007: gga
+ [Ruby]
+ Docstrings are now supported.
+ %feature("autodoc") and %feature("docstring") are now
+ properly supported in Ruby. These features will generate
+ a _wrap.cxx file with rdoc comments in them.
+
+05/02/2007: gga
+ [Ruby]
+ STL files have been upgraded to follow the new swig/python
+ Lib/std conventions.
+ This means std::vector, std::set, std::map, set::multimap,
+ std::multiset, std::deque and std::string are now properly
+ supported, including their iterators, support for containing
+ ruby objects (swig::GC_VALUE) and several other ruby
+ enhancements.
+ std::complex, std::ios, std::iostream, std::iostreambuf and
+ std::sstream are now also supported.
+ std::wstring, std::wios, std::wiostream, std::wiostreambuf
+ and std::wsstream are supported verbatim with no unicode
+ conversion.
+
+ std_vector.i now mimics the behavior of Ruby Arrays much more
+ closely, supporting slicing, shifting, unshifting,
+ multiple indexing and proper return values on assignment.
+
+ COMPATABILITY NOTE: this changes the older api a little bit in
+ that improper indexing would previously (incorrectly) raise
+ exceptions. Now, nil is returned instead, following ruby's
+ standard Array behavior.
+
+05/02/2007: gga
+ [Ruby]
+ Changed the value of SWIG_TYPECHECK_BOOL to be 10000 (ie. higher
+ than that of all integers).
+ This is because Ruby allows typecasting
+ integers down to booleans which can make overloaded functions on
+ bools and integers to fail.
+ (bug# 1488142)
+
+05/02/2007: gga
+ [Ruby]
+ Fixed a subtle bug in multiple argouts that could get triggered if
+ the user returned two or more arguments and the first one was an
+ array.
+
+05/01/2007: gga
+ [Ruby]
+ Improved the documentation to document the new features
+ added, add directorin/out/argout typemaps, etc.
+
+05/01/2007: gga
+ [Ruby]
+ Added %initstack and %ignorestack directives for director
+ functions. These allow you to control whether a director
+ function should re-init the Ruby stack.
+ This is sometimes needed for an embedded Ruby where the
+ director method is used as a C++ callback and not called
+ by the user from ruby code.
+ Explanation:
+ Ruby's GC needs to be aware of the running OS stack in order to
+ mark any VALUE (Ruby objects) it finds there to avoid collection
+ of them. This allows the ruby API to be very simple and allows
+ you to write code like "VALUE a = sth" anywhere without needing
+ to do things like refcounting like python.
+ By default, the start of the stack is set when ruby_init() is
+ called. If ruby is inited within main(), as it usually is the
+ case with the main ruby executable, ruby will be able to calculate
+ its stack properly. However, when this is not possible, as when
+ ruby is embedded as a plugin to an application where main is not
+ available, ruby_init() will be called in the wrong place, and
+ ruby will be incorrectly tracking the stack from the function
+ that called ruby_init() forwards only, which can lead to
+ all sorts of weird crashes or to ruby thinking it has run out of
+ stack space incorrectly.
+ To avoid this, director (callback) functions can now be tagged
+ to try to reset the ruby stack, which will solve the issues.
+ NOTE: ruby1.8.6 still contains a bug in it in that its function
+ to reset the stack will not always do so. This bug is triggered
+ very rarely, when ruby is called from two very distinct places
+ in memory, like a branch of main() and another dso. This bug
+ has now been reported to ruby-core and is pending further
+ investigation.
+ (bug #1700535 and patch #1702907)
+
+04/30/2007: wsfulton
+ Fix #1707582 - Restore building from read-only source directories.
+
+04/30/2007: gga
+ [Ruby]
+ Ruby will now report the parameter index properly on type
+ errors as well as the class and value of the incorrect
+ argument passed.
+ (feature request #1699670)
+
+04/30/2007: gga
+ [Ruby]
+ Ruby no longer creates the free_Class function if the class
+ contains its own user defined free function (%freefunc).
+ (bug #1702882)
+
+04/30/2007: gga
+ [Ruby]
+ Made directors raise a ruby exception for incorrect argout
+ returned values if RUBY_EMBEDDED is set, instead of throwing
+ an actual SwigDirector exception.
+ This will prevent crashes when ruby is embedded and unaware
+ of the SwigDirector exception.
+
+04/30/2007: gga
+ [Ruby]
+ Removed the need for -DSWIGEXTERN.
+ Changed swig_ruby_trackings to be a static variable, but also
+ be kept within a hidden instance variable in the SWIG module.
+ This allows properly dealing with trackings across multiple
+ DSOs, which was previously broken.
+ (bug #1700535 and improvement to patch #1702907)
+
+04/29/2007: gga
+ [Ruby] Fixed GC memory issues with trackings that could lead
+ to segfaults when dealing, mainly, with static variables.
+ (bug #1700535 and patch #1702907)
+
+04/29/2007: gga
+ [Ruby]
+ Fixed String conversion using old ruby1.6 macros. Now
+ StringValuePtr() is used if available. This removes warnings
+ when converting strings with \0 in them.
+ (bug #1700535 and patch #1702907)
+
+04/29/2007: gga
+ [Ruby]
+ Fixed the argout count in directors for Ruby. Previously,
+ ignored or "numinputs=0" typemaps would incorrectly not get
+ counted towards the argout count.
+ (bug/patch #1545585)
+
+04/29/2007: gga
+ [Ruby]
+ Upgraded Ruby converter to recognize "numinputs=0". Previously,
+ only the old "ignore" flag was checked (which would currently
+ still work properly, but is deprecated).
+
+04/29/2007: gga
+ [Ruby - but should be made generic]
+
+ %feature("numoutputs","0") added.
+
+ This feature allows you to ignore the output of a function so
+ that it is not added to a list of output values
+ ( ie. argouts ).
+ This should also become a feature of %typemap(directorout)
+ as "numoutputs"=0, just like "numinputs"=0 exists.
+
+ %feature("directors"=1)
+
+ %include <typemaps.i>
+
+ %feature("numoutputs","0") { Class::member_function1 };
+ %typemap(out) MStatus { // some code, like check mstatus
+ // and raise exception if wrong };
+
+ %inline %{
+ typedef int MStatus;
+ class Class {
+
+ // one argument returned, but director out code added
+ // MStatus is discarded as a return (out) parameter.
+ virtual MStatus member_function1( int& OUTPUT );
+
+ // two arguments returned, director out code added
+ // MStatus is not discarded
+ virtual MStatus member_function2( int& OUTPUT );
+ };
+ %}
+
+
+04/21/2007: olly
+ Fix parsing of float constants with an exponent (e.g. 1e-02f)
+ (bug #1699646).
+
+04/20/2007: olly
+ [Python] Fix lack of generation of docstrings when -O is used.
+ Also, fix generation of docstrings containing a double quote
+ character. Patch from Richard Boulton in bug#1700146.
+
+04/17/2007: wsfulton
+ [Java, C#] Support for adding in Java/C# code before and after the intermediary call,
+ specifically related to the marshalling of the proxy type to the intermediary type.
+ The javain/csin typemap now supports the 'pre' and 'post' attributes to achieve this.
+ The javain typemap also supports an optional 'pgcppname' attribute for premature garbage
+ collection prevention parameter naming and the csin typemap supports an optional 'cshin'
+ attribute for the parameter type used in a constructor helper generated when the type is used
+ in a constructor. Details in the Java.html and CSharp.html documentation.
+
+04/16/2007: olly
+ Don't treat `restrict' as a reserved identifier in C++ mode
+ (bug#1685534).
+
+04/16/2007: olly
+ [PHP5] Fix how zend_throw_exception() is called (bug #1700785).
+
+04/10/2007: olly
+ Define SWIGTEMPLATEDISAMBIGUATOR to template for aCC (reported on
+ swig-user that this is needed).
+
+04/04/2007: olly
+ [PHP5] If ZTS is enabled, release <module>_globals_id in MSHUTDOWN
+ to avoid PHP interpreter crash on shutdown. This solution was
+ suggested here: http://bugs.php.net/bug.php?id=40985
+
+04/03/2007: olly
+ [PHP4] Add missing ZTS annotations to generated C++ wrapper code
+ to fix compilation failures when using ZTS enabled SWIG (Linux
+ distributions tend to disable ZTS, but notably the Windows build
+ uses it by default).
+
+04/01/2007: efuzzyone
+ [CFFI] Patch #1684261: fixes handling of unsigned int literals, thanks Leigh Smith.
+ Also, improved documentation.
+
+03/30/2007: olly
+ Avoid generating '<:' token when using SwigValueWrapper<> on a type
+ which starts with '::' (patch #1690948).
+
+03/25/2007: wuzzeb (John Lenz)
+ [perl5] Add SWIG_fail to the SWIG_exception macro. Fixes a few problems reported
+ on the mailing list.
+
+03/23/2007: wsfulton
+ String copying patch from Josh Cherry reducing memory consumption by about 25%.
+
+03/21/2007: wsfulton
+ [Java] Apply patch #1631987 from Ulrik Peterson - bool INOUT typemaps
+ fail on big endian machines.
+
+03/16/2007: wsfulton
+ Fix seg fault given dodgy C++ code: namespace abc::def { }
+
+03/16/2007: wsfulton
+ [Java] Fixes so that ARRAYSOFCLASSES and ARRAYSOFENUMS in arrays_java.i can be applied
+ to pointer types.
+
+03/03/2007: olly
+ [PHP5] When we know the literal numeric value for a constant, use
+ that to initialise the const member in the PHP wrapper class.
+
+03/02/2007: olly
+ [PHP5] Fix PHP wrapper code generated for certain cases of
+ overloaded forms with default arguments.
+
+02/26/2007: efuzzyone
+ [CFFI] Patch #1656395: fixed hex and octal values bug, thanks to Arthur Smyles.
+
+02/22/2007: mgossage
+ [Lua] Fixed bug in typemaps which caused derived_byvalue and rname test cases to fail.
+ Updated derived_byvalue.i to explain how to find and fix the problem
+
+01/25/2007: wsfulton
+ Fix #1538522 and #1338527, forward templated class declarations without a
+ name for the templated class parameters, such as:
+
+ template <typename, class> class X;
+
+01/23/2007: mgossage
+ [Lua] Patch #1640862: <malloc.h> replaced by <stdlib.h>
+ Patch #1598063 Typo in typemaps.i
+
+01/22/2007: mgossage
+ [Lua] Added a lua specific carrays.i which adds the operator[] support.
+ modified the main code to make it not emit all the class member functions & accessors
+ Note: C structs are created using new_XXX() while C++ classes use XXX() (should be standardised)
+ Updated test case: li_carrays
+ Updated the documentation.
+
+01/12/2007: wsfulton
+ [Php] Add support for newfree typemaps (sometimes used by %newobject)
+
+01/12/2007: beazley
+ New command line option -macroerrors. When supplied, this will force
+ the C scanner/parser to report proper location information for code contained
+ inside SWIG macros (defined with %define). By default, SWIG merely reports
+ errors on the line at which a macro is used. With this option, you
+ can expand the error back to its source---something which may simplify
+ debugging.
+
+01/12/2007: beazley
+ [Internals] Major overhaul of C/C++ scanning implementation. For quite
+ some time, SWIG contained two completely independent C/C++ tokenizers--
+ the legacy scanner in CParse/cscanner.c and a general purpose scanner
+ in Swig/scanner.c. SWIG still has two scanning modules, but the C parser
+ scanner (CParse/cscanner.c) now relies upon the general purpose
+ scanner found in Swig/scanner.c. As a result, it is much smaller and
+ less complicated. This change also makes it possible to maintain all
+ of the low-level C tokenizing in one central location instead of two
+ places as before.
+
+ ***POTENTIAL FLAKINESS***
+ This change may cause problems with accurate line number reporting
+ as well as error reporting more generally. I have tried to resolve this
+ as much as possible, but there might be some corner cases.
+
+01/12/2007: mgossage
+ [Lua] Added typemap throws for std::string*, typemap for SWIGTYPE DYNAMIC,
+ changed the existing throws typemap to throw a string instead of making a copy of
+ the object (updating a few test cases to deal with the change).
+ fixed test case: dynamic_casts, exception_partial_info, li_std_string, size_t
+
+01/03/2007: beazley
+ [Internals]. Use of swigkeys.c/.h variables is revoked. Please use
+ simple strings for attribute names.
+
+12/30/2006: beazley
+ Internal API functions HashGetAttr() and HashCheckAttr() have been revoked.
+ Please use Getattr() to retrieve attributes. The function Checkattr() can
+ be used to check attributes. Note: These functions have been revoked
+ because they only added a marginal performance improvement at the expense
+ code clarity.
+
+12/26/2006: mgossage
+ [Lua] Added more STL (more exceptions, map, size_t),
+ fixed test case: conversion_ns_template.
+
+12/21/2006: mgossage
+ [Lua] Update to throw errors when setting immutables,
+ and allowing user addition of module variables.
+
+12/20/2006: wsfulton
+ Fix typedef'd variable wrappers that use %naturalvar, eg, std::string.
+
+12/14/2006: wsfulton
+ [C#] Add std::wstring and wchar_t typemaps
+
+12/14/2006: olly
+ [php] Fix bug #1613673 (bad PHP5 code generated for getters and
+ setters).
+
+12/02/2006: wsfulton, John Lenz, Dave Beazley
+ Move from cvs to Subversion for source control
+
+11/30/2006: beazley
+ Cleaned up swigwarnings.swg file not to use nested macro
+ definitions.
+
+11/12/2006: wsfulton
+ [Java, C#] Fix for %extend to work for static member variables.
+
+Version 1.3.31 (November 20, 2006)
+==================================
+
+11/12/2006: Luigi Ballabio
+ [Python] Alternate fix for Python exceptions bug #1578346 (the previous one broke Python
+ properties in modern classes)
+
+11/12/2006: wsfulton
+ -fakeversion commandline option now generates the fake version into the generated wrappers
+ as well as displaying it when the -version commandline option is used.
+
+14/11/2006: mgossage
+ [lua] update to typemap for object by value, to make it c89 compliant
+
+Version 1.3.30 (November 13, 2006)
+==================================
+
+11/12/2006: wsfulton
+ [java] Remove DetachCurrentThread patch from 08/11/2006 - it causes segfaults
+ on some systems.
+
+11/12/2006: wsfulton
+ [python] Fix #1578346 - Python exceptions with -modern
+
+11/10/2006: wsfulton
+ Fix #1593291 - Smart pointers and inheriting from templates
+
+11/09/2006: wsfulton
+ Fix director operator pointer/reference casts - #1592173.
+
+11/07/2006: wsfulton
+ Add $self special variable for %extend methods. Please use this instead of just 'self'
+ as the C++ 'this' pointer.
+
+11/07/2006: mutandiz
+ [allegrocl]
+ allegrocl.swg: swig-defvar updated to allow specifying of
+ non-default foreign type (via :ftype keyword arg).
+ allegrocl.cxx: Specify proper access type for enum values.
+
+11/03/2006: wsfulton
+ [Java/C#] Fix const std::string& return types for directors as reported by
+ Mark Donselzmann
+
+10/29/2006: wsfulton
+ [Java] Remove DeleteLocalRef from end of director methods for now as it is causing a
+ seg fault when run on Solaris 8.
+
+10/29/2006: wuzzeb (John Lenz)
+ [Guile] Patch from Chris Shoemaker to clean up some warnings in the generated code.
+
+10/29/2006: wsfulton
+ [Java] Important fix to prevent early garbage collection of the Java proxy class
+ while it is being used in a native method. The finalizer could destroy the underlying
+ C++ object while it was being used. The problem occurs when the proxy class is no
+ longer strongly reachable after a native call. The problem seems to occur in
+ memory stress situations on some JVMs. It does not seem to occur on the
+ Sun client JVM up to jdk 1.5. However the 1.6 client jdk has a more aggressive garbage
+ collector and so the problem does occur. It does occur on the Sun server
+ JVMs (certainly 1.4 onwards). The fix entails passing the proxy class into the native
+ method in addition to the C++ pointer in the long parameter, as Java classes are not
+ collected when they are passed into JNI methods. The extra parameter can be suppressed
+ by setting the nopgcpp attribute in the jtype typemap to "1" or using the new -nopgcpp
+ commandline option.
+
+ See Java.html#java_pgcpp for further details on this topic.
+
+10/24/2006: wsfulton
+ [C#] Fix smart pointer wrappers. The virtual/override/new keyword is not generated
+ for each method as the smart pointer class does not mirror the underlying pointer
+ class inheritance hierarchy. SF #1496535
+
+10/24/2006: mgossage
+ [lua] added support for native methods & member function pointers.
+ fixed test cases arrays_dimensionless & cpp_basic. Added new example (functor).
+ tidied up a little of the code (around classHandler).
+
+10/17/2006: wsfulton
+ [C#, Java] directorout typemap changes to fall in line with the other director
+ languages. $result is now used where $1 used to be used. Please change your typemaps
+ if you have a custom directorout typemap.
+
+10/18/2006: wsfulton
+ Some fixes for applying the char array typemaps to unsigned char arrays.
+
+10/17/2006: wsfulton
+ [C#, Java] Add in const size_t& and const std::size_t& typemaps.
+
+10/15/2006: efuzzyone
+ [CFFI] Suppress generating defctype for enums, thanks to Arthur Smyles. Patch 1560983.
+
+10/14/2006: wuzzeb (John Lenz)
+ [Chicken] Minor fix to make SWIG work with the (as yet unreleased) chicken 2.5
+
+ [Guile,Chicken] Fix SF Bug 1573892. Added an ext_test to the test suite to test
+ this bug, but this test can not really be made generic because the external code must
+ plug into the target language interpreter directly.
+ See Examples/test-suite/chicken/ext_test.i and ext_test_external.cxx
+
+ Added a %.externaltest to common.mk, and any interested language modules can
+ copy and slightly modify either the chicken or the guile ext_test.i
+
+10/14/2006: mgossage
+ [Lua] added OUTPUT& for all number types, added a long long type
+ fixed several test cases.
+ update: changed typemaps to use SWIG_ConvertPtr rather than SWIG_MustGetPointer
+ started spliting lua.swg into smaller parts to make it neater
+
+10/13/2006: wsfulton
+ [C#, Java] Marginally better support for multiple inheritance only in that you can
+ control what the base class is. This is done using the new 'replace' attribute in the
+ javabase/csbase typemap, eg in the following, 'Me' will be the base class,
+ no matter what Foo is really derived from in the C++ layer.
+
+ %typemap(javabase, replace="1") Foo "Me"
+ %typemap(csbase, replace="1") Foo "Me"
+
+ Previously it was not possible for the javabase/csbase typemaps to override the C++ base.
+
+10/12/2006: wsfulton
+ [Java] Remove potential race condition on the proxy class' delete() method
+ (it is now a synchronized method, but is now customisable by changing the
+ methodmodifiers attribute in the javadestruct or javadestruct_derived typemap)
+
+ [C#] Remove potential race condition on the proxy class' Dispose() method,
+ similar to Java's delete() above.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+10/12/2006: wsfulton
+ [Ruby, Python] Remove redundant director code in %extend methods (%extend
+ methods cannot be director methods)
+
+10/12/2006: wsfulton
+ [Ruby, Python] Fix #1505594 - director objects not returned as director objects
+ in %extend methods.
+
+10/11/2006: wsfulton
+ [Java] Fix #1238798 - Directors using unsigned long long or any other type
+ marshalled across the JNI boundary using a Java class (where the jni typemap
+ contains jobject).
+
+10/06/2006: wsfulton
+ Fix #1162194 - #include/%include within a structure
+
+10/06/2006: wsfulton
+ Fix #1450661, string truncation in String_seek truncating Java/C# enums.
+
+10/06/2006: mgossage
+ [Lua] Fix #1569587. The name is now correct.
+
+10/04/2006: wsfulton
+ Director fixes for virtual conversion operators
+
+10/04/2006: olly
+ [php] Fix #1569587 for PHP. Don't use sizeof() except with string
+ literals. Change some "//" comments to "/* */" for portability.
+
+10/04/2006: mgossage
+ [Lua] Partial Fix #1569587. The type is now correct, but the name is still not correct.
+
+10/03/2006: wsfulton
+ [Ruby] Fix #1527885 - Overloaded director virtual methods sometimes produced
+ uncompilable code when used with the director:except feature.
+
+10/03/2006: wsfulton
+ Directors: Directors are output in the order in which they are declared in
+ the C++ class rather than in some pseudo-random order.
+
+10/03/2006: mmatus
+ Fix #1486281 and #1471039.
+
+10/03/2006: olly
+ [Perl] Fix for handling strings with zero bytes from Stephen Hutsal.
+
+09/30/2006: efuzzyone
+ [CFFI] Bitfield support and vararg support due to Arthur Smyles.
+ C expression to Lisp conversion, thanks to Arthur Smyles for the initial
+ idea, it now supports conversion for a whole range of C expressions.
+
+09/28/2006: wsfulton
+ Fix #1508327 - Overloaded methods are hidden when using -fvirtual optimisation.
+ Overloaded methods are no longer candidates for elimination - this mimics
+ C++ behaviour where all overloaded methods must be defined and implemented
+ in a derived class in order for them to be available.
+
+09/25/2006: wsfulton
+ [Ruby, Python, Ocaml] Fix #1505591 Throwing exceptions in extended directors
+
+09/25/2006: wsfulton
+ Fix #1056100 - virtual operators.
+
+09/24/2006: olly
+ Don't accidentally create a "<:" token (which is the same as "[" in C++).
+ Fixes bug # 1521788.
+
+09/23/2006: olly
+ [Ruby] Support building with recent versions of the Ruby 1.9
+ development branch. Fixes bug #1560092.
+
+09/23/2006: olly
+ Templates can now be instantiated using negative numbers and
+ constant expressions, e.g.:
+
+ template<int q> class x {};
+ %template(x_minus1) x<-1>;
+ %template(x_1plus2) x<1+2>;
+
+ Also, constant expressions can now include comparisons (>, <, >=,
+ <=, !=, ==), modulus (%), and ternary conditionals (a ? b : c).
+
+ Fixes bugs #646275, #925555, #956282, #994301.
+
+09/22/2006: wsfulton
+ Fix %ignore on director methods - Bugs #1546254, #1543533
+
+09/20/2006: wsfulton
+ Fix %ignore on director constructors
+
+09/20/2006: wsfulton
+ Fix seg faults and asserts when director methods are ignored (#1543533)
+
+09/20/2006: wsfulton
+ Fix out of source builds - bug #1544718
+
+09/20/2006: olly
+ Treat a nested class definition as a forward declaration rather
+ than ignoring it completely, so that we generate correct code for
+ passing opaque pointers to the nested class (fixes SF bug #909387).
+
+09/20/2006: olly
+ *** POTENTIAL INCOMPATIBILITY ***
+ [php] Overload resolution now works. However to allow this, SWIG
+ generated wrappers no longer coerce PHP types (which reverts a change
+ made in 1.3.26). So for example, if a method takes a string, you
+ can no longer pass a number without explicitly converting it to a
+ string in PHP using: (string)x
+
+09/18/2006: mgossage
+ [ALL] fix on swiginit.swg, has been reported to crash on several test cases
+ found and fixed problem in imports under python (mingw)
+
+09/16/2006: wsfulton
+ [Python] Patch from Michal Marek for Python 2.5 to fix 64 bit array indexes on
+ 64 bit machines.
+
+09/13/2006: wsfulton
+ The explicitcall feature has been scrapped. This feature was introduced primarily
+ to solve recursive director method calls. Director upcall improvements made instead:
+
+ [Python, Ruby, Ocaml] The swig_up flag is no longer used. The required mutexes
+ wrapping this flag are also no longer needed. The recursive calls going from C++
+ to the target language and back again etc are now avoided by a subtlely different
+ approach. Instead of using the swig_up flag in each director method to indicate
+ whether the explicit C++ call to the appropriate base class method or a normal
+ polymorphic C++ call should be made, the new approach makes one of these calls
+ directly from the wrapper method.
+
+ [Java, C#] The recursive call problem when calling a C++ base class method from
+ Java/C# is now fixed. The implementation is slightly different to the other languages
+ as the detection as to whether the explicit call or a normal polymorphic call is made
+ in the Java/C# layer rather than in the C++ layer.
+
+09/11/2006: mgossage
+ [ALL] updated swiginit.swg to allow multiple interpreters to use multiple
+ swig modules at once. This has been tested in Lua (mingw & linux),
+ perl5 & python (linux) only.
+
+09/11/2006: mgossage
+ [lua] added support for passing function pointers as well as native lua object
+ into wrappered function.
+ Added example funcptr3 to demonstrate this feature
+
+09/05/2006: olly
+ [php] Rename ErrorCode and ErrorMsg #define-s to SWIG_ErrorCode
+ and SWIG_ErrorMsg to avoid clashes with code the user might be
+ wrapping (patch from Darren Warner in SF bug #1466086). Any
+ user typemaps which use ErrorCode and/or ErrorMsg directly will
+ need adjusting - you can easily fix them to work with both old
+ and new SWIG by changing to use SWIG_ErrorMsg and adding:
+
+ #ifndef SWIG_ErrorMsg
+ #define SWIG_ErrorMsg() ErrorMsg()
+ #endif
+
+08/29/2006: olly
+ [php] Move constant initialisation from RINIT to MINIT to fix a
+ warning when using Apache and mod_php. We only need to create
+ PHP constants once when we're first initialised, not for every HTTP
+ request.
+
+08/21/2006: mgossage
+ [Lua]
+ Bugfix #1542466 added code to allow mapping Lua nil's <-> C/C++ NULL's
+ updated various typemaps to work correctly with the changes
+ added voidtest_runme.lua to show the features working
+
+08/19/2006: wuzzeb (John Lenz)
+ [Guile] Add feature:constasvar to export constants as variables instead of functions
+ that return the constant value.
+
+08/11/2006: wsfulton
+ [Java] DetachCurrentThread calls have been added so that natively created threads
+ no longer prevent the JVM from exiting. Bug reported by Thomas Dudziak and
+ Paul Noll.
+
+08/10/2006: wsfulton
+ [C#] Fix director protected methods so they work
+
+07/25/2006: mutandiz
+ [allegrocl]
+ more additions to std::string, some tweaks and small bug fixes
+ -nocwrap mode.
+
+07/21/2006: mgossage
+ [Lua]
+ Bugfix #1526022 pdated std::string to support strings with '\0' inside them
+ updated typemaps.i to add support for pointer to pointers
+
+07/19/2006: mutandiz
+ [allegrocl]
+ - Add std_string.i support.
+ - Add newobject patch submitted by mkoeppe (thanks!)
+ - Fix type name mismatch issue for nested type definitions.
+ specifically typedefs in templated class defns.
+
+07/18/2006: mgossage
+ Bugfix #1522858
+ updated lua.cxx to support -external-runtime command
+
+07/14/2006: wuzzeb (John Lenz)
+ Increment the SWIG_RUNTIME_VERSION to 3, because of the
+ addition of the owndata member in swig_type_info.
+ Reported by: Prabhu Ramachandran
+
+07/05/2006: wsfulton
+ Search path fixes:
+ - Fix search path for library files to behave as documented in Library.html.
+ - Fix mingw/msys builds which did not find the SWIG library when installed.
+ - Windows builds also output the mingw/msys install location when running
+ swig -swiglib.
+ - The non-existent and undocumented config directory in the search path has
+ been removed.
+
+07/05/2006: wsfulton
+ Fix $symname special variable expansion.
+
+07/04/2006: wuzzeb (John Lenz)
+ [Chicken]
+ Add %feature("constasvar"), which instead of exporting a constant as a
+ scheme function, exports the constant as a scheme variable. Update the
+ documentation as well.
+
+07/04/2006: wsfulton
+ [See entry of 09/13/2006 - explicitcall feature and documentation to it removed]
+ New explicitcall feature which generates additional wrappers for virtual methods
+ that call the method explicitly, not relying on polymorphism to make the method
+ call. The feature is a feature flag and is enabled like any other feature flag.
+ It also recognises an attribute, "suffix" for mangling the feature name, see
+ SWIGPlus.html#SWIGPlus_explicitcall documentation for more details.
+
+ [Java, C#]
+ The explicitcall feature is also a workaround for solving the recursive calls
+ problem when a director method makes a call to a base class method. See
+ Java.html#java_directors_explicitcall for updated documentation.
+
+06/28/2006: joe (Joseph Wang)
+ [r] Initial support for R
+
+06/20/2006: wuzzeb (John Lenz)
+ [Chicken]
+ Minor fixes to get apply_strings.i testsuite to pass
+ Remove integers_runme.scm from the testsuite, because SWIG and Chicken does
+ handle overflows.
+
+06/19/2005: olly
+ [php] Add support for generating PHP5 class wrappers for C++
+ classes (use "swig -php5").
+
+06/17/2006: olly
+ [php] Added some missing keywords to the PHP4 keyword list, and
+ fixed __LINE__ and __FILE__ which were in the wrong category.
+ Also added all the keywords new in PHP5, and added comments
+ noting the PHP4 keywords which aren't keywords in PHP5.
+
+06/17/2006: olly
+ [php] Don't segfault if PHP Null is passed as this pointer (e.g.
+ Class_method(Null)) - give a PHP Error instead.
+
+06/15/2006: mutandiz
+ [allegrocl]
+ Add initial support for std::list container class.
+ Fix a few bugs in helper functions.
+
+05/13/2006: wsfulton
+ [Java] Replace JNIEXPORT with SWIGEXPORT, thereby enabling the possibility
+ of using gcc -fvisibility=hidden for potentially smaller faster loading wrappers.
+
+05/13/2006: wsfulton
+ Fix for Makefiles for autoconf-2.60 beta
+
+05/13/2006: wsfulton
+ Vladimir Menshakov patch for compiling wrappers with python-2.5 alpha.
+
+05/12/2006: wsfulton
+ Fix buffer overflow error when using large %feature(docstring) reported
+ by Joseph Winston.
+
+05/12/2006: wsfulton
+ [Perl] Operator overload fix from Daniel Moore.
+
+05/25/2006: mutandiz
+ [allegrocl]
+ Fix bug in generation of CLOS type declarations for unions
+ and equivalent types.
+
+05/24/2006: mutandiz
+ [allegrocl]
+ Don't require a full class definition to generate a CLOS wrapper.
+
+05/20/2006: olly
+ [php] GCC Visibility support now works with PHP.
+
+05/19/2006: olly
+ [php] Removed support for -dlname (use -module instead). Fixed
+ naming of PHP extension module to be consistent with PHP
+ conventions (no "php_" prefix on Unix; on PHP >= 4.3.0, handle Unix
+ platforms which use something other than ".so" as the extension.)
+
+05/13/2006: wsfulton
+ [C#] Director support added
+
+05/07/2006: olly
+ [php] Don't segfault if PHP Null is passed where a C++ reference
+ is wanted.
+
+05/05/2006: olly
+ [php] Fix wrappers generated for global 'char' variables to not
+ include a terminating zero byte in the PHP string.
+
+05/03/2006: wsfulton
+ Modify typemaps so that char * can be applied to unsigned char * or signed char *
+ types and visa versa.
+
+05/03/2006: efuzzyone
+ [cffi]Thanks to Luke J Crook for this idea.
+ - a struct/enum/union is replaced with :pointer only if
+ that slot is actually a pointer to that type. So,:
+ struct a_struct { int x; } and
+ struct b_struct { a_struct struct_1; };
+ will be converted as:
+ (cffi:defcstruct b_struct
+ (struct_1 a_struct))
+ - Other minor fixes in lispifying names.
+
+05/02/2006: wsfulton
+ Fix possible redefinition of _CRT_SECURE_NO_DEPRECATE for VC++.
+
+04/14/2006: efuzzyone
+ [cffi]
+ Thanks to Thomas Weidner for the patch.
+ - when feature export is set (export 'foo) is
+ generated for every symbol
+ - when feature inline is set (declaim (inline foo)) is
+ generated before every function definition
+ - when feature intern_function is set
+ #.(value-of-intern-function "name" "nodeType" package)
+ is emitted instead of the plain symbol. A sample swig-lispify
+ is provided.
+ - every symbol is prefixed by it's package.
+
+04/13/2006: efuzzyone
+ [cffi]
+ Fixed the generation of wrappers for global variables.
+ Added the option [no]swig-lisp which turns on/off generation
+ of code for swig helper lisp macro, functions, etc.
+
+Version 1.3.29 (March 21, 2006)
+===============================
+
+04/05/2006: mutandiz
+ [allegrocl]
+ Fix output typemap of char so it produces a character instead
+ of an integer. Also adds input/output typemaps for 'char *'.
+
+ add command-line argument -isolate to generate an interface
+ file that won't interfere with other SWIG generated files that
+ may be used in the same application.
+
+03/20/2005: mutandiz
+ [allegrocl]
+ More tweaks to INPUT/OUTPUT typemaps for bool.
+
+ Fix constantWrapper for char and string literals.
+
+ find-definition keybindings should work in ELI/SLIME.
+ Output (in-package <module-name>) to lisp wrapper
+ instead of (in-package #.*swig-module-name*).
+
+ slight rework of multiple return values.
+
+ doc updates.
+
+03/17/2005: mutandiz
+ [allegrocl]
+ mangle names of constants generated via constantWrapper.
+
+ When using OUTPUT typemaps and the function has a non-void
+ return value, it should be first in the values-list, followed
+ by the OUTPUT mapped values.
+
+ Fix bug with boolean parameters, which needed to be
+ passed in as int values, rather than T or NIL.
+
+03/15/2006: mutandiz
+ [allegrocl]
+ Generate wrappers for constants when in C++ or -cwrap mode.
+ Make -cwrap the default, since it is most correct. Users
+ can use the -nocwrap option to avoid the creation of a .cxx
+ file when interfacing to C code.
+
+ When in -nocwrap mode, improve the handling of converting
+ infix literals to prefix notation for lisp. This is very
+ basic and not likely to be improved upon since this only
+ applies to the -nocwrap case. Literals we can't figure out
+ will result in a warning and be included in the generated
+ code.
+
+ validIdentifier now more closely approximates what may be
+ a legal common lisp symbol.
+
+ Fix typemap error in allegrocl.swg
+
+03/12/2006: mutandiz
+ [allegrocl]
+ fix up INPUT/OUTPUT typemaps for bool.
+ Generate c++ style wrapper functions for struct/union members
+ when -cwrap option specified.
+
+03/10/2006: mutandiz
+ [allegrocl]
+ Fix bug in C wrapper generation introduced by last allegrocl
+ commit.
+
+03/10/2006: wsfulton
+ [Java]
+ Commit #1447337 - Delete LocalRefs at the end of director methods to fix potential leak
+
+03/10/2006: wsfulton
+ Fix #1444949 - configure does not honor --program-prefix.
+ Removed non-standard configure option --with-release-suffix. Fix the autoconf standard
+ options --program-prefix and --program-suffix which were being shown in the help,
+ but were being ignored. Use --program-suffix instead of --with-release-suffix now.
+
+03/10/2006: wsfulton
+ [Java]
+ Fix #1446319 with patch from andreasth - more than one wstring parameter in director methods
+
+03/07/2006: mkoeppe
+ [Guile]
+ Fix for module names containing a "-" in non-"shadow" mode.
+ Patch from Aaron VanDevender (#1441474).
+
+03/04/2006: mmatus
+ - Add -O to the main program, which now enables -fastdispatch
+
+ [Python]
+
+ - Add the -fastinit option to enable faster __init__
+ methods. Setting 'this' as 'self.this.append(this)' in the python
+ code confuses PyLucene. Now the initialization is done in the
+ the C++ side, as reported by Andi and Robin.
+
+ - Add the -fastquery option to enable faster SWIG_TypeQuery via a
+ python dict cache, as proposed by Andi Vajda
+
+ - Avoid to call PyObject_GetAttr inside SWIG_Python_GetSwigThis,
+ since this confuses PyLucene, as reported by Andi Vajda.
+
+03/02/2006: wsfulton
+ [Java]
+ Removed extra (void *) cast when casting pointers to and from jlong as this
+ was suppressing gcc's "dereferencing type-punned pointer will break strict-aliasing rules"
+ warning. This warning could be ignored in versions of gcc prior to 4.0, but now the
+ warning is useful as gcc -O2 and higher optimisation levels includes -fstrict-aliasing which
+ generates code that doesn't work with these casts. The assignment is simply never made.
+ Please use -fno-strict-aliasing to both suppress the warning and fix the bad assembly
+ code generated. Note that the warning is only generated by the C compiler, but not
+ the C++ compiler, yet the C++ compiler will also generate broken code. Alternatively use
+ -Wno-strict-aliasing to suppress the warning for gcc-3.x. The typemaps affected
+ are the "in" and "out" typemaps in java.swg and arrays_java.swg. Users ought to fix
+ their own typemaps to do the same. Note that removal of the void * cast simply prevents
+ suppression of the warning for the C compiler and nothing else. Typical change:
+
+ From:
+ %typemap(in) SWIGTYPE * %{ $1 = *($&1_ltype)(void *)&$input; %}
+ To:
+ %typemap(in) SWIGTYPE * %{ $1 = *($&1_ltype)&$input; %}
+
+ From:
+ %typemap(out) SWIGTYPE * %{ *($&1_ltype)(void *)&$result = $1; %}
+ To:
+ %typemap(out) SWIGTYPE * %{ *($&1_ltype)&$result = $1; %}
+
+03/02/2006: mkoeppe
+ [Guile -scm]
+ Add typemaps for "long long"; whether the generated code compiles, however, depends
+ on the version and configuration of Guile.
+
+03/02/2006: wsfulton
+ [C#]
+ Add support for inner exceptions. If any of the delegates are called which construct
+ a pending exception and there is already a pending exception, it will create the new
+ exception with the pending exception as an inner exception.
+
+03/02/2006: wsfulton
+ [Php]
+ Added support for Php5 exceptions if compiling against Php5 (patch from Olly Betts).
+
+03/01/2006: mmatus
+ Use the GCC visibility attribute in SWIGEXPORT.
+
+ Now you can compile (with gcc 3.4 or later) using
+ CFLAGS="-fvisibility=hidden".
+
+ Check the difference for the 'std_containers.i' python
+ test case:
+
+ Sizes:
+
+ 3305432 _std_containers.so
+ 2383992 _std_containers.so.hidden
+
+ Exported symbols (nm -D <file>.so | wc -l):
+
+ 6146 _std_containers.so
+ 174 _std_containers.so.hidden
+
+ Execution times:
+
+ real 0m0.050s user 0m0.039s sys 0m0.005s _std_containers.so
+ real 0m0.039s user 0m0.026s sys 0m0.007s _std_containers.so.hidden
+
+ Read http://gcc.gnu.org/wiki/Visibility for more details.
+
+
+02/27/2006: mutandiz
+ [allegrocl]
+ Add support for INPUT, OUTPUT, and INOUT typemaps.
+ For OUTPUT variables, the lisp wrapper returns multiple
+ values.
+
+02/26/2006: mmatus
+
+ [Ruby] add argcargv.i library file.
+
+ Use it as follow:
+
+ %include argcargv.i
+
+ %apply (int ARGC, char **ARGV) { (size_t argc, const char **argv) }
+
+ %inline {
+ int mainApp(size_t argc, const char **argv)
+ {
+ return argc;
+ }
+ }
+
+ then in the ruby side:
+
+ args = ["asdf", "asdf2"]
+ n = mainApp(args);
+
+
+ This is the similar to the python version Lib/python/argcargv.i
+
+02/24/2006: mgossage
+
+ Small update Lua documents on troubleshooting problems
+
+02/22/2006: mmatus
+
+ Fix all the errors reported for 1.3.28.
+ - fix bug #1158178
+ - fix bug #1060789
+ - fix bug #1263457
+ - fix 'const char*&' typemap in the UTL, reported by Geoff Hutchison
+ - fixes for python 2.1 and the runtime library
+ - fix copyctor + template bug #1432125
+ - fix [ 1432152 ] %rename friend operators in namespace
+ - fix gcc warning reported by R. Bernstein
+ - avoid assert when finding a recursive scope inheritance,
+ emit a warning in the worst case, reported by Nitro
+ - fix premature object deletion reported by Paul in tcl3d
+ - fix warning reported by Nitro in VC7
+ - more fixes for old Solaris compiler
+ - fix for python 2.3 and gc_refs issue reported by Luigi
+ - fix fastproxy for methods using kwargs
+ - fix overload + protected member issue reported by Colin McDonald
+ - fix seterrormsg as reported by Colin McDonald
+ - fix directors, now the test-suite runs again using -directors
+ - fix for friend operator and Visual studio and bug 1432152
+ - fix bug #1435090
+ - fix using + %extend as reported by William
+ - fix bug #1094964
+ - fix for Py_NotImplemented as reported by Olly and Amaury
+ - fix nested namespace issue reported by Charlie
+
+ and also:
+
+ - allow director protected members by default
+ - delete extra new lines in swigmacros[UTL]
+ - cosmetic for generated python code
+ - add the factory.i library for UTL
+ - add swigregister proxy method and move __repr__ to a
+ single global module [python]
+
+02/22/2006: mmatus
+
+ When using directors, now swig will emit all the virtual
+ protected methods by default.
+
+ In previous releases, you needed to use the 'dirprot'
+ option to achieve the same.
+
+ If you want, you can disable the new default behaviour,
+ use the 'nodirprot' option:
+
+ swig -nodirprot ...
+
+ and/or the %nodirector feature for specific methods, i.e.:
+
+ %nodirector Foo::bar;
+
+ struct Foo {
+ virtual ~Foo();
+
+ protected:
+ virtual void bar();
+ };
+
+
+ As before, pure abstract protected members are allways
+ emitted, independent of the 'dirprot/nodirprot' options.
+
+
+02/22/2006: mmatus
+ Add the factory.i library for languages using the UTL (python,tcl,ruby,perl).
+
+ factory.i implements a more natural wrap for factory methods.
+
+ For example, if you have:
+
+ ---- geometry.h --------
+ struct Geometry {
+ enum GeomType{
+ POINT,
+ CIRCLE
+ };
+
+ virtual ~Geometry() {}
+ virtual int draw() = 0;
+
+ //
+ // Factory method for all the Geometry objects
+ //
+ static Geometry *create(GeomType i);
+ };
+
+ struct Point : Geometry {
+ int draw() { return 1; }
+ double width() { return 1.0; }
+ };
+
+ struct Circle : Geometry {
+ int draw() { return 2; }
+ double radius() { return 1.5; }
+ };
+
+ //
+ // Factory method for all the Geometry objects
+ //
+ Geometry *Geometry::create(GeomType type) {
+ switch (type) {
+ case POINT: return new Point();
+ case CIRCLE: return new Circle();
+ default: return 0;
+ }
+ }
+ ---- geometry.h --------
+
+
+ You can use the %factory with the Geometry::create method as follows:
+
+ %newobject Geometry::create;
+ %factory(Geometry *Geometry::create, Point, Circle);
+ %include "geometry.h"
+
+ and Geometry::create will return a 'Point' or 'Circle' instance
+ instead of the plain 'Geometry' type. For example, in python:
+
+ circle = Geometry.create(Geometry.CIRCLE)
+ r = circle.radius()
+
+ where 'circle' now is a Circle proxy instance.
+
+
+02/17/2006: mkoeppe
+ [MzScheme] Typemaps for all integral types now accept the full range of integral
+ values, and they signal an error when a value outside the valid range is passed.
+ [Guile] Typemaps for all integral types now signal an error when a value outside
+ the valid range is passed.
+
+02/13/2006: mgossage
+ [Documents] updated the extending documents to give a skeleton swigging code
+ with a few typemaps.
+ [Lua] added an extra typemap for void* [in], so a function which requires a void*
+ can take any kind of pointer
+
+Version 1.3.28 (February 12, 2006)
+==================================
+
+02/11/2006: mmatus
+ Fix many issues with line counting and error reports.
+
+02/11/2006: mmatus
+ [Python] Better static data member support, if you have
+
+ struct Foo {
+ static int bar;
+ };
+
+ then now is valid to access the static data member, ie:
+
+ f = Foo()
+ f.bar = 3
+
+ just as in C++.
+
+
+02/11/2006: wsfulton
+ [Perl]
+ Fixed code generation to work again with old versions of Perl
+ (5.004 and later tested)
+
+02/04/2006: mmatus
+ [Python] Add the %extend_smart_pointer() directive to extend
+ SWIG smart pointer support in python.
+
+ For example, if you have a smart pointer as:
+
+ template <class Type> class RCPtr {
+ public:
+ ...
+ RCPtr(Type *p);
+ Type * operator->() const;
+ ...
+ };
+
+ you use the %extend_smart_pointer directive as:
+
+ %extend_smart_pointer(RCPtr<A>);
+ %template(RCPtr_A) RCPtr<A>;
+
+ then, if you have something like:
+
+ RCPtr<A> make_ptr();
+ int foo(A *);
+
+ you can do the following:
+
+ a = make_ptr();
+ b = foo(a);
+
+ ie, swig will accept a RCPtr<A> object where a 'A *' is
+ expected.
+
+ Also, when using vectors
+
+ %extend_smart_pointer(RCPtr<A>);
+ %template(RCPtr_A) RCPtr<A>;
+ %template(vector_A) std::vector<RCPtr<A> >;
+
+ you can type
+
+ a = A();
+ v = vector_A(2)
+ v[0] = a
+
+ ie, an 'A *' object is accepted, via implicit conversion,
+ where a RCPtr<A> object is expected. Additionally
+
+ x = v[0]
+
+ returns (and sets 'x' as) a copy of v[0], making reference
+ counting possible and consistent.
+
+ %extend_smart_pointer is just a collections of new/old
+ tricks, including %typemaps and the new %implicitconv
+ directive.
+
+02/02/2006: mgossage
+ bugfix #1356577, changed double=>lua_number in a few places.
+ added the std::pair wrapping
+
+01/30/2006: wsfulton
+ std::string and std::wstring member variables and global variables now use
+ %naturalvar by default, meaning they will now be wrapped as expected in all languages.
+ Previously these were wrapped as a pointer rather than a target language string.
+ It is no longer necessary to add the following workaround to wrap these as strings:
+
+ %apply const std::string & { std::string *}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+01/28/2006: mkoeppe
+ [Guile -scm]
+ Add typemaps for handling of member function pointers.
+
+01/24/2006: mmatus
+ - Better support for the %naturalvar directive, now it
+ works with the scripting languages as well as
+ Java/C#.
+
+ Now, it can also be applied to class types:
+
+ %naturalvar std::string;
+ %include <std_string.i>
+
+ that will tell swig to use the 'natural' wrapping
+ mechanism to all std::string global and member
+ variables.
+
+ - Add support for the %allowexcept feature along the
+ scripting languages, which allows the %exception feature
+ to be applied to the variable access methods. Also, add
+ the %exceptionvar directive to specify a distintic
+ exception mechanism only for variables.
+
+
+ - Add more docs for the %delobject directive to mark a method as a
+ destructor, 'disowning' the first argument. For example:
+
+ %newobject create_foo;
+ %delobject destroy_foo;
+
+ Foo *create_foo() { return new Foo(); }
+ void destroy_foo(Foo *foo) { delete foo; }
+
+ or in a member method as:
+
+ %delobject Foo::destroy;
+
+ class Foo {
+ public:
+ void destroy() { delete this;}
+
+ private:
+ ~Foo();
+ };
+
+
+01/24/2006: mgossage
+ [Lua]
+ - Removed the type swig_lua_command_info & replace with luaL_reg
+ (which then broke the code), fixed this
+ - added an additional cast in the typemaps for enum's
+ due to the issue that VC.Net will not allow casting of
+ a double to an enum directly. Therefore cast to int then to enum
+ (thanks to Jason Rego for this observation)
+
+01/16/2006: mmatus (Change disabled... will be back in CVS soon)
+ Add initial support for regexp via the external library
+ RxSpencer. SWIG doesn't require this library to compile
+ and/or run. But if you specify --with-rxspencer, and the
+ library is found during installation, then swig will use
+ it in three places:
+
+ - In %renames rules, via the new rxsmatch rules, for example:
+
+ %rename("%(lowercase)",rxsmatch$name="GSL_.*") "";
+ %rename("%(lowercase)",rxsmatch$nodeType="enum GSL_.*") "";
+
+ rxsmatch is similar to the match rule, it just uses
+ the RxSpencer regexp library to decide if there is a
+ match with the provided regexp. As with the match
+ rule, you can also use the negate rule notrxsmatch.
+
+ - In the %rename target name via the rxstarget option, for example:
+
+ %rename("%(lowercase)",rxstarget=1) "GSL_.*";
+
+ where the target name "GSL.*" is now understood as a
+ regexp to be matched.
+
+ - In the new encoder "rxspencer", which looks like:
+
+ %(rxspencer:[regexp][replace])s
+
+ where "regexp" is the regular expression and "replace"
+ is a string used as a replacement, where the @0,@1,...,@9
+ pseudo arguments are used to represent the
+ corresponding matching items in the reg expression.
+
+ For example:
+
+ %(rxspencer:[GSL.*][@0])s <- Hello ->
+ %(rxspencer:[GSL.*][@0])s <- GSLHello -> GSLHello
+ %(rxspencer:[GSL(.*)][@1])s <- GSLHello -> Hello
+ %(rxspencer:[GSL(.*)][gsl@1])s <- GSLHello -> gslHello
+
+ Another example could be:
+
+ %rename("%(lowercase)s",sourcefmt="%(rxspencer:[GSL_(.*)][@1])s",%$isfunction) "";
+
+ which take out the prefix "GSL_" and returns all the
+ function names in lower cases, as following:
+
+ void GSL_Hello(); -> hello();
+ void GSL_Hi(); -> hi();
+ const int GSL_MAX; -> GSL_MAX; // no change, is not a function
+
+ We use the RxSpencer as an initial test bed to
+ implemention while we decide which library will be
+ finally added to swig.
+
+ You can obtain the RxSpencer library from
+
+ http://arglist.com/regex (Unix)
+
+ or
+
+ http://gnuwin32.sourceforge.net/packages.html (Windows)
+
+ Once installed, use "man rxspencer" to get more info
+ about the regexp format, or just google rxspencer.
+
+ Since now you can enable the rxsmatch rules (see above),
+ the simple or '|' support for the match rules
+ (01/12/2006: mmatus) is disabled. Still, if you have
+ problems with the rxspencer library, you can re-enable
+ the simple 'match or' support using
+ -DSWIG_USE_SIMPLE_MATCHOR.
+
+
+01/16/2006: mmatus
+ Change the %rename predicates to use the prefix '%$', as in:
+
+ %rename("%(utitle)s",%$isfunction,%$ismember) "";
+
+ to avoid clashes with other swig macros/directives.
+
+01/14/2006: cfisavage
+ [Ruby]
+ Added support for Ruby bang! methods via a new %bang feature.
+ Bang methods end in exclamation points and indicate that the
+ object being processed will be modified in-place as
+ opposed to being copied.
+
+01/12/2006: cfisavage
+ [Ruby]
+ Updated the Ruby module to automatically convert
+ method names to lower_case_with_underscores using the
+ new %rename functionality.
+
+01/12/2006: mmatus
+ - Add aliases for 'case' encoders used with %rename/%namewarn
+
+ %(uppercase)s hello_world -> HELLO_WORLD
+ %(lowercase)s HelloWorld -> helloworld
+ %(camelcase)s hello_world -> HelloWorld
+ %(undercase)s HelloWorld -> hello_world
+
+
+01/12/2006: mmatus
+ - Add the -dump_parse_module and -dump_parse_top options,
+ which are similar to -dump_module and -dump_top, but they
+ dump the node trees just after parsing, showing only the
+ attributes visible at the parsing stage, and not the added
+ later in typemap.cxx, allocate.cxx, lang.cxx or elsewhere.
+
+ Besides debugging porpuses, these options are very useful
+ if you plan to use %rename in an "advance way", since it
+ shows only and all the node's attributes you can use
+ inside the match rules.
+
+
+01/12/2006: mmatus
+ - Add predicates to %rename, so, you don't need to
+ remember, for example, how to match a member function.
+
+ Now it is easy, for example to use the 'utitle' encoder
+ in all the member methods, you type:
+
+ %rename("%(utitle)s",%isfunction,%ismember) "";
+
+ or to ignore all the enumitems in a given class:
+
+ %rename("$ignore", %isenumitem, %classname="MyClass") "";
+
+ Available predicates are (see swig.swg):
+
+ %isenum
+ %isenumitem
+ %isaccess
+ %isclass
+ %isextend
+ %isextend
+ %isconstructor
+ %isdestructor
+ %isnamespace
+ %istemplate
+ %isconstant
+
+ %isunion
+ %isfunction
+ %isvariable
+ %isimmutable
+
+ %isstatic
+ %isfriend
+ %istypedef
+ %isvirtual
+ %isexplicit
+ %isextern
+
+ %ismember
+ %isglobal
+ %innamespace
+
+ %ispublic
+ %isprotected
+ %isprivate
+
+ %classname
+
+ These predicates correspond to specific 'match'
+ declarations, which sometimes are not as evident as the
+ predicates names.
+
+
+ - Add the or '|' operation in %rename match, for
+ example to capitalize all the constants (%constant or
+ const cdecl):
+
+ %rename("%(upper)s",match="cdecl|constant",%isimmutable) "";
+
+
+
+01/12/2006: mgossage
+ - Partial fixed of errors under C89, bug #1356574
+ (converted C++ style comments to C style)
+ - Added patches from [email protected] #1379988 and #1388343
+ missing a 'return' statement for error conditions
+ also updated the %init block bug #1356586
+
+01/10/2006: mmatus
+ - Add the 'utitle' encoder, as an example of how to add
+ your own encoder. I added the encoder method in misc.c
+ but developers can add others, the same way, inside any
+ target language.
+
+ Well, 'utitle' is the reverse of 'ctitle', ie:
+
+ %rename("%(ctitle)s") camel_case; -> CamelCase;
+ %rename("%(utitle)s") CamelCase; -> camel_case;
+
+
+01/10/2006: cfisavage
+ [Ruby]
+ Updated Ruby Exception handling. Classes that are specified in throws clauses,
+ or are marked as %exceptionclass, are now inherited from rb_eRuntimeError.
+ This allows instances of these classes to be returned to Ruby as exceptions.
+ Thus if a C++ method throws an instance of MyException, the calling Ruby
+ method will get back a MyException object. To see an example,
+ look at ruby/examples/exception_class.
+
+01/10/2006: mmatus
+
+ - Add the %catches directive, which complements the %exception
+ directive in a more automatic way. For example, if you have
+
+ int foo() throw(E1);
+
+ swig generates the proper try/catch code to dispatch E1.
+
+ But if you have:
+
+
+ int barfoo(int i) {
+ if (i == 1) {
+ throw E1();
+ } else {
+ throw E2();
+ }
+ return 0;
+ }
+
+ ie, where there is no explicit exception specification in the decl, you
+ end up doing:
+
+ %exception barfoo {
+ try {
+ $action
+ } catch(E1) { ... }
+ } catch(E2) { ... }
+ }
+
+ which is very tedious. Well, the %catches directive defines
+ the list of exceptions to catch, and from swig:
+
+ %catches(E1,E2) barfoo(int i);
+ int barfoo(int i);
+
+ is equivalent to
+
+ int barfoo(int i) throw(E1,E2);
+
+ Note, however, that the %catches list doesn't have to
+ correspond to the C++ exception specification. For example, if you
+ have:
+
+ struct E {};
+ struct E1 : E {};
+ struct E2 : E {};
+
+ int barfoo(int i) throw(E1,E2);
+
+ you can define
+
+ %catches(E) barfoo(int i);
+
+ and swig will generate an action code equivalent to
+
+ try {
+ $action
+ } catch(E &_e) {
+ <raise _e>;
+ }
+
+ Of course, you still have to satisfy the C++ restrictions,
+ and the catches list must be compatible (not the same)
+ as the original list of types in the exception specification.
+
+ Also, you can now specify that you want to catch the
+ unknown exception '...', for example:
+
+ %catches(E1,E2,...) barfoo(int);
+
+ In any case, the %catches directive will emit the
+ code to convert into the target language error/exception
+ using the 'throws' typemap.
+
+ For the '...' case to work, you need to
+ write the proper typemap in your target language. In the
+ UTL, this looks like:
+
+ %typemap(throws) (...) {
+ SWIG_exception(SWIG_RuntimeError,"unknown exception");
+ }
+
+01/09/2006: mutandiz
+ [Allegrocl]
+
+ Fixes a number of SEGVs primarily in the handling of
+ various anonymous types. Found in a pass through the
+ swig test-suite. Still more to do here, but this is a
+ good checkpoint.
+
+ Adds -cwrap and -nocwrap as an allegrocl specific
+ command-line argument. Controls generating of a C
+ wrapper file when wrapping C code. By default only a
+ lisp file is created for C code wrapping.
+
+ Doc updates for the command-line arguments and fixes as
+ pointed out on swig-devel
+
+01/05/2006: wsfulton
+ [Java] Fix unsigned long long and const unsigned long long & typemaps
+ - Bug #1398394 with patch from Dries Decock
+
+01/06/2006: mmatus
+ Add 'named' warning codes, now in addition to:
+
+ %warnfilter(813);
+
+ you can use
+
+ %warnfilter(SWIGWARN_JAVA_MULTIPLE_INHERITANCE);
+
+ just use the same code name found in Source/Include/swigwarn.h
+ plus the 'SWIG' prefix.
+
+ If a developer adds a new warning code, the Lib/swigwarn.swg file
+ will be generated when running the top level make.
+
+01/05/2006: cfisavage
+ [Ruby]
+ Reimplemented object tracking for Ruby. The new implementation works
+ by expanding the swig_class structure for Ruby by adding a trackObjects
+ field. This field can be set/unset via %trackobjects as explained
+ in the Ruby documentation. The new implementation is more robust
+ and takes less code to implement.
+
+01/05/2006: wsfulton
+ Fix for %extend and static const integral types, eg:
+
+ class Foo {
+ public:
+ %extend {
+ static const int bar = 42;
+ }
+ };
+
+12/30/2005: mmatus
+
+ - Add info for old and new debug options:
+
+ -dump_top - Print information of the entire node tree, including system nodes
+ -dump_module - Print information of the module node tree, avoiding system nodes
+ -dump_classes - Print information about the classes found in the interface
+ -dump_typedef - Print information about the types and typedefs found in the interface
+ -dump_tags - Print information about the tags found in the interface
+ -debug_typemap - Print information for debugging typemaps
+ -debug_template - Print information for debugging templates
+
+ - Add the fakeversion. If you have a project that uses
+ configure/setup.py, or another automatic building system
+ and requires a specific swig version, let say 1.3.22
+ you can use:
+
+ SWIG_FEATURES="-fakeversion 1.3.22"
+
+ or
+
+ swig -fakeversion 1.3.22
+
+ and then swig -version will report 1.3.22 instead of the
+ current version.
+
+ Typical use would be
+
+ SWIG_FEATURES="-fakeversion 1.3.22" ./configure
+
+12/30/2005: mmatus
+
+ - Add option/format support to %rename and %namewarn.
+ Now %namewarn can force renaming, for example:
+
+ %namewarn("314: import is a keyword",rename="_%s") "import";
+
+ and rename can also support format forms:
+
+ %rename("swig_%s") import;
+
+ Now, since the format is processed via swig Printf, you
+ can use encoders as follows:
+
+ %rename("%(title)s") import; -> Import
+ %rename("%(upper)s") import; -> IMPORT
+ %rename("%(lower)s") Import; -> import
+ %rename("%(ctitle)s") camel_case; -> CamelCase
+
+ This will allow us to add more encoders, as the
+ expected one for regular expressions.
+
+ - Add the above 'ctitle' encoder, which does the camel case:
+
+ camel_case -> CamelCase
+
+ - Also, while we get the regexp support, add the 'command' encoder,
+ you can use it as follows
+
+ %rename("%(command:sed -e 's/\([a-z]\)/\U\\1/' <<< )s") import;
+
+ then swig will popen the command
+
+ "sed -e 's/\([a-z]\)/\U\\1/' <<< import"
+
+ see below for anonymous renames for better examples.
+
+ - The rename directive now also allows:
+
+ - simple match: only apply the rename if a type match
+ happen, for example
+
+ %rename(%(title)s,match="enumitem") hello;
+
+ enum Hello {
+ hi, hello -> hi, Hello
+ };
+ int hello() -> hello;
+
+ - extended match: only apply the rename if the 'extended attribute' match
+ occurred, for example:
+
+ // same as simple match
+ %rename(%(title)s,match$nodeType="enumitem") hello;
+
+ enum Hello {
+ hi, hello -> hi, Hello
+ };
+
+ Note that the symbol '$' is used to define the attribute name in
+ a 'recursive' way, for example:
+
+ // match only hello in 'enum Hello'
+ %rename(%(title)s,match$parentNode$type="enum Hello") hello;
+
+ enum Hello {
+ hi, hello -> hi, Hello // match
+ };
+
+ enum Hi {
+ hi, hello -> hi, hello // no match
+ };
+
+ here, for Hello::hi, the "parentNode" is "Hello", and its "type"
+ is "enum Hello".
+
+
+ - Anonymous renames: you can use 'anonymous' rename directives, for example:
+
+ // rename all the enum items in Hello
+ %rename(%(title)s,match$parentNode$type="enum Hello") "";
+
+ enum Hello {
+ hi, hello -> Hi, Hello // match both
+ };
+
+ enum Hi {
+ hi, hello -> hi, hello // no match
+ };
+
+ // rename all the enum items
+ %rename(%(title)s,match$nodeType="enumitem") "";
+
+ // rename all the items in given command (sloooow, but...)
+ %rename(%(command:<my external cmd>)s) "";
+
+
+ Anonymous renames with commands can be very powerful, since you
+ can 'outsource' all the renaming mechanism (or part of it) to an
+ external program:
+
+ // Uppercase all (and only) the names that start with 'i'
+ %rename("%(command:awk '/^i/{print toupper($1)}' <<<)s") "";
+
+ int imported() -> IMPORTED;
+ int hello() -> hello
+
+ Note that if the 'command' encoder returns an empty string, swig
+ understands that no rename is necessary.
+
+ Also note that %rename 'passes' the matched name. For example, in
+ this case
+
+ namespace ns1 {
+ int foo();
+ }
+
+ namespace ns2 {
+ int bar();
+ }
+
+ the external program only receives "foo" and "bar". If needed,
+ however, you can request the 'fullname'
+
+ %rename("%(command:awk 'awk '/ns1::/{l=split($1,a,"::"); print toupper(a[l])}'' <<<)s",fullname=1) "";
+
+ ns1::foo -> FOO
+ ns2::bar -> bar
+
+ - Mixing encoders and matching: of course, you can do mix commands
+ and match fields, for example:
+
+ %rename("%(<my encoder for fncs>)",match="cdecl") "";
+ %rename("%(<my encoder for enums>)",match="enumitem") "";
+ %rename("%(<my encoder for enums inside a class>)",match="enumitem",
+ match$parentNode$parentNode$nodeType="class") "";
+
+ Use "swig -dump_parse_module" to see the attribute names you can use to
+ match a specific case.
+
+ - 'sourcefmt' and 'targetfmt': sometimes you need to
+ process the 'source' name before comparing, for example
+
+ %namewarn("314: empty is a keyword",sourcefmt="%(lower)s") "empty";
+
+ then if you have
+
+ int Empty(); // "Empty" is the source
+
+ you will get the keyword warning since 'Empty' will be
+ lower cased, via the sourcefmt="%(lower)s" option,
+ before been compared to the 'target' "empty".
+
+ There is an additional 'targetfmt' option to process the
+ 'target' before comparing.
+
+ - complementing 'match': you can use 'notmatch', for example
+
+ %namewarn("314: empty is a keyword",sourcefmt="%(lower)s",notmatch="namespace") "empty";
+
+ here, the name warning will be applied to all the symbols except namespaces.
+
+
+12/30/2005: mmatus
+
+ - Add initial support for gcj and Java -> <target language> mechanism.
+
+ See examples in:
+
+ Examples/python/java
+ Examples/ruby/java
+ Examples/tcl/java
+
+ to see how to use gcj+swig to export java classes into
+ python/ruby/tcl.
+
+ The idea is to put all the common code for gcj inside
+
+ Lib/gcj
+
+ and localize specific types such as jstring, as can be found
+ in
+
+ Lib/python/jstring.i
+ Lib/ruby/jstring.i
+ Lib/tcl/jstring.i
+
+ Using the UTL, this is very easy, and the perl version for
+ jstring.i will be next.
+
+
+12/29/2005: mmatus
+ - Add the copyctor feature/directive/option to enable the automatic
+ generation of copy constructors. Use as in:
+
+ %copyctor A;
+
+ struct A {
+
+ };
+
+ then this will work
+
+ a1 = A();
+ a2 = A(a1);
+
+ Also, since it is a feature, if you just type
+
+ %copyctor;
+
+ that will enable the automatic generation for all the
+ classes. It is also equivalent to
+
+ swig -copyctor -c++ ...
+
+ Notes:
+
+ 1.- The feature only works in C++ mode.
+
+ 2.- The automatic creation of the copy constructor will
+ usually produce overloading. Hence, if the target
+ language doesn't support overloading, a special name
+ will be used (A_copy).
+
+ 3.- For the overloading reasons above, it is probably not
+ a good idea to use the flag when, for example, you are
+ using keywords in Python.
+
+ 4.- The copyctor automatic mechanism follows more or less
+ the same rules as the default constructor mechanism,
+ i.e., a copy constructor will not be added if the
+ class is abstract or if there is a pertinent non-public
+ copy ctor in the class or its hierarchy.
+
+ Hence, it might be necessary for you to complete the
+ class declaration with the proper non-public copy ctor
+ to avoid a wrong constructor addition.
+
+ - Fix features/rename for templates ctor/dtor and other
+ things around while adding the copyctor mechanism.
+
+
+12/27/2005: mmatus
+ - Add the 'match' option to typemaps. Assume you have:
+
+ %typemap(in) SWIGTYPE * (int res) {..}
+ %typemap(freearg) SWIGTYPE * { if (res$argnum) ...}
+
+ then if you do
+
+ %typemap(in) A * {...}
+
+ swig will 'overload the 'in' typemap, but the 'freearg'
+ typemap will be also applied, even when this is wrong. The old
+ solutions is to write:
+
+ %typemap(in) A * {...}
+ %typemap(freeag) A * ""
+
+ overload 'freearg' with an empty definition.
+
+ The problem is, however, there is no way to know you need
+ to do that until you start getting broken C++ code, or
+ worse, broken runtime code.
+
+ The same applies to the infamous 'typecheck' typemap,
+ which always confuses people, since the first thing you do
+ is to just write the 'in' typemap.
+
+ The 'match' option solves the problem, and if instead you write:
+
+ %typemap(in) SWIGTYPE * (int res) {..}
+ %typemap(freearg,match="in") SWIGTYPE * { if (res$argnum) ...}
+ %typemap(typecheck,match="in",precedence...) SWIGTYPE * {...}
+
+ it will tell swig to apply the 'freearg/typecheck'
+ typemaps only if they 'match' the type of the 'in'
+ typemap. The same can be done with other typemaps as:
+
+ %typemap(directorout) SWIGTYPE * {...}
+ %typemap(directorfree,match="directorout") SWIGTYPE * {...}
+
+
+12/27/2005: mmatus
+ - Add the 'naturalvar' option/mode/feature to treat member
+ variables in a more natural way, ie, similar to the global
+ variable behavior.
+
+ You can use it in a global way via the command line
+
+ swig -naturalvar ...
+
+ or the module mode option
+
+ %module(naturalvar=1)
+
+ both forms make swig treat all the member variables in the
+ same way it treats global variables.
+
+ Also, you can use it in a case by case approach for
+ specific member variables using the directive form:
+
+ %naturalvar Bar::s;
+
+ Then, in the following case for example:
+
+ std::string s;
+ struct Bar {
+ std::string s;
+ };
+
+ you can do:
+
+ b = Bar()
+ b.s ="hello"
+ cvar.s = "hello"
+
+ if (b.s != cvar.s):
+ raise RuntimeError
+
+
+ This is valid for all the languages, and the
+ implementation is based on forcing the use of the
+ const SWIGTYPE& (C++)/SWIGTYPE (C) typemaps for the
+ get/set methods instead of the SWIGTYPE * typemaps.
+ Hence, for 'naturalvar' to work, each target language
+ must implement 'typemap(in/out) const Type&' properly.
+
+ The 'naturalvar' option replaces or makes workarounds such as:
+
+ %apply const std::string & { std::string *}
+
+ unnecessary.
+
+ Note1: If your interface has other kinds of workarounds to
+ deal with the old 'unnatural' way to deal with member
+ variables (returning/expecting pointers), the
+ 'naturalvar' option could break them.
+
+ Note2: the option has no effect on unnamed types, such
+ as unnamed nested unions.
+
+
+12/27/2005: mmatus
+ - Add more 'expressive' result states for the typemap
+ libraries.
+
+ In the past, for scripting languages, you would do checking something like:
+
+ if (ConvertPtr(obj,&vptr,ty,flags) != -1) {
+ // success
+ } else {
+ // error
+ }
+
+ Now the result state can carry more information,
+ including:
+
+ - Error state: like the old -1/0, but with error codes from swigerrors.swg.
+
+ int res = ConvertPtr(obj,&vptr,ty,flags);
+ if (SWIG_IsOK(res)) {
+ // success code
+ } else {
+ SWIG_Error(res); // res carries the error code
+ }
+
+ - Cast rank: when returning a simple successful
+ conversion, you just return SWIG_OK, but if you need
+ to do a 'cast', you can add the casting rank, ie:
+
+ if (PyFloat_Check(obj)) {
+ value = PyFloat_AsDouble(obj);
+ return SWIG_OK;
+ } else if (PyInt_Check(obj)) {
+ value = (double) PyInt_AsLong(obj);
+ return SWIG_AddCast(SWIG_OK);
+ }
+
+ later, the casting rank is used to properly dispatch
+ the overloaded function, for example. This of course
+ requires your language to support and use the new
+ dispatch cast/rank mechanism (Now mainly supported in
+ perl and python, and easily expandable to ruby and tcl).
+
+ - [UTL] Add support for the new 'expressive' result states.
+
+12/27/2005: mmatus
+ - Add support for the C++ implicit conversion mechanism, which
+ required some modifications in parser.y (to recognize
+ 'explicit') and overload.cxx (to replace $implicitconv as
+ needed).
+
+ Still, real support in each target language requires each
+ target language to be modified. Python provides an example,
+ see below.
+
+
+ - Add support for native C++ implicit conversions, ie, if you
+ have
+
+ %implicitconv A;
+
+ struct A {
+ int ii;
+ A() {ii = 1;}
+ A(int) {ii = 2;}
+ A(double) {ii = 3;}
+ explicit A(char *s) {ii = 4;}
+ };
+
+ int get(const A& a) {return a.ii;}
+
+ you can call:
+
+ a = A()
+ ai = A(1)
+ ad = A(1.0)
+ as = A("hello")
+
+ # old forms
+ get(a) -> 1
+ get(ai) -> 2
+ get(ad) -> 3
+ get(as) -> 4
+
+ #implicit conversions
+ get(1) -> 2
+ get(1.0) -> 3
+ get("hello") -> Error, explicit constructor
+
+ Also, as in C++, now implicit conversions are supported in
+ variable assigments, and if you have:
+
+ A ga;
+ struct Bar {
+ A a;
+ };
+
+ you can do:
+
+ cvar.ga = A(1)
+ cvar.ga = 1
+ cvar.ga = 1.0
+ cvar.ga = A("hello")
+ cvar.ga = "hello" -> error, explicit constructor
+
+ b = Bar()
+ b.a = A("hello")
+ b.a = 1
+ b.a = 1.0
+ b.a = "hello" -> error, explicit constructor
+
+ Note that the last case, assigning a member var directly,
+ also requires the 'naturalvar' option.
+
+ This support now makes the old '%implicit' macro, which
+ was found in 'implicit.i' and it was fragile in many ways,
+ obsolete, and you should use the new '%implicitconv'
+ directive instead.
+
+ Note that we follow the C++ conventions, ie, in the
+ following the implicit conversion is allowed:
+
+ int get(A a) {return a.ii;}
+ int get(const A& a) {return a.ii;}
+
+ but not in these cases:
+
+ int get(A *a) {return a->ii;}
+ int get(A& a) {return a.ii;}
+
+ Also, it works for director methods that return a by value
+ result, ie, the following will work:
+
+ virtual A get_a() = 0;
+
+ def get_a(self):
+ return 1
+
+ but not in this case:
+
+ virtual const A& get_a() = 0;
+ virtual A& get_a() = 0;
+ virtual A* get_a() = 0;
+
+ Notes:
+
+ - the implicitconv mechanism is implemented by directly
+ calling/dispatching the python constructor, triggering a
+ call to the __init__method. Hence, if you expanded the
+ __init__ method, like in:
+
+ class A:
+ def __init__(self,args):
+ <swig code>
+ <my code here>
+
+ then 'my code' will also be executed.
+
+ - Since the %implicitconv directive is a SWIG feature, if you type:
+
+ %implicitconv;
+
+ that will enable implicit conversion for all the classes in
+ your module.
+
+ But if you are worried about performance, maybe that will be
+ too much, especially if you have overloaded methods, since
+ to resolve the dispatching problem, python will efectively
+ try to call all the implicit constructors as needed.
+
+ - For the same reason, it is highly recommended that you use
+ the new 'castmode' when mixing implicit conversion and
+ overloading.
+
+ - [python] The %implicit directive is declared obsolete, and
+ you should use %implicitconv instead. If you include
+ the implicit.i file, a warning will remind you of this.
+
+ Note: Since %implicit is fragile, just replacing it by
+ %implicitconv could lead to different behavior. Hence, we
+ don't automatically switch from to the other, and the user
+ must migrate to the new %implicitconv directive manually.
+
+
+12/26/2005: wsfulton
+ [C#]
+ Modify std::vector wrappers to use std::vector::value_type as this is
+ closer to the real STL declarations for some methods, eg for push_back().
+ Fixes some compilation errors for some compilers eg when the templated
+ type is a pointer.
+
+ [Java]
+ std::vector improvements - a few more methods are wrapped and specializations are
+ no longer required. The specialize_std_vector macro is no longer needed (a
+ warning is issued if an attempt is made to use it).
+
+12/26/2005: wsfulton
+ [Java, C#]
+ Add in pointer reference typemaps. This also enables one to easily wrap
+ std::vector<T> where T is a pointer.
+
+12/24/2005: efuzzyone
+ [CFFI] The cffi module for SWIG:
+ - Fully supports C, but provides limited supports for C++, in
+ particular C++ support for templates and overloading needs to
+ be worked upon.
+
+12/23/2005: mmatus
+ [python] Add the castmode that allows the python
+ type casting to occur.
+
+ For example, if you have 'int foo(int)', now
+
+ class Ai():
+ def __init__(self,x):
+ self.x = x
+ def __int__(self):
+ return self.x
+
+ foo(1) // Ok
+ foo(1.0) // Ok
+ foo(1.3) // Error
+ ai = Ai(4)
+ foo(ai) // Ok
+
+ The castmode, which can be enabled either with the
+ '-castmode' option or the %module("castmode") option, uses
+ the new cast/rank dispatch mechanism. Hence, now if you
+ have 'int foo(int); int foo(double);', the following works
+ as expected:
+
+ foo(1) -> foo(int)
+ foo(1.0) -> foo(double)
+ ai = Ai(4)
+ foo(ai) -> foo(int)
+
+ Note1: the 'castmode' could disrupt some specialized
+ typemaps. In particular, the "implicit.i" library seems to
+ have problem with the castmode. But besides that one, the
+ entire test-suite compiles fine with and without the
+ castmode.
+
+ Note2: the cast mode can't be combined with the fast
+ dispatch mode, ie, the -fastdispatch option has no effect
+ when the cast mode is selected. The penalties, however,
+ are minimum since the cast dispatch code is already based
+ on the same fast dispatch mechanism.
+
+ See the file overload_dispatch_cast_runme.py file for
+ new cases and examples.
+
+12/22/2005: mmatus
+ Add the cast and rank mechanism to dispatch overloading
+ functions. The UTF supports it now, but for each language
+ it must be decided how to implement and/or when to use it.
+
+ [perl] Now perl uses the new cast and rank dispatch
+ mechanism, which solves all the past problems known
+ in perl, such as the old '+ 1' problem:
+
+ int foo(int);
+
+ $n = 1
+ $n = $n + 1
+ $r = foo(n)
+
+ also works:
+
+ foo(1);
+ foo("1");
+ foo(1.0);
+ foo("1.0");
+
+ but fails
+
+ foo("l");
+
+ and when overloading foo(int) and foo(double);
+
+ foo(1) -> foo(int)
+ foo(1.0) -> foo(double)
+ foo("1") -> foo(int)
+ foo("1.0") -> foo(double)
+ foo("l") -> error
+ foo($n) -> foo(int) for good perl versions
+ foo($n) -> foo(double) for old bad perl versions
+
+ when overloading foo(int), foo(char*) and foo(double):
+
+ foo(1) -> foo(int)
+ foo(1.0) -> foo(double)
+ foo("1") -> foo(char*)
+ foo("1.0") -> foo(char*)
+ foo("l") -> foo(char*)
+
+ Note: In perl the old dispatch mechanism was broken,
+ so, we don't provide an option to enable the old one
+ since, again, it was really really broken.
+
+ See 'overload_simple_runme.pl' for more cases and tests.
+
+ PS: all the old known issues are declared resolved, any
+ new "problem" that could be discovered is declared,
+ a priori, as "features" of the new dispatch mechanism
+ (until we find another solution at least).
+
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ As with the introduction of the UTF, some things could
+ now start to work as expected, and people used to deal or
+ workaround previous bugs related to the dispatch
+ mechanism, could see now a difference in perl behavior.
+
+12/21/2005: mmatus
+ - The '-nodefault' flag (pragma and feature) now generates
+ a warning, and recommends to use the explicit
+ -nodefaultctor and -nodefaultdtor options.
+
+ The reason to split the 'nodefault' behavior is that, in
+ general, ignoring the default destructor generates memory
+ leaks in the target language. Hence, is too risky just to
+ disable both the default constructor and destructor
+ at the same time.
+
+ If you need to disable the default destructor, it is
+ also recommended you use the directive form:
+
+ %nodefaultdtor MyVerySpecialClass;
+
+ for specific classes, and always avoid using the global
+ -nodefault and -nodefaultdtor options.
+
+12/21/2005: wsfulton
+ [Java, C#]
+ Fix incorrect code generation when the intermediary classname is changed
+ in the module directive from its default. For example:
+
+ %module(jniclassname="myimclassnewname") "mymodule" // Java
+ %module(imclassname="myimclassnewname") "mymodule" // C#
+
+ Add in new special variable $imclassname. See docs.
+
+12/17/2005: mmatus
+ [Python]
+ - Add the -aliasobj0/-noaliasobj0 options to use with
+ -fastunpack and/or -O and old typemaps that use 'obj0'
+ directly.
+
+ So, if you compile your code using -O and get errors about
+ the undeclared 'obj0' variable, run again using
+
+ swig -O -aliasobj0 -python ....
+
+ For new typemaps, never use 'obj0' directly, if needed,
+ use the '$self' name that will be properly expanded to
+ 'obj0' (nofastunpack) or 'swig_obj[0]' (fastunpack).
+
+ If you have no idea what I am talking about, better, that
+ means you have no typemap with this problem.
+
+
+12/14/2005: mmatus
+ [Python]
+ - Add the -fastunpack/-nofastunpack options to enable/disable
+ the use of the internal UnpackTuple method, instead of
+ calling the one from the python C API.
+
+ The option -O now also implies -fastunpack.
+
+
+12/11/2005: mmatus
+ [Python]
+ - Add the -proxydel/-noproxydel options to enable/disable
+ the generation of proxy/shadow __del__ methods, even
+ when now they are redundant, since they are empty.
+ However, old interfaces could rely on calling them.
+
+ The default behavior is to generate the __del__ methods
+ as in 1.3.27 or older swig versions.
+
+ The option -O now also implies -noproxydel.
+
+12/10/2005: mmatus
+ [UTF]
+ - Fix unnecessary calls to SWIG_TypeQuery for 'char *'
+ and 'wchar_t *', problem found by Clay Culver while
+ profiling the PyOgre project.
+
+
+ [Python]
+ - Add the -dirvtable/-nodirvtable to enable/disable
+ a pseudo virtual table used for directors, avoiding
+ the need to resolve the python method at each call.
+
+ - Add the -safecstrings/-nosafecstrings options to
+ enable/disable the use of safe conversions from PyString
+ to char *. Python requires you to never change the internal
+ buffer directly, and hence 'safectrings' warranties that
+ but returning a copy of the internal python string buffer.
+
+ The default, as in previous releases, is to return a
+ pointer to the buffer (nosafecstrings), so, it is the user's
+ responsibility to avoid its modification.
+
+ - Add the -O option to enable all the optimization options
+ at once, initially equivalent to
+
+ -modern -fastdispatch -dirvtable -nosafecstrings -fvirtual
+
+12/08/2005: mmatus
+
+ - Add the -fastdispatch option (fastdispatch feature). This
+ enables the "fast dispatch" mechanism for overloaded
+ methods provided by Salvador Fandi~no Garc'ia (#930586).
+
+ The resulting code is smaller and faster since less type
+ checking is performed. However, the error messages you
+ get when the overloading is not resolved could be
+ different from what the traditional method returns.
+
+ With the old method you always get an error such as
+
+ "No matching function for overloaded ..."
+
+ with the new method you can also get errors such as
+
+ "Type error in argument 1 of type ..."
+
+ See bug report #930586 for more details.
+
+ So, this optimization must be explicitly enabled by users.
+
+ The new mechanism can be used as:
+
+ swig -fastdispatch
+
+ or using the feature form
+
+ %feature("fastdispatch") method;
+ or
+ %fastdispatch method;
+
+
+12/06/2005: mmatus
+
+ - Several memory and speed improvements, specially for
+ templates. Now swig is up to 20 faster than before for
+ large template interfaces, such as the std_containers.i
+ and template_matrix.i files in the python test-suite.
+
+ Memory footprint is also reduced in consideration of small
+ pcs/architectures.
+
+ - add commandline options -cpperraswarn and -nocpperraswarn" to force
+ the swig preprocessor to treat the #error directive as a #warning.
+
+ the pragmas
+
+ #pragma SWIG cpperraswarn=1
+ #pragma SWIG cpperraswarn=0
+
+ are equivalent to the command line options, respectively.
+
+
+12/06/2005: mmatus
+ [Python] The generated code is now more portable, especially
+ for Windows. Following
+
+ http://www.python.org/doc/faq/windows.html
+
+ Py_None is never accessed as a structure, plus other
+ tricks mentioned there.
+
+12/06/2005: mmatus
+ [Python] Added initial support for threads based in the
+ proposal by Joseph Winston.
+
+ The user interface is as follows:
+
+ 1.- the module thread support is enable via the "threads" module
+ option, i.e.
+
+ %module("threads"=1)
+
+ 2.- Equivalent to that, is the new '-threads' swig option
+
+ swig -threads -python ...
+
+ 3.- You can partially disable thread support for a given
+ method using:
+
+ %feature("nothread") method;
+ or
+ %nothread method;
+
+ also, you can disable sections of the thread support,
+ for example
+
+ %feature("nothreadblock") method;
+ or
+ %nothreadblock method;
+
+ %feature("nothreadallow") method;
+ or
+ %nothreadallow method;
+
+ the first disables the C++/python thread protection, and the
+ second disables the python/C++ thread protection.
+
+ 4.- The current thread support is based in the PyGIL
+ extension present in python version 2.3 or later, but
+ you can provide the thread code for older versions by
+ defining the macros in pythreads.swg.
+
+ If you get a working implementation for older versions,
+ please send us a patch.
+
+ For the curious about performance, here are some numbers
+ for the profiletest.i test, which is used to check the speed
+ of the wrapped code:
+
+ nothread 9.6s (no thread code)
+ nothreadblock 12.2s (only 'allow' code)
+ nothreadallow 13.6s (only 'block' code)
+ full thread 15.5s ('allow' + 'block' code)
+
+ i.e., full thread code decreases the wrapping performance by
+ around 60%. If that is important to your application, you
+ can tune each method using the different 'nothread',
+ 'nothreadblock' or 'nothreadallow' features as
+ needed. Note that for some methods deactivating the
+ 'thread block' or 'thread allow' code is not an option,
+ so, be careful.
+
+
+11/26/2005: wsfulton
+ SWIG library files use system angle brackets everywhere for %include, eg
+ %include "std_common.i"
+ becomes
+ %include <std_common.i>
+
+11/26/2005: wsfulton
+ [Java, C#]
+ Typesafe enums and proper enums have an extra constructor so that enum item values that
+ are initialised by another enum item value can be wrapped without having to use %javaconstvalue/
+ %csconstvalue for when using %javaconst(1)/%csconst(1). Suggestion by
+ Bob Marinier/Douglas Pearson.
+ For example:
+
+ typedef enum
+ {
+ xyz,
+ last = xyz
+ } repeat;
+
+11/21/2005: mmatus
+ [ruby + python]
+
+ Fixes for directors + pointers. This is an ugly problem without an easy
+ solution. Before we identified this case as problematic:
+
+ virtual const MyClass& my_method();
+
+ but it turns out that all the cases where a pointer, array or
+ reference is returned, are problematic, even for
+ primitive types (as int, double, char*, etc).
+
+ To try to fix the issue, a new typemap was added,
+ 'directorfree', which is used to 'free' the resources
+ allocated during the 'directorout' phase. At the same
+ time, a primitive garbage collector engine was added to
+ deal with orphaned addresses, when needed.
+
+ The situation is much better now, but still it is possible to have
+ memory exhaustation if recursion is used.
+
+ So, still you need to avoid returning pointers, arrays or
+ references when using director methods.
+
+ - Added stdint.i - typemaps for latest C99 integral types found in stdint.h.
+
+11/14/2005: wsfulton
+ More types added to windows.i, eg UINT8, WORD, BYTE etc.
+ Including windows.i will also enable SWIG to parse the __declspec Microsoft
+ extension, eg __declspec(dllimport). Also other Windows calling conventions
+ such as __stdcall.
+
+11/10/2005: wsfulton
+ New library file for Windows - windows.i. This file will contain useful type
+ information for users who include windows.h. Initial support is for the
+ non ISO integral types: __int8, __int16, __int32, __int64 and unsigned versions.
+ The unsigned versions previously could not be parsed by SWIG. SF #872013.
+
+11/09/2005: wsfulton
+ [Java, C#] Portability warning for files which will overwrite each other on case
+ insensitive file systems such as FAT32/NTFS. This will occur, for example, when two
+ class names are the same barring case. The warning is issued on all platforms and
+ can be suppressed with the usual warning suppression techniques. SF bug #1084507.
+
+11/09/2005: wsfulton
+ ./configure --with-python --with-ruby --with-perl5 etc enable these languages,
+ ie the --with-xxxx options, where no path is specified, work the same as if
+ the option was not specified at all. Based on patches #1335042 #1329048 #1329047.
+
+11/09/2005: dancy
+
+ [Allegrocl]
+ Add C++ support to the Allegrocl module. Further
+ enhances the C support as well. Some of the
+ features:
+
+ - MUCH better generation of foreign types based on
+ the C/C++ types for use in defining the FFI on
+ the lisp side. We don't pass everything as a (* :void)
+ any longer.
+
+ - Uses typemaps for better control of type conversions
+ and code generation in the generated lisp and c++ wrapper
+ code.
+
+ - CLOS wrapping of pointers returned from foreign space
+ makes it easier to differentiate pointers in user code.
+ The wrapping objects can be passed directly to FF calls.
+
+ - Defun wrapping of FF calls, allowing for more lispy
+ interface. Conversion, GCing, of lisp objects to
+ foreign objects can be done in the wrapping defun via
+ the use of typemaps.
+
+ - overload dispatching implemented on the lisp side
+ using generic functions.
+
+ - Templates and synonymous types supported.
+
+11/07/2005: mmatus
+
+ [Python] Adding proper support for multi-inheritance in
+ the python side, ie, if you have two C++ wrapped class, Foo
+ and Bar, now:
+
+ class MyPythonClass(Foo,Bar):
+ ....
+
+ will properly work, even with directors, and the
+ deallocation of Foo.this and Bar.this will follow
+ correctly. Before, a class could only have one 'this'
+ instance (unlike C++), only the last base class was
+ properly deleted, or detected with directors.
+
+ Now 'self.this' can be a list, which will contain the C++
+ instance pointers for all the base classes.
+
+ Also, swig.this is responsible for deallocating the C++
+ instance(s), and the __del__ method is not emitted unless
+ the user preppend/append some code to it.
+
+ - Swig can now detect memory leaks, ie, if you still
+ don't use proxy/shadow classes, and type something like
+
+ import _example
+ f = _example.new_Foo()
+
+ and forget to call _example.delete_Foo(f), then swig will
+ tell you that there is a memory leak.
+
+ Otherwise, if you always use the proxy classes, you probably
+ you will never ever see this warning unless there is
+ something wrong inside the swig wrapping code.
+
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ If you overloaded the __del__ method, and call the base
+ one without a try block, as in
+
+ class MyClass(SwigClass):
+
+ def __del__(self):
+ <your code here>
+ SwigClass.__del__(self)
+
+ python could complain that the method SwigClass.__del__ is
+ undefined. Try to use instead:
+
+ def __del__(self):
+ <your code here>
+ try: SwigClass.__del__(self)
+ except: pass
+
+ or simply
+
+ def __del__(self):
+ <your code here>
+
+11/02/2005: mmatus
+
+ [Python] Adding more fun to STL/STD containers, now you
+ can do
+
+ %template(pyset) std::set<PyObject *>;
+ %template(pyvector) std::vector<PyObject *>;
+ %template() std::pair<PyObject *,PyObject *>;
+ %template(pyvector) std::map<PyObject *,PyObject *>;
+ ....
+
+ The same applies to std::list, std::deque, std::multiset, etc.
+
+ Then, at the python side you can do now:
+
+ # C++ std::vector as native python sequence
+ v = pyvector([1,"hello",(1,2)])
+ print v[1]
+ >> 'hello'
+ print v[2]
+ >> (1,2)
+
+ # C++ std::set as native python sequence
+ s = pyset()
+ s.insert((1,2))
+ s.insert(1)
+ s.insert("hello")
+ sum=()
+ for i in s:
+ sum +=(i,)
+ print sum
+ >>> (1, 'hello', (1, 2))
+
+ # C++ std::map as native python sequence
+ m = pymap()
+ m["foo"] = "hello"
+ m[1] = (1,2)
+ pm = {}
+ for k in m:
+ pm[k] = m[k]
+ print pm
+ >>> {1: (1, 2), 'foo': 'hello'}
+
+ ie, the STD/STL containers work as real native python
+ container, with arbitrary item types and so.
+
+ But since normal C++ containers do not properly ref/unref
+ their items, you should use the safer versions:
+
+ %template(pyset) std::set<swig::PyObject_ptr>;
+ %template(pyvector) std::vector<swig::PyObject_ptr>;
+ %template() std::pair<swig::PyObject_ptr, swig::PyObject_ptr>;
+ %template(pyvector) std::map<swig::PyObject_ptr,swig::PyObject_ptr>;
+ ....
+
+ where swig::PyObject_ptr is a PyObject * envelope class provided
+ to safely incref/decref the python object.
+
+ So, now you can use all the STL/STD containers as native
+ Python containers.
+
+ Note 1: std::map, std::set and the other 'ordered'
+ containers will properly use PyObject_Compare for sorting,
+ when needed.
+
+ Note 2: all the STL/STD containers have a limit size of
+ SIZE_MAX, ie, you can have manage containers larger than
+ INT_MAX, the python limit.
+
+
+11/02/2005: mmatus
+
+ [Python]
+ - add 'iterator()' method for all sequences and additionally
+ 'key_iterator()' for maps.
+
+ 'iterator()' will always return the native C++ iterator.
+ Additionally, in maps, 'key_iterator()' will return a python
+ iterator using only the map keys.
+
+ In general the sequence method __iter__ will call
+ 'iterator()', returning the native C++ iterator, but in
+ maps it will call 'key_iterator()', maintaining
+ backward compatibility.
+
+ Hence, for std::maps, you can play then with the native
+ C++ iterator, which value is a (key, value) pair, by
+ calling map.iterator(), as with map.begin(), map.end(), etc.
+
+ The difference is that map.iterator() returns a safe
+ 'closed' iterator, while map.begin() and map.end() are
+ 'open' iterators.
+
+ A 'closed' iterator knows the begin and the end of the
+ sequence, and it never can seg. fault. An 'open'
+ iterator, as in C++, can seg. fault at the C++ side.
+
+ # a closed iterator is safe in the following example.
+ # the next() method will throw a StopIteration
+ # exception as needed
+
+ i = seq.iterator()
+ try:
+ while True:
+ sum += i.next()
+ except: pass
+
+ # an open iterator always need to be checked,
+ # or it will crash at the C++ side
+
+ current = seq.begin()
+ end = seq.end()
+ while (current != end):
+ sum += current.next()
+
+
+ [Python]
+ - Finally, when we call
+
+ f = Foo()
+
+ the construction is 'one-way'. Before construction was done
+ something like
+
+ Foo() (python) -> _new_Foo() (C++)
+ new_Foo() (C++) -> FooPtr() (python)
+ FooPtr() (python) -> Foo() (python)
+
+ and returning a pointer was done like
+
+ NewPointerObj() (C++) -> FooPtr() (python)
+ FooPtr(python) -> Foo() (python)
+
+
+ ie, we when going back and forward between the C++ and
+ python side.
+
+ Now since there is no FooPtr the construction process is
+
+ Foo() (python) -> _new_Foo() (C++)
+ _new_Foo() (C++) -> NewPointerObj() (C++) (no shadow class)
+
+ and returning a pointer is done
+
+ NewPointerObj() (C++) (with shadow class) -> NewInstaceObj() (C++)
+
+ where NewInstanceObj creates a new instance without
+ calling __init__ and it doesn't go 'back' to python, is
+ 'pure' C API.
+
+ - With this change, and the other ones in the
+ PySwigObject type, which now carries the thisown and
+ swig_type_info pointer, the generated code should be as
+ fast as boost::Python and/or the other python wrappers
+ based in pure Python/C API calls.
+
+ As a reference, the profiletest_runme.py example, which
+ does a simple call function many times, such as this code:
+
+ import profiletest
+
+ a = profiletest.A()
+ b = profiletest.B()
+ for i in range(0,1000000)
+ a = b.fn(a)
+
+
+ where fn is defined as 'A* B::fn(A *a) {return a;}',
+ produces the following times
+
+ nomodern modern
+ swig-1.3.26 19.70s 5.98s
+ swig-CVS 0.99s 0.98s
+
+
+ Clearly, there is a large improvement for the python
+ 'nomodern' mode. Still, the 'modern' mode is around
+ 6 times faster than before. For the same test, but
+ using the non-shadow version of the module, we get
+
+ _profiletest (non-shadow)
+ swig-1.3.26 0.80s
+ swig-CVS 0.60s
+
+ Hence, now for practical purposes, the proxy overhead
+ is insignificant.
+
+ Note that the performance numbers we are showing is for
+ a simple module (two types) and a simple function (one
+ argument). For real situations, for modules with many
+ more types and/or functions with many more parameters,
+ you will see even better results.
+
+
+10/31/2005: mmatus
+ [Python]
+
+ - Finally, no more ClassPtr proxy classes. You will see
+ only a clean Class proxy class in the .py file.
+
+ - No more 'real' thisown attribute either, the PySwigObject now
+ carries the ownership info.
+
+ You can also do something like
+
+ print self.this.own()
+ >>> True
+
+ self.this.disown()
+ self.this.own(0)
+ print self.this.own()
+ >>> False
+
+ self.this.acquire()
+ self.this.own(1)
+ print self.this.own()
+ >>> True
+
+ Still the old way,
+
+ print self.thisown
+ >>> True
+
+ self.thisown = 0
+ print self.thisown
+ >>> False
+
+ self.thisown = 1
+ print self.thisown
+ >>> True
+
+ is supported, and python dispatches the proper method
+ calls as needed.
+
+
+ - Support for iterators in STL/STD containers, for example, if you have
+
+ %template<set_string> std::set<std::string>;
+
+ you can use the C++ iterators as:
+
+ s = set_string()
+
+ s.append("c")
+ s.append("a")
+ s.append("b")
+
+ b = s.begin()
+ e = s.end()
+ sum = ""
+ while (b != e):
+ sum += b.next()
+ print sum
+
+ >>> "abc"
+
+ advance the iterator as in C++
+
+ current = s.begin()
+ current += 1
+ print current.value()
+ >>> "b"
+
+ now using the reverse operators
+
+ b = s.rbegin()
+ e = s.rend()
+ sum = ""
+ while (b != e):
+ sum += b.next()
+ print sum
+
+ >>> "cba"
+
+ or the 'previous' method
+
+ b = s.begin()
+ e = s.end()
+ sum = ""
+ while (b != e):
+ sum += e.previous()
+ print sum
+
+ >>> "cba"
+
+ or just as in a python fashion
+
+ for i in s:
+ sum += i
+
+ Note 1: Iterators in C++ are very powerful, but
+ dangerous too. And in python you can shoot yourself in the foot
+ just like in C++, so, be careful.
+
+ Note 2: the iterators are 'light', ie, they do not
+ convert sequence elements until you request to do so, via
+ next(), value() or previous(). If you just increment/decrement one
+ no conversion is performed, for example:
+
+
+ b = s.begin()
+ b += 1
+ b.incr()
+ b.incr(2)
+ b.decr(2)
+ b.decr()
+ b -= 1
+
+ only the iterator is modified, and not value wrapper
+ is generated. Other typical C++ operations are also
+ available, such as:
+
+ print s.end() - s.begin()
+ >>> 3
+ f = s.begin() + 1
+ print f.value()
+ >>> "b"
+ l = s.end() - 1
+ print l.value()
+ >>> "c"
+
+ etc. Of course, the 'find', 'insert', 'erase', and
+ so on methods also supports iterators now, ie:
+
+ i = s.begin()
+ i += 1
+ s.erase(i)
+ for i in s:
+ sum += i
+ print sum
+ >>> "ac"
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ There is no more 'thisown' attribute. If you use it, python
+ will translate the following code as follows:
+
+ if (self.thisown): ==> if (self.this.own()):
+ self.thisown = 1 ==> self.this.own(1)
+ self.thisown = 0 ==> self.this.own(0)
+
+ Still, maybe in some unusual cases the translation will not be
+ 100% correct, so if you have a problem, please report it
+ and/or use the new 'self.this.own()' accessor.
+
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ There is no more ClassPtr classes in the python code. Hence,
+ if in the past you needed to resort to some kind of trickery
+ with them, or overcome their presence, it is no longer
+ required, but the extra code you added could now break
+ things.
+
+ If needed, you can use the option -classptr, i.e.,
+
+ swig -classptr -python ...
+
+ to generate the old ClassPtr classes.
+
+
+10/30/2005: mkoeppe
+ [Guile] Make declared and defined linkage of SWIG_init consistent.
+ Reported by Steven G. Johnson (SF patch 1315498).
+
+10/26/2005: mmatus
+
+ - Added the attribute.i file to the global library director.
+ Now it can be used from other languages that do not use
+ the unified typemap library as well.
+
+ So, if you have something like:
+
+ %include attribute.i
+
+ %attribute(A, int, a, get_a, set_a);
+
+ struct A
+ {
+ int get_a() const;
+ void set_a(int aa);
+ };
+
+ %attribute_ref(B, int, c);
+
+ struct B
+ {
+ int& c();
+ };
+
+ then in the target language the 'A.a' and 'B.c' attributes will
+ be visible, ie, you can access them as plain variables:
+
+ f = A()
+ f.a = 3
+ g = B()
+ g.c = 3
+
+ h = f.a + g.c
+
+ and the proper get/set methods will be dispatched. See
+ attribute.i for more info.
+
+ - More cleanups around and adding more test-cases. The
+ DISOWN typemap now is tested and working in all the
+ languages that use the unified typemap library, ie, tcl,
+ ruby, perl and python.
+
+
+10/25/2005: mmatus
+
+ - Perl, complete the DISOWN typemap.
+
+ - added the attribute.i file to the unified typemap
+ library (before was only usable from python).
+
+ - unify the names for the setter and getter methods in
+ perl,tcl,ruby and python, so, the attribute.i library
+ can work across them.
+
+ - see the li_attribute.i test-case or the library file
+
+ Lib/typemaps/attribute.swg
+
+ for more info about how to use it.
+
+
+
+
+10/24/2005: mmatus
+
+ - Perl now uses the unified typemap library.
+
+ - Changes in ruby to use the $track option in typemaps.
+
+ - Changes in the unified typemap library to follow the
+ convention that all macros that are not used in the
+ C/C++ side starts with %, such as
+
+ %delete
+ %new_array
+
+ etc.
+
+ - Documenting fragments, see fragments.swg.
+
+ - Cleaner way to use the unified typemap library, include
+ just <typemaps/swigtypes.swg>.
+
+ Check some of the supported languages: perl, tcl, ruby,
+ python.
+
+ Always start with the head file, such as
+
+ python/python.swg
+ tcl/tcl8.swg
+ ruby/ruby.swg
+ perl5/perl5.swg
+
+ and the principal file that invokes the unified library, such as
+
+ python/pytypemaps.swg
+ tcl/tcltypemaps.swg
+ ruby/rubytypemaps.swg
+ perl/perltypemaps.swg
+
+ The file that provide the specialization for each
+ language are the one that provides the basic types:
+
+ python/pyprimtypes.swg
+ ruby/rubyprimtypes.swg
+ tcl/tclprimtypes.swg
+ perl5/perlprimtypes.swg
+
+ and the string manipulation:
+
+ python/pystrings.swg
+ ruby/rubystrings.swg
+ tcl/tclstrings.swg
+ perl5/perlstrings.swg
+
+
+ The rest of the files, such as carray.i, are mostly one
+ line files that include the proper typemap library
+ version.
+
+ *** POTENTIAL INCOMPATIBILITY in Perl ***
+
+ Some missing/wrong typemaps could start working properly,
+ and change the old expected behavior in Perl.
+
+10/23/2005: wuzzeb
+ Chicken:
+ + pointers to member functions finally work properly
+ + add test of member function pointers to cpp_basic.i
+
+10/20/2005: dancy
+ [allegrocl] Added C++ support. Large update, many changes. See
+ newly added Allegro Common Lisp section in lisp.html
+
+10/20/2005: mmatus
+ Ruby, Tcl, Python:
+
+ - Uniform way to fail (label fail:), now finally
+ SWIG_exception works across the three languages and all
+ the typemaps.
+
+ - Add proper cleanup code to ruby
+
+ - More valgrind fixes
+
+ - Simplify the inline use, it seems a small interface of
+ 20,000 lines (plus many many templates) can break
+ gcc -O3 easily.
+
+ - Finalize the typemaps library. All the old *.i files
+ (carray.i, cpointer.i, exception.i) had been implemented
+ in the new typemaps library.
+
+
+10/19/2005: wuzzeb
+ Update the Runtime Typemap documentation in Typemaps.html
+
+10/18/2005: wuzzeb
+ Chicken:
+ - Correctly handle %ignored classes
+ - Correctly convert long, long long, unsigned long, etc
+ to chicken primitives. (Thanks to Felix Winkelmann)
+ - Using argout parameters when the return value was a
+ wrapped pointer caused a memory corruption. The chicken
+ garbage collector moved a pointer out from under us.
+ This is now fixed by running all the proxy creation
+ functions as continuations after the wrapper function
+ returns. As part of this, we no longer need the
+ chickenfastproxy flag on output typemaps.
+ - using -proxy and -nocollection together works now
+ Before, it was not exporting the destructor in the proxy
+ wrapper.
+
+10/18/2005: mmatus
+
+ Added the Unified Typemap Library (UTL). It unifies the typemaps for
+
+ python, ruby, tcl
+
+ and in the process, fixes several problems in each of the three
+ languages to work in a "canonical" way now established in
+ the typemap library
+
+ SWIG/Lib/typempas
+
+ The current status of the unification is that everything
+ compiles and runs inside the test-suite and examples
+ directories. And for the first time we have three
+ languages than pass the primitive_types.i case.
+
+ Also, we have a uniform way to treat the errors, for example
+ if you do something like
+
+ >>> from primitive_types import *
+ >>> print val_uchar(10)
+ 10
+ >>> print val_uchar(1000)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in ?
+ OverflowError: in argument 1 of type 'unsigned char'
+
+ you get the same exception in all the three languages.
+
+ And well, many more good things will come from this
+ unification, for example, proper support of the STL/STD classes
+ for all the languages, and hopefully, we can keep
+ adding other languages.
+
+ The hardest part, writing a common typemap library
+ that suites the three different languages, is done,
+ and adding another language should now be easy.
+
+ Still the global unification is not complete, the STL/STD
+ part is next, and probably as well as adding one or two more
+ languages.
+
+ If you are curious, look at the python, ruby and/or tcl
+ directories to see what is needed to support the new
+ common typemaps library. Still, the final way to
+ integrate a new language could change as we move to
+ integrate the STD/STL.
+
+ *** POTENTIAL INCOMPATIBILITY in Ruby/Tcl ***
+
+ Some missing/wrong typemaps could start working properly,
+ and change the old behavior, specially in ruby and tcl.
+
+Version 1.3.27 (October 15, 2005)
+=================================
+
+10/15/2005: wsfulton
+ [Java] Fix for typesafe enum wrapping so that it is possible to
+ overload a method with 2 different enum types.
+
+10/15/2005: wsfulton
+ Fix for %feature("immutable","0") attempting to generate setters
+ for constants.
+
+ Restored %immutable and %makedefault to clear the feature as it
+ behaved in SWIG-1.3.25 and earlier.
+
+10/14/2005: mmatus
+ Fix bug in anonymous typedef structures which was leading to
+ strange behaviour.
+
+10/13/2005: mmatus
+ Several minor changes:
+
+ - Improve the wchar_t type support
+ - Add a warning for when you define the 'in' typemap but
+ you don't define the 'typecheck' one. Very common mistake.
+ - Add proper default rule for function pointers, now you
+ can define a typemap such as:
+
+ %typemap(in) SWIGTYPE ((*)(ANY)) {...}
+
+ That will apply to all the pointer to functions. The
+ rule in C++ also apply to the function 'reference', ie,
+ in both cases
+
+ typedef int (*fptr)(int a);
+ typedef int (func)(int a);
+
+ This was needed since it seems to be 'illegal' in C++ to
+ do something like:
+
+ void *ptr = static_cast<void *>(fptr);
+
+ and probably, as for member functions, it is not
+ warrantied that the pointer sizes will match.
+
+ - Add the #error/#warning directives to swig's cpp.
+
+ - Add the noblock option for typemaps, which is used as
+ follows: supposed you a typemap, like this
+
+
+ %typemap(in,noblock=1) Hello {
+ ....
+ }
+
+ then the typemap will be inserted without the block
+ imposed by the brackets, similar to
+
+ %typemap(in) Hello "..."
+
+ So, why you don't just use the quote style?, because:
+
+ 1.- The quote style doesn't get preprocessed, for example
+
+ %typemap(in) Hello "$1= SWIG_macro($1);"
+
+ here, SWIG_macro doesn't get expanded
+
+ 2.- Inside a quote typemap, you have to use
+ quotes carefully
+
+ %typemap(in) Hello "$1 = \"hello\" "
+
+ 3.- You can't make emacs and/or other editors
+ to indent inside a string!.
+
+
+ So, why do you want to remove the block?, because an extra
+ block when not needed (no local variables in it):
+
+ 1.- makes the code harder to read
+ 2.- makes the code larger
+ 3.- or in short, for the same reason we have the quote style.
+
+Version 1.3.26 (October 9, 2005)
+================================
+
+10/08/2005: wsfulton
+ [Php] Added 'throws' typemaps.
+
+10/08/2005: wsfulton
+ Fixes for languages that don't support multiple inheritance. The
+ first non-ignored class in the public base class list is used for inheritance.
+ by the proxy class. Previously, if the first class in the list was ignored, then
+ the proxy class wouldn't have any base classes.
+
+10/07/2005: mmatus
+ Update more features to follow new convention, including:
+
+ callback
+ ref/unref
+ except
+
+ All of them use not only the feature as a flag, but also
+ as code value. To deal with those features, we use now
+ GetFlagAttr, which is similar to GetFlag, but instead or
+ returning 1 or 0, it returns the attr value, if happens
+ to be different of "0" of course.
+
+ Now there are also more uniform directive names for the
+ ones based in features, for example, for the old
+ %newobject directive now we have three directives defined:
+
+
+ #define %newobject %feature("new")
+ #define %nonewobject %feature("new","0")
+ #define %clearnewobject %feature("new","")
+
+ and so on for all the other feature directives.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+09/30/2005: wsfulton
+ Subtle change to some features. Previously it was not possible to disable many
+ features once they had been enabled. This was for most features that behave as
+ flags. These features now work as follows:
+
+ %feature("name") // enables the feature
+ %feature("name", "1") // enables the feature
+ %feature("name", "0") // disables the feature
+ %feature("name", "") // clears the feature
+
+ In fact any non-empty value other than "0" will enable the feature (like C boolean logic).
+ Previously "1", "0" or any other non-empty value would enable the feature and it would
+ only be possible to disable the feature by clearing it (assuming there was no global enable).
+
+ The following features are affected:
+
+ allowexcept
+ compactdefaultargs
+ classic (Python)
+ cs:const (C#)
+ director
+ exceptionclass (Python)
+ ignore
+ immutable
+ java:const (Java)
+ java:downcast (Java)
+ kwargs
+ modern (Python)
+ new
+ noautodoc (Python)
+ nodefault
+ nodirector
+ noref
+ notabstract
+ nounref
+ novaluewrapper
+ python:maybecall (Python)
+ python:nondynamic (Python)
+ modula3:multiretval (Modula3)
+ predicate (Ruby)
+ trackobjects (Ruby)
+ valuewrapper
+
+ It is now possible, for example to ignore all methods/classes in a header file, except for a
+ few targetted methods, for example:
+
+ %feature("ignore"); // ignore all methods/classes
+ %feature("ignore","0") some_function(int, double); // do not ignore this function
+ %feature("ignore","0") SomeClass; // do not ignore this Class
+ %feature("ignore","0") SomeClass::method; // do not ignore this method
+ %include "bigheader.h"
+
+ Removed %pythondynamic - it never worked properly. Use %pythonnondynamic instead.
+ Removed %feature("nokwargs") - it wasn't fully implemented - use %feature("kwargs","0") instead.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+09/25/2005: mkoeppe
+ [Guile] Add "throws" typemaps.
+
+09/24/2005: cfisavage
+ [Ruby] Adds new %trackobjects functionality that maps C++ objects to
+ Ruby objects. This functionality makes it much easier to implement
+ mark functions for the garbage collector. For more information
+ refer to the update documentation and examples.
+
+09/20/2005: wsfulton
+ [Perl] Patch 1116431 from Josh Cherry. Fixes non member functions inadvertently
+ being called instead of member functions.
+
+09/20/2005: wsfulton
+ [Lua] Patch from Mark Gossage to add support for Lua-5.1, std::string,
+ std::vector, std::exception and documentation.
+
+09/14/2005: mmatus
+ [Python] Add -nocppcast. Now the default behavior is to
+ always use the cppcast operators. Before that was the case
+ only when you used the -cppcast option.
+
+ If this seems to break your code... your welcome!, it
+ means it was broken before, and you never notice.
+
+ If you thing the error is due to one of the SWIG typemaps,
+ send us an example.
+
+ Use -nocppcast only with very old C++ compilers that
+ do not support the cppcast operations.
+
+ So, here applies:
+
+ This change doesn't break compatibility, it was broken before.
+
+09/13/2005: wsfulton
+ [Java] Fix for director methods when a class is passed by value as a
+ parameter.
+
+09/11/2005: mmatus
+ Adding the module option to the %import directive. Now you
+ can use it as
+
+ %import(module="BigModule") foo.i
+
+ where subfile could (or not) define the module name via
+ the %module directive. The module option take precedence
+ and it has the same effects than having the directive
+
+ %module BigModule
+
+ inside the imported file foo.i.
+
+ You can use the option in mainly two cases:
+
+ 1.- You used the -module option when you generated the
+ module to be imported, and hence the module name in
+ the imported %module directive is not really useful.
+
+ 2.- The module you want to import is very large, and it
+ has several .i/.h files. Then, if you just one to
+ import a class or so from the module, says 'foo', and
+ not the entire module via importing the main
+ BigModule.i file, then you just do:
+
+ %import(module="BigModule") foo.h
+
+ or
+
+ %import(module="BigModule") foo.i
+
+ where foo.i contains the 'foo' declaration and maybe a
+ couple of extra %include directives, as needed.
+
+
+09/11/2005: mmatus
+ Fix bug #1282637, about the -module option not having effect
+ in places where it was needed.
+
+09/11/2005: wsfulton
+ When wrapping variables, ensure that none of the typemaps used for the
+ set wrappers are used when generating the get wrappers. I doubt this was a
+ problem for any languages except for the recently introduced null attribute
+ in the out typemap (C# only).
+
+09/08/2005: wsfulton
+ More descriptive error messages when files fail to open.
+
+09/06/2005: mmatus
+
+ Allow a %define a macro inside another %define macro, for example
+
+ %define hello(name, Type)
+ %define name ## a(Type)
+ %typemap(in) Type "hello;"
+ %enddef
+ %enddef
+
+ To learn how to use this new features in your own typemaps library, see
+ python/cstring.i, python/cwstring.i and python/cwstrbase.i.
+
+ [Python] Normalize the cstring.i implementation to use fragments, and add
+ cwstring.i, which implements the same typemaps but for wchar_t strings.
+
+ [Python] Bug fixed: 1247477, 1245591, 1249878 and others.
+
+08/18/2005: wsfulton
+ [Ruby] Implement support for SWIGTYPE* DISOWN typemap (like in Python) for
+ better control of memory management, eg when adding an object created in Ruby
+ to a C++ container. Patch #1261692 from Charlie Savage.
+
+08/18/2005: wsfulton
+ [Tcl] 64 bit platform fixes for the varargs handling in SWIG_GetArgs. This is an
+ improved fix for bug #1011604 as suggested by Jeremy Lin.
+
+08/18/2005: wsfulton
+ [Tcl] Bug #1240469 - %newobject support for Tcl. Patch from Bob Marinier.
+
+08/16/2005: wsfulton
+ [Perl] Bug #1254494 - Fix for global namespace pollution by perl header files
+ (bool define) prevented STL headers from being used on some systems, eg
+ Windows with Visual Studio.
+
+08/16/2005: wsfulton
+ [Java] Bug #1240937 - Redefinition of __int64 typedef for Intel compilers.
+
+08/15/2005: wsfulton
+ [Xml] Bug #1251832 - C++ template may generate invalid XML file
+
+08/15/2005: wsfulton
+ [Lua] Support added for Lua. Patch #1242772 from Mark Gossage.
+ It supports most C/C++ features (functions, struct, classes, arrays, pointers,
+ exceptions), as well as lots of documentation and a few test cases & examples.
+
+08/14/2005: wsfulton
+ [Xml] Fix incorrect xml escaping in base class name when base class is a template.
+
+08/13/2005: efuzzyone
+ [CLISP] Added support for handling enums. Does not adds the return type declaration
+ to the function definition, if a function returns void.
+
+08/09/2005: mkoeppe
+ New language module, Common Lisp with UFFI, from Utz-Uwe Haus.
+
+08/09/2005: mkoeppe
+ Fix the Lisp s-expression output module; it no longer complains about "unknown targets".
+
+07/27/2005: wsfulton
+ Modifications to STL wrappers so that it is possible for a user's %exception directive
+ to be applied to the STL wrapper methods. Previously the following global %exception
+ directive would not be used on the wrapper methods:
+
+ %exception {
+ try {
+ $action
+ } catch (...) {
+ // handle uncaught exceptions
+ }
+ }
+
+ This has been implemented by replacing %exception directives for specific STL wrapper
+ methods with an exception specification declared on the wrapper methods. throws typemaps
+ are now supplied for handling the STL exception specification. These can also be easily
+ overridden, for example the std::out_of_range exception, which is used a lot in the STL
+ wrappers, can be customised easily:
+
+ %include "std_vector.i"
+ %typemap(throws) std::out_of_range {
+ // custom exception handler
+ }
+ %template(VectInt) std::vector<int>;
+
+07/22/2005: efuzzyone
+ [CLISP] The clisp module for SWIG:
+ - It can only handle C, clisp currently does not supports ffi bindings to C++.
+ - It has two options, (a) -extern-all this will generate wrappers for all functions
+ and variablestions, (b) -generate-typedef this will generate wrappers "def-c-type"
+ wrappers for typedefs
+ - Can handle pointers to functions, complex types such as n-dimensional arrays of
+ pointers of depth d
+ - Generates wrappers for constants as well as variables
+ - Correctly distinguishes between the declaration of variables in structures and functions
+ - Creates a defpackage "declaration" with the module name as the package name, the created
+ package exports both functions and variables
+ - tries to guess when should a pointer variable be declared as c-ptr or c-pointer
+
+07/22/2005: wsfulton
+ [C#] Changes to support C# structs returned by value. The changes required are:
+ - Using an optional 'null' attribute in the out typemap. If this attribute is specified,
+ then it is used for the $null special variable substitution.
+ - The ctype used in the C/C++ wrappers is no longer initialised to 0 on declaration.
+ Both of these changes fix the situations where an attempt was made to assign 0 to the
+ returned struct. Marshalling structs as value types still requires user defined typemaps.
+ See documentation for an example.
+
+07/22/2005: wsfulton
+ [C#, Java] Fix SWIG_exception usage to work with compilers that don't support empty macro
+ arguments. Unfortunately this fix will stop usage of SWIG_exception being used within typemaps
+ that use "" or %{ %} delimiters, but continues to work with typemaps using {} delimiters.
+ Please use the SWIG_CSharpSetPendingExceptionArgument or SWIG_JavaThrowException methods instead
+ as SWIG_exception is really intended as a platform independent macro for the SWIG library writers.
+
+07/16/2005: mkoeppe
+ [Allegro CL] Use specific foreign types rather than (* :void).
+ Use *swig-identifier-converter*.
+
+06/27/2005: wsfulton
+ Functions declared as 'extern' no longer have an additional function declaration added to the
+ wrapper files. There are some cases where SWIG does not get this right, eg bug #1205859 (extern
+ functions with default arguments declared in a namespace). Also SWIG cannot get non-standard
+ calling conventions correct, eg Windows calling conventions are usually handled like this:
+
+ %{
+ #define DLLIMPORT __declspec(dllimport)
+ #define STDCALL __stdcall
+ %}
+ #define DLLIMPORT
+ #define STDCALL
+ %inline %{
+ DLLIMPORT extern STDCALL void function(int);
+ %}
+
+ SWIG incorrectly generates:
+
+ extern void function(int);
+
+ To which there is no solution as SWIG doesn't handle non-standard calling conventions. The extra
+ 'extern' function that SWIG generates is superfluous unless a user has forgotten to add the function
+ declaration into the wrappers.
+
+ The -noextern commandline argument is now redundant and a new commandline argument -addextern can
+ be used to obtain the original behaviour. This shouldn't be necessary unless the header file
+ containing the function declaration was inadvertently not added to the wrappers. To fix this
+ add the function declaration into your wrappers, For example, replace:
+
+ extern void foo(int);
+
+ with:
+
+ %inline %{
+ extern void foo(int);
+ %}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+06/22/2005: wsfulton
+ [C#, Java, Modula3, Ocaml]
+ The intermediary function names have been changed when wrapping variables to
+ match the other language modules so that %extend for a member variable works
+ uniformly across all language modules, eg:
+
+ %extend ExtendMe {
+ Var;
+ };
+
+ %{
+ void ExtendMe_Var_set(ExtendMe *, double) {...}
+ double ExtendMe_Var_get(ExtendMe *) {...}
+ %}
+
+ The methods implementing the get/set used to be:
+
+ %{
+ void set_ExtendMe_Var(ExtendMe *, double) {...}
+ double get_ExtendMe_Var(ExtendMe *) {...}
+ %}
+
+ This also changes the name of variable wrapper functions when using -noproxy.
+ The original names can be generated with the -oldvarnames commandline option.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+Version 1.3.25 (June 11, 2005)
+==============================
+
+06/11/2006: mkoeppe
+ [Guile] Fix handling of anonymous-enum variables.
+
+06/10/2005: mkoeppe
+ [Guile] Fix for function arguments that are passed by
+ copy-of-value. Fix for global "const char *" variables.
+ Fix testcases arrays_dimensionless, arrays_global.
+
+06/08/2005: wsfulton
+ Fix for when a base class defines a symbol as a member variable and a derived class defines
+ the same symbol as a member method.
+
+06/08/2005: wsfulton
+ [C#] More fixes for virtual/new/override modifiers - when a method has protected access
+ in base and public access in derived class.
+
+06/02/2005: wsfulton
+ Fix #1066363 - Follow convention of release tarball name matching directory name.
+
+06/02/2005: wsfulton
+ [C#, Java] Fix #1211353 - typesafe enums (and Java proper enums) wrappers when enum value
+ is negative.
+
+05/27/2005: wsfulton
+ Modernised and tidied up Windows macros --> SWIGEXPORT, SWIGSTDCALL. They can be overridden
+ by users via -D compiler directives if need be.
+
+05/26/2005: wsfulton
+ %csmethodmodifiers can be applied to variables as well as methods now.
+
+ In addition to the default 'public' modifier that SWIG generates, %csmethodmodifiers will also
+ replace the virtual/new/override modifiers that SWIG thinks is appropriate. This feature is
+ useful for some obscure cases where SWIG might get the modifiers incorrect, for example
+ with multiple inheritance and overriding a method in the base class.
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+05/25/2005: wsfulton
+ Added missing constructors to std::pair wrappers (std_pair.i) for all languages.
+
+05/25/2005: wsfulton
+ [C#] Added std::pair wrappers in std_pair.i
+
+05/25/2005: wsfulton
+ [C#] The C# 'new' and 'override' modifiers will be generated when a C++ class inherits methods
+ via a C++ 'using' declaration.
+
+05/25/2005: wsfulton
+ Fix for exception specifications previously being ignored in classes that inherited methods
+ from 'using' declarations, eg calls to Derived::bar below will convert C++ exceptions into
+ a target language exception/error, like it always has done for Base::Bar.
+
+ class Base {
+ virtual bar() throw (std::string);
+ };
+ class Derived : public Base {
+ using Base::bar;
+ };
+
+05/23/2005: wsfulton
+ Fixes for detecting virtual methods in %extend for the -fvirtual option and C# override and new
+ method modifiers.
+
+05/23/2005: wsfulton
+ [C#] The 'new' modifier is now generated on the proxy method when a method in a derived
+ class is not polymorphic and the same method exists in the derived class (ie it hides
+ the base class' non-virtual method).
+
+05/23/2005: wsfulton
+ [Java, C#] Fixes to detection of covariant return types - when the class hierarchy is more
+ than 2 classes deep.
+
+05/21/2005: wsfulton
+ [Java] std::wstring typemaps moved from std_string.i to std_wstring.i
+
+05/21/2005: wsfulton
+ Fix for crash in DohStrstr, bug #1190921
+
+05/21/2005: wsfulton
+ [TCL] Fix for methods with similar names when showing list of names on error - bug #1191828.
+ Patch from Jeroen Dobbelaere.
+
+05/21/2005: wsfulton
+ [TCL] long long overloading fix - bug #1191835, patch from Jeroen Dobbelaere.
+
+05/21/2005: wsfulton
+ Fix bug #1196755 to remove debug from swigtcl8.swg.
+
+05/19/2005: wsfulton
+ [C# and -fvirtual option] Fix for the override key not being generated in the derived class when a
+ virtual method's return type was a typedef in either the base or derived class. Also ensures the
+ method is eliminated when using the -fvirtual option. For example, Derived.method now has the C#
+ override keyword generated:
+
+ typedef int* IntegerPtr;
+
+ struct Base {
+ virtual IntegerPtr method();
+ };
+
+ struct Derived : Base {
+ int * method() const;
+ };
+
+ [C#] Fix for the override key being incorrectly generated for virtual methods when a base class
+ is ignored with %ignore.
+
+05/13/2005: wsfulton
+ [Java] Fixes to remove "dereferencing type-punned pointer will break strict-aliasing rules"
+ warnings in C wrappers when compiling C code with 'gcc -Wall -fstrict-aliasing'. Patch from
+ Michael Cahill. This modifies many of the casts slightly, for example
+ arg1 = *(DB_ENV **)&jarg1;
+ to
+ arg1 = *(DB_ENV **)(void *)&jarg1;
+
+05/12/2005: wsfulton
+ [C#] Support for C# attributes. C# attributes can be generated:
+ 1) On a C/C++ type basis by specifying an inattributes and/or outattributes typemap attribute
+ in the imtype or cstype typemaps (for C# return type or C# parameter type attributes).
+ 2) On a wrapped method or variable by specifying a csattributes feature (%feature).
+ 3) On a wrapped proxy class or enum by specifying a csattributes typemap.
+
+ Examples are in the C# documentation (CSharp.html).
+
+04/29/2005: wsfulton
+ New configure option to turn off the default maximum compiler warning as
+ they couldn't be removed even when overriding CFLAGS and CXXFLAGS with configure
+ (./configure CFLAGS= CXXFLAGS=). To turn the maximum warnings off, run:
+
+ ./configure --without-maximum-compile-warnings
+
+04/28/2005: wsfulton
+ Patch from Scott Michel which reworks the Java constructor and finalize/destructor typemaps,
+ for directors to reduce the number of overall Java typemaps. Added the director_take and
+ director_release typemaps to emulate other modules' __disown__ functionality.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA DIRECTORS ***
+
+04/28/2005: wsfulton
+ [C#] Fixed problems due to the over eager garbage collector. Occasionally the
+ garbage collector would collect a C# proxy class instance while it was being used
+ in unmanaged code if the object was passed as a parameter to a wrapped function.
+ Needless to say this caused havoc as the C# proxy class calls the C++ destructor
+ when it is collected. Proxy classes and type wrapper classes now use a HandleRef,
+ which holds an IntPtr, instead of a plain IntPtr to marshal the C++ pointer to unmanaged
+ code. There doesn't appear to be any performance degradation as a result of this
+ modification.
+
+ The changes are in the proxy and type wrapper classes. The swigCPtr is now of type HandleRef
+ instead of IntPtr and consequently the getCPtr method return type has also changed. The net
+ effect is that any custom written typemaps might have to be modified to suite. Affected users
+ should note that the implementation uses the new 'out' attribute in the imtype typemap as the
+ input type is now a HandleRef and the output type is still an IntPtr.
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+04/28/2005: wsfulton
+ [C#] Support for asymmetric type marshalling added. Sometimes the output type needs to be
+ different to the input type. Support for this comes in the form of a new optional 'out'
+ attribute for the ctype, imtype and cstype typemaps. If this typemap attribute is not
+ specified, then the type used for both input and output is the type specified in the
+ typemap, as has always previously been the case. If this typemap attribute is specified,
+ then the type specified in the attribute is used for output types and the type specified
+ in the typemap itself is used for the input type. An output type is a return value from
+ a wrapped method or wrapped constant and an input type is a parameter in a wrapped method.
+
+ An example shows that char * could be marshalled in different ways,
+
+ %typemap(imtype, out="IntPtr") char * "string"
+ char * function(char *);
+
+ The output type is thus IntPtr and the input type is string. The resulting intermediary C# code is:
+
+ public static extern IntPtr function(string jarg1);
+
+04/22/2005: mkoeppe (Matthias Koeppe)
+ [Guile] Fix generation of "define-method" for methods of
+ classes with a constructor. Reported by Luigi Ballabio.
+
+04/15/2005: wuzzeb (John Lenz)
+ [Chicken]
+ For wrapped functions that return multiple values (using argout),
+ SWIG CHICKEN now returns them as multiple values instead of as
+ a list. They can then be accessed using (call-with-values).
+
+04/14/2005: wuzzeb (John Lenz)
+ [Chicken]
+ + Added a whole bunch of new _runme scripts into the chicken test
+ suite. Also fix some bugs these new scripts turned up.
+
+ + Added optimization when returning a wrapped proxy class. Before,
+ a minor garbage collection was invoked every time a function returned.
+
+ + All the chicken Examples should now run correctly
+
+04/14/2005: wsfulton
+ [C#] More fixes for typemap matching when wrapping variables, in particular
+ std::string, so that std::string variables can be easily marshalled with
+ a C# string property using:
+
+ %include "std_string.i"
+ %apply const std::string & { std::string *variable_name };
+ std::string variable_name;
+
+ (Recall that all class variables are wrapped using pointers)
+
+04/05/2005: wuzzeb (John Lenz)
+ [Chicken]
+ + Added Examples/chicken/egg, an example on how to build a chicken
+ extension library in the form of an egg. Also updated the
+ documentation on the different linking options.
+
+ + chicken test-suite now has support to check SWIG with the -proxy
+ argument if there exists a _proxy_runme.ss file.
+
+ + More fixes for overloaded functions and -proxy
+
+03/31/2005: wsfulton
+ Turned on extra template features for all languages which were
+ previously only available to Python.
+
+ This enables typemaps defined within a templated class to be used as
+ expected. Requires %template on the templated class, %template() will
+ also pick up the typemaps. Example:
+
+ template <typename T> struct Foo {
+ ...
+ %typemap(in) Foo "in typemap for Foo<T> "
+ or
+ %typemap(in) Foo<T> "in typemap for Foo<T> "
+ };
+
+ %template(Foo_i) Foo<int>;
+ %template() Foo<double>;
+
+ will generate the proper 'in' typemaps wherever Foo<int> and Foo<double>
+ are used.
+
+03/30/2005: mkoeppe (Matthias Koeppe)
+ [MzScheme] Patch from Hans Oesterholt for supporting MzScheme 30x.
+
+03/29/2005: wuzzeb (John Lenz)
+ [Chicken]
+ + Reallow older versions of chicken (1.40 to 1.89) by passing -nocollection
+ argument to SWIG
+ + %import now works correctly with tinyclos. (declare (uses ...)) will be
+ exported correctly.
+ + TinyCLOS proxy classes now work correctly with overloaded functions
+ and constructors.
+
+03/29/2005: wsfulton
+ [Java] Patch from Scott Michel for directorout typemaps. Java directors
+ require the directorout typemaps like the other languages now. The new
+ typemaps provide fixes for methods where the return type is returned
+ by reference (this cannot automatically be made thread safe though).
+
+03/22/2005: wsfulton
+ Enum casting fixes. Visual C++ didn't like the C type casting SWIG produced
+ when wrapping C++ enum references, as reported by Admire Kandawasvika.
+
+03/21/2005: wsfulton
+ [Perl] SF #1124490. Fix Perl macro clashes when using Visual Studio's STL string,
+ so now projects can #include <string>.
+
+03/21/2005: wsfulton
+ Fixed %varargs which got broken with the recent default argument changes.
+ Also works for Java and C# for the first time now.
+
+03/17/2005: wuzzeb (John Lenz)
+ [Chicken]
+ + Fix a whole bunch of bugs in the chicken module. The entire
+ test suite now compiles, with the exception of the tests that require
+ std_vector.i, std_deque.i, and so on, which chicken does not have yet.
+
+ + Add support for %exception and %typemap(exceptions). Exceptions are
+ thrown with a call to (abort) and can be handled by (handle-exceptions)
+
+03/15/2005: wsfulton
+ [Java] Patch from Scott Michel for directors. Modifications to the typemaps
+ giving users fine control over memory ownership and lifetime of director classes.
+ Director classes no longer live forever by default as they are now collectable
+ by the GC.
+
+03/15/2005: wuzzeb (John Lenz)
+ [Chicken] Add support for adding finalizers garbage collected objects.
+ Functions that return new objects should be marked with %newobject and
+ input arguments which consume (or take ownership) of a pointer should
+ be marked with the DISOWN typemap.
+
+ Also add support for correctly checking the number of arguments passed
+ to a function, and raising an error if the wrong number are passed.
+
+03/14/2005: wuzzeb (John Lenz)
+ Add --without-alllang option to configure.in, which is the same as
+ passing all the --without-python --without-perl5 etc... that Matthias added.
+
+03/09/2005: wsfulton
+ [Php] Memory leak fix for functions returning classes/structs by value.
+
+03/08/2005: wsfulton
+ [Perl] Fix for Perl incorrectly taking memory ownership for return types that
+ are typedefs to a struct/class pointer. Reported by Josh Cherry.
+
+03/07/2005: wsfulton
+ [C#] Various exception changes for the std::vector wrappers. These now more
+ accurately mirror the same exceptions that System.Collections.ArrayList throw.
+
+03/07/2005: wsfulton
+ [C#] Fix undefined behaviour after any of the std::vector methods
+ throw an exception.
+
+03/07/2005: wsfulton
+ [C#] When null is passed for a C++ reference or value parameter, the
+ exception thrown has been corrected to an ArgumentNullException instead
+ of NullReferenceException as recommended in the .NET Framework documentation.
+
+ The default throws typemaps turn a C++ exception into an ApplicationException,
+ not a SystemException now.
+
+03/07/2005: wsfulton
+ [C#] Numerous changes in C# exception handling have been made over the past
+ few weeks. A summary follows:
+
+ The way in which C++ exceptions are mapped to C# exceptions is quite different.
+ The change is to fix C# exceptions so that the C++ exception stack is correctly
+ unwound as previously C++ exceptions were being thrown across the C PInvoke layer
+ into the managed world.
+
+ New typemap attributes (canthrow and excode) have been introduced to control the
+ mapping of C++ to C# exceptions. Essentially a callback into the unmanaged world
+ is made to set a pending exception. The exception to throw is stored in thread local
+ storage (so the approach is thread-safe). The typemaps are expected to return
+ from unmanaged code as soon as the pending exception is set. Any pending exceptions
+ are checked for and thrown once managed code starts executing. There should
+ be minimal impact on execution speed during normal behaviour. Full details will be
+ documented in CSharp.html.
+
+ The SWIG_CSharpThrowException() function has been removed and replaced with the
+ SWIG_CSharpSetPendingExceptionArgument() and SWIG_CSharpSetPendingException()
+ functions. The original name has been deliberately changed to break old code as
+ the old approach was somewhat flawed. Any user defined exceptions that follow the
+ same pattern as the old approach should also be fixed.
+
+ Numerous new .NET framework exceptions are now available for easy throwing from
+ unmanaged code. The complete list is:
+
+ ApplicationException, ArithmeticException, DivideByZeroException,
+ IndexOutOfRangeException, InvalidOperationException, IOException,
+ NullReferenceException, OutOfMemoryException, OverflowException,
+ SystemException, ArgumentException, ArgumentNullException and
+ ArgumentOutOfRangeException.
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+05/05/2005: mmatus
+
+ Fix several memory leaks around. Even when we survive knowning
+ swig is a memory leak factory, it was a little out of
+ control. To run std_containers.i in the python test-suite,
+ swig was using ~260MB, now it uses 'only' ~40MB, which is
+ the same ammount that g++ uses, so, is not that bad.
+ In the process, I found a couple of extra Deletes, which
+ in some cases could trigger seg. faults and/or
+ DOH/asserts.
+
+ [python] Better support for directors + exception. More
+ verbose errors and added an unexpected exception handler.
+
+ [python] Fix memory leak for the
+
+ std::vector<std::vector<int> >
+
+ case,reported by Bo Peng.
+
+ [python] Fix SwigPyObject compare problem reporte by
+ Cameron Patrick.
+
+ [python] Fix several warnings in the generated code
+ for gnu-gcc, Intel and VC7.1 compilers.
+
+
+02/25/2005: wuzzeb (John Lenz)
+ Update documentation to use CSS and <div> instead of <blockquote>
+ I used a script to convert the docs, and it set all the box classes
+ to be "code". There are actually 4 different classes,
+ "shell", "code", "targetlang", and "diagram". We need to go through
+ and convert the divs depending on what they contain.
+
+02/23/2005: mmatus
+
+ [Python] Added option -nortti to disable the use of native
+ C++ RTTI with directors (dynamic_cast<> is not used).
+
+ Add more code for directors to detect and report errors in
+ the python side.
+
+ Extend the use of SWIGINTERN whenever is possible.
+
+ Remove template warnings reported by VC7.1.
+
+ Remove warnings reported by gcc/g++. Finally you can
+ compile using
+
+ g++ -W -Wall -c mymodule_wrap.cxx
+
+ and no spurious errors will be generated in the wrapper
+ code.
+
+02/23/2005: wuzzeb (John Lenz)
+ Added -external-runtime argument. This argument is used to dump
+ out all the code needed for external access to the runtime system,
+ and it replaces including the files directly. This change adds
+ two new virtual functions to the Language class, which are used
+ to find the language specific runtime code. I also updated
+ all languages that use the runtime to implement these two functions.
+
+02/22/2005: mmatus
+ Fix %template + private error SF#1099976.
+
+02/21/2005: mmatus
+
+ Fix swigrun.swg warnings reported when using "gcc -W -Wall"
+ (static/inline not used in front of a function
+ declaration), and add SWIGUNUSED attribute to avoid
+ unused warnings elsewhere.
+
+ Fix unused variable warnings.
+
+ [Python] Use new SWIGUNUSED attribute to avoid warnings in
+ SWIGINTERN methods.
+
+ [Python] Fix PyOS_snprintf for python versions < 2.2 (SF #1104919).
+
+ [Python] Fix map/multimap to allow empty maps (reported by
+ Philippe Hetroy).
+
+ [Docs] Add some documentation to Python.html and
+ SWIGPlus.html, including for example the fact that
+ 'friends' are now supported.
+
+02/21/2005: wsfulton
+ [PHP] Patch from Olly Betts, so that wrappers compile with Zend thread safety enabled.
+
+02/17/2005: wsfulton
+ Memory leak fix in some of the scripting language modules when using default
+ arguments in constructors. The scripting language was not taking ownership of the
+ C++ object memory when any of the constructors that use default arguments was called.
+
+02/16/2005: wsfulton
+ SF #1115055: Failed make install. Patch from Rob Stone.
+
+02/16/2005: wsfulton
+ [Java] SF #1123416 from Paul Moore. Correct memory allocation for STRINGARRAY
+ typemaps in various.i.
+
+02/15/2005: wsfulton
+ Disabled typemap search changes for now (see entry 19/12/2004). It breaks
+ old typemaps, lengthens the execution time by about 25% and introduces
+ inconsistencies.
+
+02/15/2005: wsfulton
+ swig -help follows other software by printing to stdout instead of stderr now.
+ swig -version also displays to stdout instead of stderr now.
+ Behaviour reported by Torsten Landschoff.
+
+02/15/2005: wsfulton
+ [Ruby] Fix for the less commonly used ordering of %include and #include, so
+ that the generated code compiles. Bug reported by reported by Max Bowsher.
+ %include foo.h
+ %{
+ #include foo.h
+ %}
+
+02/15/2005: wsfulton
+ [C#, Java] SWIG_exception macro will now return from unmanaged code / native code
+ as soon as it is called. Fixes possible JVM crashes and other code unexpectedly
+ being executed. Note SWIG_exception is only occasionally used by SWIG library
+ writers, and is best avoided by SWIG users.
+
+02/15/2005: wsfulton
+ [C#, Java] Typemaps can now be targeted at global variable names
+ and static member variable names. Previously the typemaps for
+ the setters were ignored, for example:
+
+ %typemap(in) int globalint "..."
+ int globalint;
+
+02/13/2005: mkoeppe (Matthias Koeppe)
+ [Guile] Add %typecheck for SWIGTYPE, add %typecheck for ptrdiff_t, fix
+ typemaps for size_t.
+
+ [Pike] Merge patch from Torsten Landschoff for improved Pike configuration.
+
+02/12/2005: mkoeppe (Matthias Koeppe)
+ New configure switches --without-tcl, --without-python etc. allow to
+ disable the search for installed languages.
+
+01/31/2005: wuzzeb (John Lenz)
+ - Add DohSortList to DOH
+
+ - Improve the runtime type system:
+ + Speed. Type loading is now O(n log n) instead of O(N^2), which
+ for large modules is a huge improvement.
+ + A whole bunch of functions in swigrun.swg no longer need the
+ swig_type_list_handle passed to them. The only one left is
+ TypeQuery. This also makes runtime.swg a lot smaller.
+ + Split up swig_type_info structure into two structures
+ (swig_type_info and swig_cast_info)
+ + Store a pointer to a swig_type_info rather than just the type
+ name string in the linked list of casts. First off, this makes
+ the guile module a little faster, and second, the
+ SWIG_TypeClientData() function is faster too.
+ + Add the idea of a module into the type system. Before, all the
+ types were stored in one huge linked list. Now, another level is
+ added, and the type system stores a linked list of modules, each
+ of which stores an array of types associated with it.
+ + For more information of how the runtime type system now works,
+ please see Doc/Manual/typemaps.html and Doc/Devel/runtime.txt
+
+ - Update all language modules to use the new type system. The changes
+ to each language module are minor. All languages are now able to
+ use runtime.swg for external access to the type system. Before
+ only python and perl did.
+
+ - [guile, mzscheme, ocaml, and php4] These languages opened up the
+ init function inside the .cxx code, and any code in the .swg files
+ in the init section was inside this function. This was a problem
+ for swiginit.swg, which needs to be inserted before the SWIG_init
+ function is opened. Thus I changed these languages to be like
+ python or perl, where the init function is declared in the .swg
+ file.
+
+ - [Ruby] Instead of moving the init function to the .swg file, I
+ added a new section initbeforefunc, and then added
+ %insert(initbeforefunc) "swiginit.swg"
+
+ - [MzScheme] Fix enums and fix Examples/Makefile.in so that if
+ multiple -I arguments are specified in the INCLUDES variable, each
+ gets a ++ccf.
+
+ - [Guile GH] Update Guile GH to use the new type system. See
+ Doc/Manual/Guile.html for how smobs are now used.
+
+01/11/2005: wsfulton
+ [C#] New typemap called 'csconstruct'. The code in this typemaps was previously hard
+ coded and could not be customised by a user. This typemap contains the code that is
+ generated into a proxy class's constructor.
+
+ [Java] New typemap called 'javaconstruct'. The code in this typemaps was previously hard
+ coded and could not be customised by a user. This typemap contains the code that is
+ generated into a proxy class's constructor. Another typemap named 'javaconstruct_director'
+ is used instead when the proxy class is a director class.
+
+ [C#, Java] If a C++ class did not have a default constructor, a protected default constructor
+ was automatically generated by SWIG. This seems is unnecessary and has been removed
+ and thereby giving the user almost complete control over the generated code along with the
+ new typemaps above.
+
+19/12/2004: mmatus
+ [Disabled, see entry 02/15/2004]
+ - Fix typemap search, now the "out" typemap search is done as follows
+
+ int *Foo::foo(int bar) -> int *Foo::foo(int bar)
+ -> int *Foo::foo
+ -> int *foo(int bar)
+ -> int *foo
+ -> int *
+
+ then, now you can be more specific, and define
+
+ /* apply only for 'Foo::foo' method */
+ %typemap(out) int * Foo::foo(int *bar) ...;
+
+ /* apply for all 'foo' functions/methods */
+ %typemap(out) int * foo(int *bar) ...;
+
+ %inline {
+ struct Foo {
+ int *foo(int *bar);
+ };
+ }
+
+
+15/12/2004: mmatus
+ - More fixes for templates and template default args.
+ See template_default.i for scary cases that now are
+ supported, besides the already ugly STL/std cases.
+
+ - Cosmetics and more use of 'const' where it was implicit.
+ - Other fixes for OSS, which is now working again with 1.3.25.
+
+Version 1.3.24 (December 14, 2004)
+==================================
+
+12/12/2004: wuzzeb (John Lenz)
+ [Chicken] Fix a bunch of bugs relating to -proxy support
+ + non-class variables now export properly using -proxy
+ + static member functions now export properly using -proxy
+ + member class variables now export properly using -proxy
+ + added a -nounit argument, which does not export the (declare (unit ...))
+ + correctly install swigclosprefix.scm
+ + constants (enums, defines) now correcly export when using -proxy
+
+12/11/2004: wsfulton
+ configure fix for when more than one version of jni_md.h is found
+ in the Java include directory (was generating lots of sed error
+ messages).
+
+12/08/2004: wsfulton
+ [Java] Fixes to arrays_java.i so that one can apply the array
+ typemaps to functions taking pointers as input, eg
+
+ %include "arrays_java.i"
+ %apply int[] {int*};
+ void foo(int *a);
+
+12/05/2004: wsfulton
+ [Java] Director mods contributed by Scott Michel. New typemaps
+ directordisconnect and directordisconnect_derived for the
+ swigDirectorDisconnect() method. Also fix to get the javapackage
+ typemap working again.
+
+12/05/2004: mmatus
+ - Finishing the fixes for templates + default template
+ args + specializations.
+
+ - [Python] Now we use the new templates + default template
+ args in the std/STL library. That means the internal
+ swig files are getting uglier since we now support the
+ original declarations:
+
+ template<class _Tp, class _Alloc = std::allocator< _Tp > >
+ class vector {
+ ....
+ };
+
+ template<class _Key, class _Tp, class _Compare = std::less<_Key >,
+ class _Alloc = std::allocator<std::pair<const _Key, _Tp > > >
+ class map {
+ ....
+ };
+
+ and the user can use the %template directive as
+
+ %template() std::vector<int>;
+ %template() std::vector<int, std::allocator<int> >;
+ %template() std::vector<int, MyAllocator<int> >;
+
+ Now we are closer to the cleaning/rewriting of the
+ python std/STL support, such that we recover support for
+ MSVC++ 6.0, and we can add support for other languages
+ too.
+
+
+12/02/2004: wsfulton
+ [Java] Fix for directors when wrapping methods using a member enum
+ and typesafe/proper enums enabled.
+
+12/01/2004: mmatus
+ - Fix typemaps to work with templates and default template
+ args, ie
+
+ template <class A, class B = int>
+ struct Foo {
+ };
+
+ %typemap(in) Foo<int> *{...}
+ %typemap(out) Foo<int,int> *{...}
+
+ Foo<int> * foo( Foo<int> *f1, Foo<int,int> *f2);
+
+ now 'f1', 'f2' and the return value resolve the provided
+ typemaps properly.
+
+ This is highly needed for proper STL support, see new
+ std_basic_string.i, std_sstream.i, etc.
+
+ - Added std_sstream.i, and fix std_basic_string.i to use
+ the new typemaps + template def. arg mechanism. Also,
+ added the needed std_alloc.i. Now, all the containers
+ can be modified to support std::allocator, like in:
+
+ template<class T, class A = std::allocator<T > >
+ class vector {
+ public:
+ ....
+ };
+
+ This change is only completed by now for basic_string.
+
+ - Fix for smart pointers + members + extensions:
+
+ %extend Foo {
+ int extension(int i, int j) { return i; }
+ int extension() { return 1; }
+ }
+
+ %inline %{
+
+ class Foo {
+ public:
+ int y;
+ static const int z;
+ };
+
+ class Bar {
+ Foo *f;
+ public:
+ Bar(Foo *f) : f(f) { }
+ Foo *operator->() {
+ return f;
+ }
+ };
+
+ now you can
+
+ f = Foo()
+ f.y = 3
+ a = f.z
+ f->extension()
+
+ b = Bar(f)
+ b.y = 3
+ a = b.z
+ b->extension()
+
+ - Other small errors fixes, mostly python.
+
+11/25/2004: wsfulton
+ [Java] Numerous director bug fixes so that the correct java types
+ and canonicalized types in the JNI code are emitted. Use of the
+ $javaclassname special variables in the director typemaps now
+ consistent with the non-director typemaps. The types used for
+ typemap lookups are also corrected in a few places. If you
+ previously had your own director typemaps, ensure they are using the
+ correct C++ type.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA DIRECTORS ***
+
+11/25/2004: wsfulton
+ const enum SWIGTYPE & typemaps added. These wrap const enum references
+ as if they were passed by value. Const enum references thus work the
+ same as const reference primitive types such as const double &,
+ const int & etc. Typemaps added for Java, C#, Ruby, Tcl, Perl and Pike.
+
+11/25/2004: wsfulton
+ [Java, C#] New special variable: $*javaclassname, similar to $javaclassname
+ and $&javaclassname. The new one removes a pointer from the C type before
+ obtaining the Java class name. One or more of $javaclassname,
+ $&javaclassname or $*javaclassname may now appear in a typemap. Likewise for
+ C# using csclassname instead of javaclassname.
+
+11/25/2004: wsfulton
+ The last vestiges of enums being handled as integers removed from the
+ internals. The wrapper methods use the enum type rather than an int
+ now. The net result is added type safety for enums when handled as
+ pointers, references etc. Previously in situations such as a method
+ taking a pointer to an enum, a pointer to an int or a pointer to an
+ enum of some other type could inadvertantly be passed to the method.
+ This is now fixed as the descriptor for an enum is no longer based on
+ an int, but the enum type instead. Anonymous enums are still handled
+ as integers.
+
+ The consequence for scripting language users in correct usage of enums
+ should not be noticeable. There is no change for any of the languages
+ where enums are passed by value - most of the scripting languages will
+ still accept an integer for an enum value and the strongly typed
+ languages still use either typesafe enums, integers or proper enums
+ depending on what the user configures. For Java and C# users a change
+ in the typewrapper class name has occurred (for enum pointers,
+ references etc). For example:
+
+ enum Numbers { one=1, two };
+ enum Numbers* number();
+
+ In Java and C# this must now be coded as
+
+ SWIGTYPE_p_Numbers n = modulename.number();
+
+ rather than
+
+ SWIGTYPE_p_int n = modulename.number();
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/21/2004: wsfulton/mmatus
+ Added missing deprecated warning for %name and remove remaining %name
+ usage in the SWIG libraries.
+
+11/21/04: mmatus
+ - [Python] Adding the PySwigObject to be used for carrying
+ the instance C/C++ pointers. This is used instead of
+ string and PyCObjects.
+
+ The new PySwigObject is even safer than PyCObject, and
+ more friendly than plain strings:
+
+ now you can do
+
+ print a.this
+ <Swig Object at _00691608_p_A>
+
+ print str(a.this)
+ _00691608_p_A
+
+ print long(a.this)
+ 135686400
+
+ print "%s 0x%x" % (a.this, a.this)
+ _00691608_p_A 0x8166900
+
+ the last one is very useful when debugging the C/C++
+ side, since is the pointer value you will usually get
+ from the debugger.
+
+ Also, if you have some old code that uses the string
+ representation "_00691608_p_A", you can use it now again
+ using 'str(ptr)', or by calling 'str = PyObject_Str(obj)'
+ in the C/C++ side.
+
+ This change is mainly for nostalgic swig users that miss
+ the string representation, but also allows to say again
+
+ if a.this == b.this:
+ return "a is b"
+
+ and well, since the change were really simple, maybe in
+ the future we will be able to do
+
+ next = a.this + 1
+
+ or add native python iteration over native C/C++ arrays,
+ ie, no need to create/copy new tuples when returning and
+ array or vector.
+
+ Also, a PySwigPacked object was adding to carry a member
+ method pointer, but this is probably a temporary solution
+ until a more general object for methods is added.
+
+ Be aware that to simplify maintaining and compatibility
+ with other tools, the old string and PyCObjects
+ representation could disappear very soon, and the
+ SWIG_COBJECTS_TYPES or SWIG_NO_OBJECT_TYPES macros will
+ have no effect at compilation time. Still, the three
+ mechanisms are present in the code just for testing,
+ debugging and comparison purposes.
+
+11/21/04: mmatus
+
+ - [Python] Adding back support for using the swig runtime code
+ inside the user code. We just allow the user to include
+ the minimal code needed to implement the runtime
+ mechanism statically, just as in done in the swig
+ modules.
+
+ To use the swig runtime code, for example with python,
+ the user needs include the following:
+
+ #include <Python.h> // or using your favorite language
+ #include <swigrun.swg>
+ #include <python/pyrun.swg> // or using your favorite language
+ #include <runtime.swg>
+
+ the files swigrun.swg, pyrun.swg and runtime.swg can
+ be checked out by using swig -co, or they can simply
+ be found by adding the swig lib directory to the
+ compiler include directory list, for example
+
+ SWIGLIB=`swig -swiglib`
+ c++ -I${SWIGLIB} ..
+
+ of better, using the CPPFLAGS, but that depends on your
+ environment.
+
+ This change can be ported to the other languages too,
+ you just need to isolate the needed runtime code in
+ a single file like 'pyrun.swg', and provide the
+ SWIG_Runtime_GetTypeList() method. Look at the
+ Lib/python/pyrun.swg file and the Examples/python/swigrun
+ example.
+
+11/15/04: mmatus
+ - Fix mixed_types.i + gcc-3.4, ie, arrays + references +
+ typedefs
+
+ - Fix multidim arrays + typedefs,ie
+
+ typedef char character[1];
+ typedef character word[64];
+
+ - Process protected/private bases in the same way before
+ we process protected/private members, ie, we check
+ for constructors, operator new, virtual members, etc.
+
+ - Fix Ruby/Java to work (or ignore) multi-inheritance +
+ directors. Allow other languages to define if it is
+ supported or not.
+
+ - Now you can run
+
+ SWIG_FEATURES="-directors -dirprot"
+ make check-ruby-test-suite
+ make check-python-test-suite
+ make check-java-test-suite
+ make check-ocaml-test-suite
+
+ and you will get only 'real' errors. ruby and python
+ compile with no errors, java shows some problems.
+
+Version 1.3.23 (November 11, 2004)
+==================================
+
+11/05/2004: wsfulton
+ Patch #982753 from Fabrice Salvaire: Adds dependencies generation for
+ constructing makefiles. New command line options -MF -MD -MMD to work
+ with the current options -M and -MM. These options are named the same
+ and work the same as in gcc.
+
+11/05/2004: wsfulton
+ %ignore/%rename changes for methods with default arguments to mirror
+ %feature behaviour. See previous entry.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/04/2004: wsfulton
+ %feature improvements for fine tuning when wrapping methods with
+ default arguments. Any %feature targeting a method with default arguments
+ will apply to all the extra overloaded methods that SWIG generates if the
+ default arguments are specified in the feature. If the default arguments are
+ not specified in the feature, then the feature will match that exact
+ wrapper method only and not the extra overloaded methods that SWIG generates.
+ For example:
+
+ %feature("except") hello(int i=0, double d=0.0);
+ void hello(int i=0, double d=0.0);
+
+ will apply the feature to all three wrapper methods, that is:
+
+ void hello(int i, double d);
+ void hello(int i);
+ void hello();
+
+ If the default arguments are not specified in the feature:
+
+ %feature("except") hello(int i, double d);
+ void hello(int i=0, double d=0.0);
+
+ then the feature will only apply to this wrapper method:
+
+ void hello(int i, double d);
+
+ and not these wrapper methods:
+
+ void hello(int i);
+ void hello();
+
+ This has been introduced to make %feature more powerful to ease the migration
+ to new default arguments wrapping approach.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ If you previously had a %feature and didn't specify the default arguments,
+ you will have to add them in now or you can obtain the original behaviour
+ by using %feature("compactdefaultargs").
+
+11/04/2004: wsfulton
+ [C#] Typemaps for std::vector added into std_vector.i. The proxy classes
+ generated are modelled on the .NET ArrayList class. This isn't quite
+ ready for general consumption yet, but will work with vectors of primitive
+ types and some classes.
+
+10/3/2004: wuzzeb (John Lenz)
+ [GUILE] The -scm interface is now the default. The old GH interface can
+ still be enabled by passing -gh to SWIG.
+
+10/2/2004: mmatus
+
+ - More fixes for namespace + class declarations.
+ As an extra bonus, we get %template support for static/members class
+ methods, ie, now you can say:
+
+ namespace space {
+ struct A
+ {
+ template <class Y>
+ static void fooT(Y y) { }
+ };
+ }
+
+ struct B
+ {
+ template <class Y>
+ void barT(Y y) {}
+ };
+
+ %template(foo) space::A::fooT<double>;
+ %template(foo) space::A::fooT<int>;
+ %template(foo) space::A::fooT<char>;
+
+ %template(bar) B::barT<double>;
+ %template(bar) B::barT<int>;
+ %template(bar) B::barT<char>;
+
+ and call
+
+ A.foo(1)
+ b = B()
+ b.bar(1)
+
+ note the methods are emitted inside the classes,
+ and hence, the %template name refers to the 'member'
+ method name, not a global namespace name.
+
+10/31/2004: mmatus
+ - Solve namespace + class declarations, as in
+
+ namespace foo {
+ struct Bar;
+ struct Foo {
+ };
+ }
+
+ struct foo::Bar : Foo {
+ };
+
+ see namespace_class.i for more examples.
+
+ - Fix %template directive to properly use namespaces,
+ including the case:
+
+ namespace one
+ {
+ template <typename T>
+ struct Ptr {};
+ }
+
+ namespace one
+ {
+ struct Obj1 {};
+ typedef Ptr<Obj1> Obj1_ptr;
+ %template(Obj1_ptr) Ptr<Obj1>;
+ }
+
+ namespace two
+ {
+ struct Obj2 {};
+ typedef one::Ptr<Obj2> Obj2_ptr;
+ %template(Obj2_ptr) one::Ptr<Obj2>;
+ }
+
+ this is done by using the namespace name 'one' to create
+ a namespace node to emit the template instantiation,
+ just as before, but the template parameters are resolved
+ and qualified in the current namespace ('one' or 'two').
+ This is same way that typedef works.
+
+ This resolve the smart_pointer_namespace2.i case, and at
+ the same time, several other ones where before swig was
+ generating the
+
+ "Can't instantiate template 'xx' inside namespace 'yy'"
+
+ error message. In fact, that error doesn't exist
+ anymore. You can only get an error if you use a bad
+ namespace name or so.
+
+10/30/2004: mmatus
+ - [ruby] Directors fixes:
+ - enums and std::strings are working now (several
+ reports in bug track system)
+ - added patch 1025861 for director + exceptions
+
+ *** Attention ***: ruby with directors + protected
+ members work with version 1.7+. Older versions seems to
+ have a broken signature for'rb_protect'.
+
+ If you need to use an old version, look at
+
+ http://excruby.sourceforge.net/docs/html/ruby__hacks_8hpp-source.html
+ for workarounds.
+
+ - [ruby] Fix memory allocation problem in typemap (bug 1037259)
+
+ - [tcl] Fix (enums|constants) + namespace option
+ (reported by [email protected]).
+
+ - [perl] Add patch 962168 for multiple inheretance
+
+ - Fix 'defined' as variable name.
+
+10/29/2004: wsfulton
+ Seg fault fix for global scope operator used for friend methods:
+
+ class B {
+ friend void ::globalscope();
+ ...
+ };
+
+10/28/2004:mmatus
+ - Added module and swig option "templatereduce" to force swig
+ to reduce any type needed with templates, ie, in these cases
+
+ %module("templatereduce") test
+
+ template <class T> struct A { };
+
+ typedef int Int;
+ %template(A_Int) A<Int> ==> %template(A_Int) A<int>
+
+ typedef B* Bp;
+ %template(A_Bp) A<Bp> ==> %template(A_Bp) A<B*>
+
+ swig reduces the types Int and Bp to their primitives
+ int and B*. This is closer to the usual compiler
+ resolution mechanism, and it is really needed sometimes
+ when you mix templates + typedefs + specializations.
+
+ Don't use it if you don't have any problem already,
+ since the type reduction can interfere with some
+ user typemaps, specially if you defined something like
+
+ typedef int Int;
+ %typemap(in) Int ...;
+
+ in this case, when you use the "templatereduce" option,
+ swig will ignore the user typemap, since the "typedef int Int"
+ will take precedence, and the usual "int" typemap will be
+ applied.
+
+ Note that the previous case is not common, and should be
+ avoided, ie, is not recommended to use a typedef and a
+ typemap at the same time, specially if you are going to
+ use templates + specializations.
+
+ - Directors:
+
+ virtual destructor is always emitted now, this doesn't
+ cause any harm, and could solve some nasty and
+ mysterious errors, like the one mentioned by Scott.
+
+ also the destructor is not in-lined, so, that can solve
+ some other mysterious errors when mixing directors +
+ imports + embedded applications + some specific compilers.
+
+10/27/2004: wsfulton
+ [C#] typemaps.i library file with INPUT, OUTPUT and INOUT typemaps added.
+
+10/27/2004: wsfulton
+ [Java] std::wstring typemap fixes in std_string.i from Russell Keith-Magee.
+
+10/25/2004: mmatus
+
+ - Using + namespace is working now (using_namespace.i).
+
+ - Derived + nested classes is working now
+ (deriver_nested.i), but of course, we are still waiting
+ for the nested class support.
+
+ - Directors:
+ - unnamed parameters support,
+
+ - protected constructor support (automatic and with
+ dirprot mode),
+
+ - detection of really needed protected declarations
+ (members and constructors) now is done automatically.
+ Even if you don't use the 'dirprot' mode, swig will
+ wrap what is minimally needed (and protected) for the
+ code to compile.
+
+ what is public, as usual, is always wrapped, and if
+ you use the 'dirport'
+
+
+ - Final fixes for the OSS to compile with SWIG 1.3.23 (my
+ very very ugly C++ + templates + everything mounters wrap).
+
+10/25/2004: wsfulton
+ [C#] New commandline option -dllimport. This enables one to specify
+ the name of the DLL for the DllImport attribute. Normally this name
+ comes from the module name, so now it is possible to override this:
+
+ swig -csharp -dllimport xyz example.i
+
+ will generate for all the wrapped PInvoke methods:
+
+ [DllImport("xyz", EntryPoint="...")]
+ public static extern ...
+
+ The wrappers from many different SWIG invocations can thus be compiled
+ into one DLL.
+
+ A new special variable $dllimport can also be used in typemaps, pragmas,
+ features etc. This will get translated into the value specified by -dllimport
+ if specified, otherwise the module name.
+
+10/22/2004: wsfulton
+ [Java] Patch #1049496 from Scott Michel fixes directors methods with
+ enums when wrapped with typesafe or proper Java enums.
+
+10/21/2004: wsfulton
+ Fixes for default arguments in director constructors (Python, Ruby, Ocaml).
+
+10/21/2004: mmatus
+ - [Python] Add the '-cpluscast' option to enable the 'new'
+ C++ casting operators, such as 'static_cast', inside the
+ typemaps. By default swig use the old C cast style, even
+ when parsing C++.
+
+ - [Python] Add the '-new_vwm' option to enable the new
+ SwigValueWrapper mode. Now this is mainly for testing
+ that the typemaps are really safe for any future
+ solution, but you can use it if you have a very strange
+ error with default cosntructors missing + %apply +
+ %typemap, and if everything else fails (see
+ valuwrapper_opaque.i for alternative and current
+ solutions). If you are a user that don't know what is
+ SwigValueWrapper, don't even try it.
+
+ - [Python] Add the '-noh' option to be used with directors
+ and when you prefer to disable the generation of the
+ director header file. If not used, swig will work as
+ usual generating both the wrap.cxx and wrap.h files. If
+ you use it, swig will only generate wrap.cxx.
+
+10/21/2004: wuzzeb (John Lenz)
+ - If you define SWIG_TYPE_TABLE when compiling a wrapper file,
+ the runtime types will be stored in the given type table name.
+ Using this, you can seperate different modules to share their
+ own type systems. -DSWIG_TYPE_TABLE=Mytable
+
+ - [Python] If you define SWIG_STATIC_RUNTIME then the type information
+ will be static to this wrapper. Nothing will be shared with any
+ other modules
+
+ - [Python] If you define SWIG_LINK_RUNTIME, then instead of using
+ the new way of sharing type information, the wrapper will expect
+ to be linked against the Lib/linkruntime.c file. Any modules compiled
+ with SWIG_LINK_RUNTIME and linked against linkruntime.c will all
+ share type information.
+
+10/20/2004: mmatus
+ - [Python] Initial fix for python/import example. Please
+ update the Makefile (autoconf, configure, etc, expert),
+ since now probably is only working with g++, icc and a
+ few other compilers that have the -shared option.
+
+ We need to create additional shared libraries for the
+ virtual destructors. Old and usually forgotten C++
+ requirement.
+
+ Same fix need to be used in perl, I think.
+
+ - [Python] Fix generation of header file for directors,
+ now directors.swg is also included, so, it can be really
+ used from C++, and it solves some problem with compiler
+ that require that, even with the simple swig inclusion.
+
+ - [Python] Reordering the methods and moving some bodies
+ outside the class declaration. This is needed due to
+ some gcc-2.96 internal compiler errors. It seems the
+ PYTHON class is getting too large to been declared and
+ defined at the same time.
+
+ - Add the -oh option to change the output header file name
+ if needed:
+
+ swig -c++ -python test.i -o test.CC -oh test.HH
+
+ this is mainly needed when using directors, and if the
+ current default header file name is not good for you,
+ which is generated as follow:
+
+ swig -c++ -python test.i => test_wrap.h
+ swig -c++ -python test.i -o test.CC => test.h
+
+
+10/20/2004: wsfulton
+ 1) Compact default arguments feature added. This feature allows one
+ to use the default argument code generation that was used in
+ SWIG-1.3.22 and earlier versions. It produces more compact wrappers
+ as only one wrapper method is generated for any method with default
+ arguments. So the advantage is it generates less code but has the
+ original limitations, like it it does not work with all default arguments
+ and default arguments cannot be taken advantage of in the strongly typed
+ languages (C# and Java). It is implemented via the usual %feature mechanism:
+
+ %feature("compactdefaultargs");
+
+ 2) Keyword arguments (kwargs) are working again for default arguments
+ in the languages that support it, ie, Python and Ruby. The new default
+ argument wrapping approach using overloaded methods cannot support kwargs
+ so the compact default argument feature is automatically turned on when
+ kwargs are specified, by %feature("kwargs").
+
+ 3) Compact default arguments are also automatically turned on when wrapping
+ C (not C++) code. This is to support the bizarre notion of default arguments
+ for C code.
+
+10/20/2004: wsfulton
+ Overloaded templated functions in namespaces also working now.
+ Templated functions with default arguments in namespaces too.
+
+10/19/2004: mmatus
+
+ - Allow to disable the new SwigValueWrapper mechanism,
+ if you add the following line in your language main.
+
+ /* Turn on safe value wrapper use mode */
+ Swig_value_wrapper_mode(1);
+
+
+ Now is only active in python. All the other languages
+ are using the old resolution, but they can also use the
+ "valuewrapper"/"novaluewrapper" features to fix some
+ of the old broken cases. Note, however, that not all
+ the broken cases can be solved in that way.
+
+ The new mechanism seems to be working fine in perl, ruby
+ and tcl, but failing in some typemaps in java.
+
+ Hence, is upto the language maintainer to test it, and
+ decide to enable it or not.
+
+ Look at the valuewrapper_opaque.i for examples.
+
+ - Fix more SwigValueWrapper cases when the new mechanism
+ is active. Now it also check for local typemap
+ variables, see valuewrapper_opaque.i for an example when
+ this is needed. But again, this extra checking will only
+ be activated when using the new value wrapper mode.
+
+ - [Python] Fix variable wrapping of classes with private
+ assign operators. It should be easy to fix in all the
+ other modules, instead of checking
+
+ if (!Getattr(n,"immutable")) ...
+
+ you need to verify
+
+ if (is_assignable(n)) ...
+
+ Look at the private_assign.i for an example.
+
+10/18/2004: mmatus
+ - %features "director"/"nodirector" now work as expected.
+ - General fixes in %feature to resolve function decl
+ properly,
+
+ %feature("hello") foo();
+ char foo() -> f() // was working
+ char *foo() -> f().p // it wasn't
+
+
+ - Template + specialization + default template args now is
+ working, (don't confuse with template + default arg
+ values, that was solved before), now this ugly case is
+ working:
+
+ template <class T, class A = Alloc<T> >
+ struct Vector
+ {
+ Vector(T a){}
+ };
+
+ template <>
+ struct Vector<double>
+ {
+ Vector(){}
+ int foo() { return 0; }
+ };
+
+ %template(V_c) Vector<char, Alloc<char> >;
+ %template(V_i) Vector<int>; // picks Vector<int,Alloc<int> >
+ %template(V_d) Vector<double>; // picks the specialization
+
+ this is needed for automatic STL support (later will
+ be).
+
+ - Fix the template + typedef errors in test-suite, which
+ probably will fix another group of strange template +
+ namespaces + typedefs errors.
+
+ - %warnfilter is working better now, parser.y tries to use
+ them when needed.
+
+ - **** New default type resolution method (stype.c) *****
+
+ It preserves the original mixed types, then it goes
+ 'backward' first deleting the qualifier, then the inner
+ types, for example:
+
+ typedef A *Aptr;
+ const Aptr&;
+ r.q(const).Aptr -> r.q(const).p.SWIGTYPE
+ r.q(const).p.SWIGTYPE -> r.p.SWIGTYPE
+ r.p.SWIGTYPE -> r.SWIGTYPE
+ r.SWIGTYPE -> SWIGTYPE
+
+ enum Hello {};
+ const Hello& hi;
+ r.q(const).Hello -> r.q(const).enum SWIGTYPE
+ r.q(const).enum SWIGTYPE -> r.enum SWIGTYPE
+ r.enum SWIGTYPE -> r.SWIGTYPE
+ r.SWIGTYPE -> SWIGTYPE
+
+ int a[2][4];
+ a(2).a(4).int -> a(ANY).a(ANY).SWIGTYPE
+ a(ANY).a(ANY).SWIGTYPE -> a(ANY).a().SWIGTYPE
+ a(ANY).a().SWIGTYPE -> a(ANY).p.SWIGTYPE
+ a(ANY).p.SWIGTYPE -> a(ANY).SWIGTYPE
+ a(ANY).SWIGTYPE -> a().SWIGTYPE
+ a().SWIGTYPE -> p.SWIGTYPE
+ p.SWIGTYPE -> SWIGTYPE
+
+ before it always stops after finding ref/pointer/enum/array/etc.
+
+ Now, then, you can define (use and apply) 'higher' typemaps such as:
+
+ %typemap(in) SWIGTYPE* const&
+ %typemap(out) char FIXSIZE[ANY]
+ %typemap(in) SWIGTYPE* const&
+ %typemap(in) const enum SWIGTYPE&
+ %typemap(in) SWIGTYPE[ANY][ANY]
+ %typemap(in) const char (&)[ANY]
+
+ It is possible with this change that previous typemaps
+ that were defined (but ignored), now will start to work.
+
+ Also, it is necessary check for the '%typemap(varin) SWIGTYPE[]',
+ before it was usually not defined (but char[] was),
+ and that can produce some inconsistencies.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ This change was needed for STL, since std::vector<enum Hello>
+ std::vector<A*>, etc, will always generate methods that
+ mix const references with the vector type.
+
+ Now that is working, all the std::container<T*>
+ specialization will not be needed anymore, well, in
+ theory.
+
+ In the practice, everythin is working as before until
+ the proper mixed types are defined and the libraries
+ simplified to use them.
+
+ - Change the behavior of extern "java"/"fortran"/"etc",
+ now swig produces a warning, and use extern "C" instead.
+ The warning can also be disable with the "-w 313" flag.
+ (WARN_PARSE_UNDEFINED_EXTERN).
+
+ - SwigValueWrapper is now more selective (lang.cxx).
+
+ [Perl/Tcl]
+ - Fix some typemaps (perl/tcl) to work properly with
+ SwigValueWrapper. This was not a problem with
+ SwigValueWrapper, but with the typemaps that now are
+ safe to use with %apply.
+
+ [Python]
+
+ - Fix %callback/%pythoncallback work now as before after
+ the def args changes. Also, %callback now is an alias
+ for %pythoncallback, so, they do the same.
+
+ [Python/Ruby]
+ - %callback is more usable and uniform:
+
+ %callback("%s_cb") foo(); // for both, python/ruby
+ %callback("%s_cb"); // for both, python/ruby
+ %callback(1) foo(); // only in python.
+
+10/17/2004: arty
+ [OCAML]
+ - Tweak to enum typing for soundness in the presence of multiple
+ modules.
+ - global functions are now unambiguous in multiple loaded modules.
+ - Fixed test case code to build multimodule test cases correctly.
+ - There is no way to share overload resolution across modules
+ because of soundness issues. If the user wants to call some
+ function foo from an arbitrary module bar, they will have to
+ use Bar._foo to call it correctly. Later I will fix the
+ camlp4 module to do something clever in this case.
+ - Promided performance overhaul of class mechanism.
+ - Removed symbol hack for ocaml-3.07 and below which is not needed
+ for ocaml-3.08 and above.
+
+10/16/2004: wuzzeb (John Lenz)
+ [CHICKEN]
+ - Completly change how chicken.cxx handles CLOS and generic code.
+ chicken no longer exports -clos.scm and -generic.scm. The clos
+ code is exported directly into the module.scm file if -proxy is passed.
+ - The code now always exports a unit. Running the test-suite is now
+ majorly broken, and needs to be fixed.
+ - CLOS now generates virtual slots for member variables similar to how
+ GOOPS support works in the guile module.
+ - chicken no longer prefixes symbols by the module name, and no longer
+ forces all names to lower case. It now has -useclassprefix and -closprefix
+ similar to how guile handles GOOPS names.
+
+10/16/2004: wsfulton
+ Templated functions with default arguments working with new default argument
+ wrapping approach. The new approach no longer fails with the following default
+ argument pattern (previously failed with some primitive types, like
+ unsigned primitive types):
+
+ template<typename T> int foo(const T& u = T());
+ %template(foo) foo<unsigned int>;
+
+ This relies on the templated function overloading support just added, so all
+ the combinations of overloading by template parameters and normal parameters
+ as well as overloading with default parameters works.
+
+10/16/2004: wsfulton
+ Added support for the large range of templated function overloading that C++
+ supports.
+
+ - Overloaded templated functions, eg
+
+ template<typename T> int overload(T t);
+ template<typename T> int overload(T t, const T &r);
+
+ - Fixes where the templated type is not used in the parameter list, eg
+
+ template<typename T> void xyz();
+ template<> void xyz<double>();
+
+ - Fixes for overloading of plain functions by a templated function:
+
+ void abc(double d);
+ template<typename T> void abc(T t);
+
+ - Overloading by templated parameters fixed:
+
+ template<typename T> void foo(T t) {}
+ template<typename T, typename U> void foo(T t, U u) {}
+
+ %template(foo) foo<double, double>;
+
+ - All combinations of the above also working including specializations, eg:
+
+ void abc(double d);
+ template<typename T> void abc(T t);
+ template<> void abc<double>(double t);
+ template<> void abc(int t);
+
+10/16/2004: wuzzeb (John Lenz)
+ - Remove the ability to share type information by using c linking.
+ All type sharing happens through a global variable in the target language.
+ + Remove SWIG_NOIMPORT, SWIG_RUNTIME, and related defines.
+ + Deprecate -runtime, -noruntime command line options
+ + Update test-suite common.mk to correctly build multicpptest
+ + Remove reference to precommon.swg
+ + Update the guile_gh interface to share data by a global var instead
+ of c linkage.
+
+ - Remove Advanced.html, since everything in it is now obsolete
+
+10/09/2004: mmatus
+ - Split the python std/STL C++ library files, now
+ all the language independent definitions are under
+ the directory
+
+ Lib/std
+
+ and hence, can be used from other languages.
+
+ - Add more documentation to the Python STL, and
+ clean unnecessary code.
+
+ - Add initial C99 complex support, and some fixes
+ for long double.
+
+10/08/2004: mmatus
+ - Fix the SwigValueWrapper for opaque types, now it is
+ applied for opaque templates and classes, for which we
+ don't know if there is or not a default constructor, ie
+
+ struct A {
+ A(int);
+ };
+
+ Still, if you know that you class has a default
+ constructor, and for some very very particular reason
+ you want to avoid the SwigValueWrapper, and you don't
+ want or can't expose the class to swig, now you can
+ say
+
+ %feature("novaluewrapper") A;
+ class A;
+
+ or the other way around, if the class has a default
+ constructor, but you want to use the value wrapper, you
+ can say
+
+ %feature("valuewrapper") A;
+ struct A {
+ A();
+ ....
+ };
+
+ - Fix for char > 128, ie
+
+ const char tilde_a = '\341';
+
+ - Add patch 1041858 for $lextype, which carries the
+ literal type of a symbol. See lextype.i in the
+ test-suite for more details.
+
+
+
+
+10/07/2004: wsfulton
+ {Ruby, Java] Fix director + 'empty' throws
+
+ struct A {
+ A() throw();
+ virtual ~A() throw();
+ int foo() throw();
+ };
+
+
+10/06/2004: wuzzeb (John Lenz)
+ [TCL]
+ - Fix bug reported by William A. Hoffman propagating clientdata
+ between modules. Added clientdata_prop.multicpptest to check for
+ this bug. The fix involved the following changes:
+ + SwigType_clientdata_collect does not need to check
+ types in r_resolved because we only want to propagate clientdata
+ to typedefed classes, and r_mangled already takes care of typedefs.
+
+ + SWIG_TypeRegister now copies the clientdata field correctly
+
+ + Move SWIG_Guile_PropagateClientData function from guile module
+ into common.swg, because we need to call it from both guile and tcl.
+
+ + Add base_names to swig_class to delay the lookup of bases. SWIG
+ now exports the base names and only when the base swig_class is
+ needed is SWIG_TypeQuery(name)->clientdata looked up.
+
+ - conversion_ns_template testsuite test was failing because
+ the name of the wrapped constructor function was not calculated
+ correctly for structs. Fixed.
+
+10/06/2004: wsfulton
+ Fixes for default arguments used in directors - in virtual
+ methods and director constructors.
+
+10/06/2004: mmatus
+ Fix the __cplusplus macro, and bug 1041170.
+ Now it is working as supposed, ie, you can safely use
+
+ #ifdef __cplusplus
+ ...
+
+ all over swig, including inside %defines and %{ %} bodies.
+
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ The old trick of using
+
+ #if __cplusplus
+
+ doesn't work any more. So, if you have your own typemaps
+ using that syntax, you will need to migrate them to use
+ "#ifdef __cplusplus".
+
+10/05/2004: wuzzeb (John Lenz)
+ - Reorganize how runtime type information is stored and shared
+ between modules. For chicken and mzscheme, I removed
+ the ability to use runtime libraries, while perl, tcl, python, and
+ ruby default to using the new method but can go back to the old
+ method by declaring SWIG_ALLOW_RUNTIME.
+
+ - line 582 in mzscheme.cxx was generating a segfault on
+ imports.multicpptest, so I fixed it.
+
+10/05/2004: wsfulton
+ Fixes for %extend and overloaded static methods with default
+ arguments.
+
+10/05/2004: mmatus
+ - [python] Fix director + method with 'empty' throw, ie
+
+ struct A {
+ virtual int foo() throw();
+ };
+
+ other languages should also easy to fix, look for
+ Getattr(n,"throw") in python.cxx.
+
+ - Fix director + destructor with 'empty' throw
+
+ struct A {
+ virtual ~A() throw();
+ };
+
+ - Now SWIG_FEATURES parse all and the same options you
+ can pass to swig in the command line.
+
+ - New command line flag: -features <list>, as in
+
+ swig -features autodoc=3,director
+
+ ie, any global feature can be initialized from the
+ command line. This is mainly for testing, but users
+ can also take advantage of it.
+
+10/04/2004: mmatus
+ - Properly qualify type in syntax as 'long(2)' or 'Foo()',
+ this solve old problem with default args, and probably
+ other problems around. However, the default arg problem
+ was also already solved by William (see below).
+
+ - Fix feature_set and feature_get methods. Before
+ they look from particular to general and keep the first
+ feature found. This didn't work well with templates.
+ Now the methods look from general to particular, and
+ override any found feature.
+
+ - Previously a feature could not be applied to constructors
+ or destructors that weren't explicitly declared in the class.
+ This is now fixed, for example:
+
+ %feature("featurename") Foo() "..."
+ %feature("featurename") ~Foo() "..."
+ class Foo {
+ // implicit Foo() and ~Foo()
+ };
+
+ - Fix missing features for default const/dest, by really
+ 'creating' the methods and applying the features.
+
+ - Fix return_const_value.i case by adding SwigValueWrapper<const T>
+ specialization.
+
+ - Fix %extend + overload, including overloading actual
+ class methods.
+
+ - Adding more cases in related files in the test-suite.
+
+10/04/2004: wsfulton
+ Changes to the way default arguments are wrapped. Previously a single
+ method was generated for each method that had default arguments. If
+ a method had 5 arguments, say, of which 1 had a default argument
+ then the call to the wrapped method would pass 5 arguments. The default
+ value was copied into the wrapper method and used if the scripting
+ language passed just 4 arguments. However, this was flawed as the
+ default argument sometimes does not have global access, for example
+ SWIG would generate code that couldn't compile when wrapping:
+
+ class Tricky {
+ public:
+ void foo(int val = privatevalue);
+ void bar(int val = Tricky::getDefault());
+ private:
+ static int getDefault();
+ enum { privatevalue = 200 };
+ };
+
+ Also bugs in resolving symbols generated code that wouldn't compile, for example
+ (probably fixable though):
+
+ namespace Space {
+ class Klass {
+ };
+ Klass constructorcall(const Klass& k = Klass());
+ }
+
+ The approach also does not work for statically typed languages (C# and Java)
+ as these languages do not allow methods to have variable number of arguments.
+ Although C# has a mechanism to pass a variable number of arguments they
+ must be of the same type and are more like varargs.
+
+ The new approach solves the above problems and wraps methods with default
+ arguments as if the method was overloaded. So SWIG will now treat
+
+ void foo(int val=0);
+
+ as if it had parsed:
+
+ void foo(int);
+ void foo();
+
+ The code generated is then exactly the same as if SWIG had parsed the two
+ overloaded methods. The scripting languages count the arguments passed and call
+ the appropriate method, just like overloaded methods. C# and Java are now able
+ to properly wrap methods with default arguments by generating extra methods,
+ again as if the method was overloaded, so for:
+
+ void bar(string s="hello", double d=10.0, int i=0);
+
+ the following proxy methods are generated:
+
+ void bar(string s, double d, int i);
+ void bar(string s, double d);
+ void bar(string s);
+ void bar();
+
+ The new approach comes with a couple of minor knock on effects.
+
+ 1) SWIG support for default arguments for C (not C++) code no longer works.
+ Previously you could have this interface:
+
+ %{
+ void foo(int val);
+ %}
+ void foo(int val=0);
+
+ and call the wrapped method from a scripting language and pass no arguments
+ whereupon the default of 0 was used. You can get the same behaviour for C
+ code by using the "default" typemap:
+
+ %typemap(default) int val "$1 = 0;"
+ %{
+ void foo(int val);
+ %}
+ void foo(int val);
+
+ or you could of course compile your code as C++ if you want C++ features :) :
+
+ %{
+ void foo(int val=0);
+ %}
+ void foo(int val=0);
+
+ A couple of SWIG's libraries used this C extension and these have been modified
+ to use the "default" typemap. The "default" typemap is thus unchanged (and still
+ is not and is not fully supported by C# and Java, and is likely to remain so).
+
+
+ 2) All features (%feature, %rename, %ignore etc) no longer work as if the method
+ with default arguments is just one method. For example, previously
+
+ %ignore foo(int);
+
+ would have ignored the method completely. Now it will only ignore foo(int) but
+ not the extra foo() method. Instead use:
+
+ %ignore foo;
+
+ to ignore them all. or
+
+ %ignore foo(int);
+ %ignore foo();
+
+ This of course allows one to fine tune the wrapping, for example one could use:
+
+ %rename(fooint) foo(int);
+ %rename(foodefaults) foo();
+ void foo(int val=0);
+
+ and call them from any language like so:
+
+ fooint(200)
+ foodefaults()
+
+ or for example ignore the extra overloaded method, so the defaults cannot be used:
+
+ %ignore foo();
+ void foo(int val=0);
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+10/2/2004: mmatus
+ [Python]
+ - More cleaning up and uniformation on the Python Lib
+
+ - Added Robin's docstring patch, plus some fixes, plus
+ some extensions, see autodoc.i example in the test-suite,
+ and try using %feature("autodoc","extended").
+
+ This patch is not a complete solution for the
+ documentation problem, just enough to inform python about
+ the parameter list.
+
+ The expected swig documentation support is far far away yet.
+
+
+10/1/2004: mmatus
+ - Fix the %callback feature (only used in ruby and python examples,
+ by now, but it should be generic), now member callbacks
+ are working again
+
+ - Fix wrapping of functions pointers like
+
+ std::ostream& std::endl(std::ostream&);
+
+ ie, the ones that return references or enums.
+
+ [Python] Add the %pythoncallback directive, which is
+ an improved version of %callback, ie,
+
+ %pythoncallback(1) foo;
+ %pythoncallback(1) A::bar;
+ %pythoncallback(1) A::barm;
+
+ int foo(int a) {
+ return a;
+ }
+
+ struct A
+ {
+ static int bar(int a);
+ int barm(int a);
+
+ };
+
+ int foobar(int a, int (*pf)(int a));
+
+ in python you can use
+
+ foo(2)
+ foobar(2,foo)
+ A.bar(2)
+ foobar(2,A.bar)
+
+ ie, no additional pointer elements are created, and
+ the original 'foo' and 'A.bar' can be used as parameters.
+
+ In the case of member function however, still you need
+ to use the special variable Class::<fnc_name>_cb_ptr, ie:
+
+ foobarm(3, a, A.barm_cb_ptr)
+
+ we will try to fix this situation also, but later.
+
+ [Python] Add more elements from the STL library, now
+ you can use
+
+ import std
+ std.cout << "hello " << 123 << std.endl
+
+ [Python] Fix in/out return mechanism, now swig will behave
+ as 1.3.21 but using a python list when needed. The problem
+ is that the types std::pair,std::vector,etc, use tuples,
+ and they interfer with the previous inout tuple type.
+
+ By using lists we solve the conflicts, swig acts as before,
+ but returns a list when more than one parameter are using
+ the OUT typemap. See the new inout.i example in the
+ test-suite.
+
+ *** POTENTIAL INCOMPATIBILITY FOR PYTHON MODULE ***
+
+ [Python] Much better error messages for bad arguments, now
+ you always get the argument number where the error occurred.
+
+09/27/2004: wsfulton
+ Patch from Bill Clarke -
+ 1) Warning emitted when -importall and -includeall is used together,
+ with -includeall taking precedence.
+ 2) Ensure SWIGIMPORTED is always defined when a file is being
+ imported with %import. Note that this is not the same as SWIGIMPORT,
+ which gets defined in all generated wrapper files.
+
+09/26/2004: mmatus
+
+ - add %feature("exceptionclass") to identify a class used
+ as exception. Before swig identified and marked a class
+ using the "cplus:exceptionclass" attribute. However, the
+ class needed to appear on an throw() statement. Now
+ swig keeps trying to identify the exception classes, as
+ before, but it also allows the user to mark a class by
+ using the %feature explicitly. (mostly relevant for
+ python and chicken)
+
+ [Python]
+
+ - fix -modern option + exceptions, which mix old class
+ style with the new one. So, we always need to emit
+ the "nonmodern" python code.
+
+ - add the "python:nondynamic" feature and its handler
+
+ now if you have
+
+ %pythonnondynamic A;
+
+ struct A {
+ int a;
+ int b;
+ };
+
+ then, in the python side
+
+ aa = A()
+
+ aa.a = 1 # ok
+ aa.b = 2 # ok
+ aa.c = 3 # error, the class can not be extended dynamically.
+
+
+ Since this is a feature, you can use
+
+ %pythonnondynamic;
+
+ or
+
+ %pythondynamic; [ Note: %pythondynamic since deprecated ]
+
+ to force all the wrapped classes to be "nondynamic" ones.
+
+ The default, as in regular python, is that all the wrapped
+ classes are dynamics. So, careful with your spelling.
+
+09/14/2004: mmatus
+ - Support the -I- option.
+
+ - Differentiate between %include <file> and %include "file".
+ This fix several corner cases.
+
+
+ [Python] Several patches:
+
+ - Normalize the Lib file names:
+ *.swg internal files,
+ *.i user files.
+
+ - Fix Char[ANY] typemaps, so they also delete any extra '\0' chars,
+ now they behave as before (1.3.21). Still, you can use
+ the SWIG_PRESERVE_CARRAY_SIZE macro if you need to
+ preserve the original size (see pystrbase.swg).
+
+ - Add the Char FIXSIZE[ANY] typemaps, to preserve the
+ original C array sizes (see above). Though, you can't
+ use them yet since %apply and arrays are not working
+ together.
+
+ - Add pyfragments.swg, now the user can add fragments
+ to override the default ones.
+
+09/10/2004: wsfulton
+ Patch from Bill Clarke which fixes spurious preprocessor bug which
+ shows on Solaris and gcc, eg:
+ Warning(202): Could not evaluate '!defined(SWIGJAVA) &&
+ !(defined(SWIGCSHARP)'
+ Also fixes a bug where '#if "a" == "b" == 1' wouldn't have worked
+
+09/10/2004: wsfulton
+ Restored multiple build directories for the test-suite. Patch from
+ Bill Clarke.
+
+09/06/2004: wsfulton
+ Added the missing runtime.dsp Visual Studio project files for the
+ import examples to work.
+
+
+Version 1.3.22 (September 4, 2004)
+==================================
+
+09/03/2004: wsfulton
+ The swig.m4 macro for use with the Autoconf/Automake/Libtool has
+ been removed and is no longer installed. Please use the new and better
+ maintained version derived from swig.m4 in the Autoconf macro archive.
+ See http://www.gnu.org/software/ac-archive/htmldoc/ac_pkg_swig.html and
+ http://www.gnu.org/software/ac-archive/htmldoc/ac_python_devel.html.
+
+09/01/2004: wsfulton
+ [Perl] Applied patch #1019669 from Christoph Flamm. Adds support
+ for %feature("shadow") in the same way as it works in Python. This
+ enables one to override the generated shadow/proxy methods, including
+ constructors and destructors. For example:
+
+ /* Let's make the constructor of the class Square more verbose */
+
+ %feature("shadow") Square(double w)
+ %{
+ sub new {
+ my $pkg = shift;
+ my $self = examplec::new_Square(@_);
+ print STDERR "Constructed an @{[ref($self)]}\n";
+ bless $self, $pkg if defined($self);
+ }
+ %}
+
+ class Square {
+ public:
+ Square(double w);
+ ...
+ };
+
+08/31/2004: mmatus
+ [Python] Incompatibility reported by Bill Clarke ([email protected]):
+
+ If you are using Sun Studio 8 (and possibly earlier
+ versions) to compile the output produced by swig
+ 1.3.22rc1, and you are using C++ and STL templates then
+ you need to use either "-runtime" or "-noruntime". If you
+ use neither of these options then you will probably get
+ compiler errors when trying to compile the wrapper file;
+ the error message will be like this: The name
+ SWIG_Python_ConvertPtr[...] is unusable in static
+ swigpy::traits_asptr[...] If you get this error message,
+ you need to regenerate your wrapper file using 'swig
+ -runtime' or 'swig -noruntime'.
+
+ You shouldn't get this problem with Sun Studio 9.
+
+ *** POTENTIAL INCOMPATIBILITY FOR PYTHON MODULE ***
+
+08/26/2004: wsfulton
+ [Perl] Applied #932333 from Ikegami Tsutomu. Fixes long long *OUTPUT
+ and unsigned long long *OUTPUT typemaps in typemaps.i.
+
+08/26/2004: wsfulton
+ Applied patch #857344 from Art Yerkes. Workaround for autoconf bug when
+ running 'make install'.
+
+08/26/2004: wsfulton
+ [Perl] Part of patch #982753 applied. This implements a %perlcode directive.
+ It allows one to add Perl code to the generated .pm file. Works the same
+ as %pythoncode.
+
+08/26/2004: wsfulton
+ [Java] Fix for directors when wrapping virtual methods with exception
+ specifications that were not simple types. Previously code was generated that
+ didn't compile, for example when the exception specification was a pointer.
+
+08/25/2004: wsfulton
+ [C#] Typemap fix for methods that return char *. The CLR would incorrectly
+ delete the memory pointed to by char *. Also applied the same correction to
+ the char array typemaps.
+
+08/24/2004: wsfulton
+ Fixes for -fmicrosoft error/warning message display:
+ - End of file (EOF) warning messages not displaying in correct format
+ - Some messages containing a file path were displaying a double backslash
+ instead of a single backslash
+
+08/23/2004: wsfulton
+ Applied patch #1011604 submitted by Charles Schwieters. Fix for 64 bit tcl
+ interpreters.
+
+08/23/2004: wsfulton
+ Fix for bug #875583 - enum forward declarations previously gave a syntax error.
+
+08/23/2004: mkoeppe
+ [Allegro CL] Use typemaps "ffitype" and "lisptype" to determine the FFI type
+ specifiers from the C type. This makes it possible, for instance, to control
+ whether a C "char" argument takes a Lisp character or a Lisp integer value.
+ The default (taking Lisp characters) is done by these built-in typemaps:
+ %typemap(ffitype) char ":char"
+ %typemap(lisptype) char "character"
+ If char means an integer instead, use these typemaps:
+ %typemap(ffitype) char ":char"
+ %typemap(lisptype) char "integer"
+
+08/22/2004: wsfulton
+ As discussed in bug #772453, the SWIG library directory is now installed
+ into a different default directory. The library used to be installed to
+ /usr/local/lib/swig1.3. It is now in the more usual architecture independent
+ directory and I have additionally used a version specific subdirectory as
+ the library will rarely work with older versions of SWIG. This release
+ will thus use /usr/local/share/swig/1.3.22 by default, which can be
+ tailored as before using './configure --swiglibdir'.
+
+08/17/2004: mkoeppe
+ [MzScheme] Add support to create native MzScheme structures from C structures.
+ To convert a C structure to an MzScheme structure, use the new runtime macro
+ SWIG_NewStructFromPtr in a typemap. Patch from Dmitriy Zavin.
+
+08/12/2004: wsfulton
+ Patch #837715 from Ben Reser to correctly detect Python lib directory
+ on 64 bit systems.
+
+08/12/2004: wsfulton
+ [C# and Java] Prevent memory leaks in the case of early return
+ from wrapper methods using const std::string & parameters. Modified
+ Mark Traudt patch #951565.
+
+08/12/2004: wsfulton
+ Bug #943783 with patch fixes php char * out typemap NULL values.
+
+08/03/2004: Ahmon Dancy <dancy@dancy>
+
+ [allegrocl] Additional case mode fixes. Also, make sure
+ foreign types are exported.
+
+07/24/2004: mkoeppe
+ [Guile] In -scm mode, SWIG modules now exchange their pointer type
+ information via the Guile interpreter. It is no longer necessary to build a
+ runtime library or to use -noruntime and -runtime etc.
+
+ The module (Swig swigrun) which was introduced in the change of 05/17/2004 is
+ no longer automatically built. If you need it, run SWIG on the interface file
+ swigrun.i.
+
+07/23/2004: wsfulton
+ [C#] Bug #917601 Mapping C++ bool fix from Mark Traudt
+
+07/23/2004: wsfulton
+ RPM fixes for latest CVS version including removal of runtime
+ library.
+
+07/23/2004: wsfulton
+ Patch #908955 from Robert H De Vries.
+ RPM file generation fix for Fedore Core 1 and Redhat AS2.1.
+
+07/12/2004: wsfulton
+ Patch #864689 from Robin Dunn:
+
+ This patch corrects two problems in the XML output of SWIG:
+
+ 1. There were often extra '/>\n' in the output.
+
+ 2. value attributes were output with '\n' in them but
+ since that is not technically legal most (all?) XML
+ parsers will strip them out. Replacing the '\n' with
+ the '&#10;' entity reference solves this as that is
+ legal and XML parsers will convert it to a '\n' when
+ reading the values back in.
+
+ This patch also adds a new global command line option
+ that will allow the parse tree to be written out in XML
+ *after* some other language module has been run, in
+ order to be able to get extra info that the language
+ module puts in the tree. In this way the XML is a
+ post-processed version of the tree rather than a
+ pre-processed version.
+
+ Command line option is -dump_xml or -xmlout <file>
+
+07/12/2004: wsfulton
+ [Java] Patch from Scott Michel to fix typesafe enums and proper enums
+ with directors.
+
+07/12/2004: wsfulton
+ HTML documentation (makechap.py) file generator missing end of line
+ patch #908951 from Robert de Vries.
+
+07/08/2004: wsfulton
+ The deprecated runtime library build has been removed. This also removes
+ the dependency on Libtool. Libtool is no longer required to build SWIG.
+ The associated -ldflags SWIG commandline option has also been removed.
+
+ The examples and test-suite testcases that used the runtime library have
+ been updated to use the replacement approach to using SWIG across
+ multiple modules, that is they use the -noruntime and -runtime commandline
+ options, see Modules.html. Effectively they build their own runtime
+ libraries using -runtime. The examples are import and import_template.
+ The test cases are in the imports and template_typedef_import directories.
+
+ Anyone who wants the original runtime libraries can either run the test-suite
+ or build the examples and use the appropriate shared object/DLL that is
+ generated with the -runtime commandline option. For example libimports_runtime.so
+ (Python calls it lib_imports_runtime.so) is generated after running the
+ 'make imports.multicpptest' testcase in the Examples/test-suite/<lang>
+ directory. Or use libruntime.so / runtime.dll after building the import
+ examples in Examples/<lang>/import.
+
+07/07/2004: mkoeppe
+ [Allegro CL] Convert character and string literals in constants to
+ CL syntax. Fix FF:DEF-FOREIGN-CALL for mixed-case C functions.
+
+06/27/2004: wsfulton
+ [Java] New feature for Java exceptions with format %javaexception(exceptionclasses).
+ This feature is a slight enhancement to %exception and the only difference is the
+ addition of the exception classes which are generated into a throws clause.
+ The 'exceptionclasses' is a comma separated list of classes which will be
+ added to the associated proxy method's throws clause. The 'exceptionclasses'
+ are specified like the exception classes in the 'throws' attribute in the
+ typemaps. This feature should be used for correctly handling checked exceptions
+ thrown from JNI code. For example:
+
+ %javaexception("java.lang.Exception") throwException %{
+ ... convert a std::logic_error into a java.lang.Exception using JNI code ...
+ %}
+
+ #include <stdexcept>
+ void throwException() {
+ throw std::logic_error("Logic error!");
+ }
+
+ will generate a method with a throws clause in the module class:
+
+ public static void throwException() throws java.lang.Exception { ... }
+
+06/27/2004: wsfulton
+ [C#] New %csconstvalue(value) feature directive for use with constants and
+ enums. This works the same way as %javaconstvalue. For C#, this directive
+ is the only way that one can fix wrapping of C/C++ enums with proper C#
+ enums if the enum item's initialiser cannot compile as C# code. This is
+ because Java enums can use a call into C code to initialise the enum item,
+ whereas in C#, the enum value must be a compile time constant. That is,
+ using %csconst(0) cannot be used in C# to initialise the C# enum item via
+ a PINVOKE call.
+
+06/27/2004: wsfulton
+ [Java] New %javaconstvalue(value) feature directive for use with constants and
+ enums. Sometimes the use of %javaconst(1) will produce code that won't compile
+ under Java. If a compile time constant is required, %javaconst(0) is not an
+ option. The %javaconstvalue directive achieves this goal and the value specified
+ is generated as Java code to initialise the constant. For example:
+
+ %javaconst(1);
+ %javaconstvalue(1000) BIG;
+ %javaconstvalue("new java.math.BigInteger(\"2000\")") LARGE;
+ %javaconstvalue(10) bar;
+ %{
+ const int bar = 10;
+ %}
+ %inline %{
+ #define BIG 1000LL
+ #define LARGE 2000ULL
+ enum Foo { BAR = ::bar };
+ %}
+
+ Generates:
+
+ public interface exampleConstants {
+ public final static long BIG = 1000;
+ public final static java.math.BigInteger LARGE = new java.math.BigInteger("2000");
+ }
+ public final class Foo {
+ public final static Foo BAR = new Foo("BAR", 10);
+ ...
+ }
+
+ Previously, none of BIG, LARGE or BAR would have produced compilable code
+ when using %javaconst(1).
+
+06/27/2004: wsfulton
+ %feature enhancements. Features can now take an unlimited number of attributes
+ in addition to the feature name and feature value. The attributes are optional
+ and are much the same as the typemap attributes. For example, the following
+ specifies two optional attributes, attrib1 and attrib2:
+
+ %feature(featurename, attrib1="attribval1", attrib2="attribval2") name "val";
+ %feature(featurename, val, attrib1="attribval1", attrib2="attribval2") name;
+
+06/27/2004: wsfulton
+ %feature improvements for the syntax that takes the feature value within the
+ %feature() brackets. The value specified is no longer restricted to being just
+ a string. It can be a string or a number. For example, this is now acceptable
+ syntax:
+ %feature("featurename",20.0);
+ whereas previously it would have to have been:
+ %feature("featurename","20.0");
+ Useful for features that are implemented as a macro, for example:
+ #define %somefeature(value) %feature("somefeature",value)
+ These will now work accepting either a string or a number:
+ %somefeature("Fred");
+ %somefeature(4);
+
+06/06/2004: wuzzeb (John Lenz)
+ [Chicken, Guile]
+ - Created the Examples/test-suite/schemerunme directory, which holds all the
+ runme scripts for guile and chicken (and possibly mzscheme...). The guile
+ and chicken _runme files then (load "../schemerunme/foo.scm").
+ - In chicken module, fix a few bugs invlolving dynamic casts.
+
+06/03/2004: wsfulton
+ Patch to fix wrapping of templated methods. ISO compliant compilers, like
+ Comeau and GCC-3.4.0, don't like the template specifier that SWIG was generating
+ when calling the method. This fix may break some non standard compliant compilers,
+ for example, Sun workshop compilers prior to version 6.2.p2. Patch submitted
+ by Bill Clarke.
+
+06/03/2004: wsfulton
+ [Java, C#] Undocumented special variable $imclassname removed.
+ New special variable $module is replaced by the module name, as specified
+ by %module or -module commandline option. $imclassname can be created from $module.
+
+06/03/2004: wsfulton
+ [C#] Same as for Java below. The new typemaps are named differently, namely,
+ csbody and csbody_derived. The deprecated typemaps are csgetcptr and
+ csptrconstructormodifiers.
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+06/03/2004: wsfulton
+ [Java] Typemap changes for the Java proxy / typewrapper and enum classes. A new
+ typemap called javabody contains the essential support code for generation into the body
+ of these classes. There is also a new javabody_derived typemap which is used instead for
+ wrapped classes that have a wrapped base class. The code is basically, the getCPtr()
+ method and swigCPtr and swigCMemOwn member variables. These used to be hard coded
+ with no way to modify the code. The introduction of this typemap makes it possible for
+ the user to tailor nearly every aspect of the code generation.
+ The exception now is the code for director classes.
+
+ The javagetcptr and javaptrconstructormodifiers typemaps are deprecated and are
+ no longer used as the code that these generated can be put in the more flexible
+ javabody and javabody_derived typemaps.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+ The following macros contributed by Scott Michel may help you upgrade if you have used
+ the javagetcptr typemap:
+
+ /* Utility macro for manipulating the Java body code method attributes */
+ %define SWIGJAVA_ATTRIBS(TYPENAME, CTOR_ATTRIB, GETCPTR_ATTRIB)
+ %typemap(javabody) TYPENAME %{
+ private long swigCPtr;
+ protected boolean swigCMemOwn;
+
+ CTOR_ATTRIB $javaclassname(long cPtr, boolean cMemoryOwn) {
+ swigCMemOwn = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ GETCPTR_ATTRIB static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+ %}
+
+ %typemap(javabody_derived) TYPENAME %{
+ private long swigCPtr;
+
+ CTOR_ATTRIB $javaclassname(long cPtr, boolean cMemoryOwn) {
+ super($moduleJNI.SWIG$javaclassnameUpcast(cPtr), cMemoryOwn);
+ swigCPtr = cPtr;
+ }
+
+ GETCPTR_ATTRIB static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+ %}
+ %enddef
+
+ /* The default is protected getCPtr, protected constructor */
+ SWIGJAVA_ATTRIBS(SWIGTYPE, protected, protected)
+
+ /* Public getCPtr method, protected constructor */
+ %define PUBLIC_GETCPTR(TYPENAME)
+ SWIGJAVA_ATTRIBS(TYPENAME, protected, public)
+ %enddef
+
+ /* Public getCPtr method, public constructor */
+ %define PUBLIC_BODYMETHODS(TYPENAME)
+ SWIGJAVA_ATTRIBS(TYPENAME, public, public)
+ %enddef
+
+06/03/2004: wsfulton
+ [Java, C#] The contents of the class modifier typemaps and pragmas have changed.
+ They must now include the class type. Previously 'class' was hard coded.
+ This change enables flexibility into what type of class is generated,
+ for example the proxy class could be an interface instead of a class.
+
+ For Java this affects the javaclassmodifiers typemap and the jniclassclassmodifiers
+ and moduleclassmodifiers pragmas.
+
+ For C# this affects the csclassmodifiers typemap and the imclassclassmodifiers
+ and moduleclassmodifiers pragmas.
+
+ Unless you have overridden the default versions of these typemaps or pragmas, you
+ shouldn't be affected. However, if you have, upgrading is easy, for example
+
+ class Foo {};
+ %typemap(javaclassmodifiers) Foo "public final"
+
+ must now be:
+
+ class Foo {};
+ %typemap(javaclassmodifiers) Foo "public final class"
+
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+05/31/2004: wsfulton
+ Fix for C++ exception specifications that are references. Problem reported by
+ Oren Miller. Also improves the generated exception declarations in the
+ catch handler for pointers - a pointer is used instead of a reference to
+ a pointer. Added default throws typemaps for SWIGTYPE &, SWIGTYPE * and
+ SWIGTYPE[ANY] (Java and C#).
+
+05/31/2004: wsfulton
+ [Java, C#] Some minor typesafe enum improvements, including storing the name of
+ the enum item. The toSring() / ToString() methods are overridden to return this name.
+
+05/30/2004: wuzzeb (John Lenz)
+ [Chicken]
+ - Update how examples and the test suite are built.
+ - Symbol names are no longer converted to lower case
+ - Added union_runme.ss, which was copied and modified from the guile module
+
+05/26/2004: lballabio (Luigi Ballabio)
+ Committed on behalf of Marcelo (who still has problems with
+ the SourceForge CVS.)
+
+ Added Python typemaps for FILE* with (Python-only) test.
+
+5/24/2004: dancy
+
+ * Allegro CL module: Now using some macros (defined in
+ Lib/allegrocl/allegrocl.swg), swig-defconstant and swig-defun, for
+ defining constants and foreign functions. This makes the
+ generated file a bit neater.
+
+ Now strips a layer of parenthesis from constants.
+
+ Uses (* :void) instead of :foreign-address now.
+
+05/20/2004: wsfulton
+ Unnamed enum global variables are now supported in addition
+ to the recently added support for unnamed enum member variables.
+ For example:
+
+ struct Foo {
+ enum { enum1, enum2 } MemberInstance;
+ };
+ enum { enum3, enum4 } GlobalInstance;
+
+ The int typemaps are used for wrapping the get/set accessor methods.
+ If the sizeof an enum is not the same size as an int then setting the
+ variable will silently do nothing as the casts cannot be easily and portably
+ generated. If you need to solve this highly obscure situation, write
+ the assignment using the %exception feature.
+
+05/20/2004: wsfulton
+ [C#] C# enum wrapping mods. Similar to the Java module, enums can be wrapped using
+ one of 3 approaches:
+
+ 1) Proper C# enums - use %include "enums.swg"
+ 2) Typesafe enums - use %include "enumtypesafe.swg"
+ 3) Simple constant integers (original approach) - use %include "enumsimple.swg"
+
+ See each of these files for further details. Each of these files use typemaps
+ and a new feature to control the generated code. The feature is:
+
+ %csenum(wrapapproach);
+
+ where wrapapproach should be one of: "proper", "typesafe", "typeunsafe" or "simple".
+ [No implementation deemed necessary for type unsafe enums].
+
+ The default approach is proper C# enums. Anonymous enums are always wrapped by
+ constant integers.
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+05/20/2004: wsfulton
+ [Java] Java enum support added. There are now 4 ways in which enums can be wrapped:
+
+ 1) Proper Java enums - use %include "enums.swg"
+ 2) Typesafe enums - use %include "enumtypesafe.swg"
+ 3) Type unsafe enums (constant integers) - use %include "enumtypeunsafe.swg"
+ 4) Simple constant integers (original approach) - use %include "enumsimple.swg"
+
+ See each of these files for further details. Each of these files use typemaps
+ and a new feature to control the generated code. The feature is:
+
+ %javaenum(wrapapproach);
+
+ where wrapapproach should be one of: "proper", "typesafe", "typeunsafe" or "simple".
+ The default typemaps will handle enums that may or may not have specified initial
+ values, for example ten is specified:
+
+ enum Numbers { zero, ten(10) };
+
+ However, the amount of generated Java code can be cut down, by modifying these typemaps
+ if none of the enums have initial values (proper Java enums and typesafe enums approach).
+
+ The default approach is typesafe enums. Anonymous enums are always wrapped by
+ constant integers.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+05/11/2004: wsfulton
+ [Java, C#] Fix bug using %rename on enum items and when using
+ %javaconst(1) / %csconst(1)
+ For example, the following used to generate code that wouldn't compile:
+
+ %rename(Obj) Object;
+ enum Grammar { Subject, Object };
+
+04/28/2004: wsfulton
+ [Java, C#] Minor fixes when using combinations of the
+ javainterfaces, javabase, csinterfaces and csbase typemaps.
+
+05/18/2004: wsfulton
+ [Java] JVM link failure on some systems fixed when using std_vector.i.
+ Also adds default vector constructor for use from Java.
+
+05/17/2004: mkoeppe (Matthias Koeppe)
+
+ [Guile] New runtime functions SWIG_PointerAddress,
+ SWIG_PointerType, SWIG_IsPointerOfType, SWIG_IsPointer.
+
+ [Guile] In -scm mode, wrap several SWIG runtime functions
+ and export them into the module (Swig swigrun). The
+ runtime module is now built with "module" linkage.
+
+ [Guile] GOOPS proxy objects now also print the pointer
+ address of the C object.
+
+05/14/2004: lyle
+ Added Kou's patch for the Ruby %import directive so that modules
+ with "nested" names are handled properly. Consider an interface
+ file foo.i that has this %module declaration at its top:
+
+ %module "misc::text::foo"
+
+ Now consider another interface file spam.i that imports foo.i:
+
+ %import foo.i
+
+ Before this patch, this would result in the following code being
+ generated for spam_wrap.c:
+
+ rb_require("misc::text::foo");
+
+ With this patch, however, you'll get the correct path name
+ for the call to rb_require(), e.g.
+
+ rb_require("misc/text/foo");
+
+ See SourceForge Bug #928299.
+
+05/12/2004: wsfulton
+ Patch for emitting directors when %feature("director") specified
+ for a class with no virtual methods, but does have a virtual destructor.
+ Submitted by Kevin Smith.
+
+05/06/2004: mkoeppe (Matthias Koeppe)
+ New SWIG runtime function SWIG_TypePrettyName, which
+ returns an unmangled type name for a swig_type_info
+ object.
+
+ [Guile]: Use it for printing pointer objects.
+
+05/03/2004: dancy (Ahmon Dancy)
+
+ * Lib/allegrocl/allegrocl.swg: Updated comments about identifer
+ conversion.
+
+ * Sources/Modules/allegrocl.cxx: Register /dev/null for "header"
+ target. Also, disregard "const" qualifiers during type
+ conversion.
+
+
+05/02/2004: wuzzeb (John Lenz)
+ [Chicken] Fix bug 782468.
+ To fix this bug, the runtime code has been rewritten, and
+ pointers are now represented as a C_SWIG_POINTER_TYPE.
+
+ Chicken version > 1.40 is now required!
+
+ * Typemap incompatibility: typemaps no longer use chicken_words.
+ If a typemap needs some space, it should just call C_alloc
+
+ * argout typemaps no longer use the /* if ONE */ construct to
+ build an output list. A SWIG_APPEND_VALUE macro, exactly like
+ guile and mzscheme is now used.
+
+04/25/2004: mkoeppe (Matthias Koeppe)
+ [Guile] In the generated GOOPS code, don't create methods
+ that would not specialize any arguments; simply re-export
+ the primitive functions. (This is a performance
+ optimization which reduces load time and execution time.)
+
+ [Guile] In -gh mode, fix the "too many initializers" error
+ which was caused by an incompatible swig_type_info layout.
+
+ [Guile] The typemap for FILE * in ports.i now also accepts
+ a regular FILE * pointer object. Also a bug with Scheme
+ file ports that are open for input and output has been
+ fixed.
+
+04/25/2004: wsfulton
+ Change entry 03/21/2004 revoked. The change introduced another
+ inconsistency (reference typemaps beings used instead of
+ pointer typemaps for member variables as well as static
+ member variables and global variables for some languages,
+ but only for C++ and not C). This would break user's current
+ typemaps and introduce further inconsistencies. Alternative
+ solution required and being discussed.
+
+04/10/2004: mmatus (Marcelo Matus)
+
+ Added the -directors flag. This enables the director
+ mode for the interface and all the classes that
+ don't set the "feature:nodirector" explicitly.
+
+ You can use this in your module if you want to use the
+ director feature in all your classes, but it is most
+ intended for testing purposes, like:
+
+ make check-python-test-suite SWIG="../../../swig -directors"
+ make check-ruby-test-suite SWIG="../../../swig -directors"
+ make check-java-test-suite SWIG="../../../../swig -directors"
+
+ These commands will run the entire test-suite using
+ directors, and not only the specific 'directors_*'
+ cases. This should be done from time to time.
+
+04/10/2004: mmatus (Marcelo Matus)
+
+ [python] Added support for std::wstring and wchar_t,
+ for compiler and python versions that support them.
+
+ When needed, use
+
+ %inlcude std_string.i // 'char' strings
+ %inlcude std_wstring.i // 'wchar_t' strings
+
+
+04/10/2004: mmatus (Marcelo Matus)
+
+ [python] Fix the default behaviour (seg. fault) when an
+ inplace operator (+=,-=,...) was wrapped, as reported by
+ Lucriz ([email protected]), when the most common
+ form was used:
+
+ A& A::operator+=(int i) { ...; return *this; }
+ ^^^^ ^^^^^^
+
+
+ ie, an object is returned and its contains the same 'this'
+ value than the input object, which is deleted after the
+ operation "a += b", leaving the result with no real
+ object, but a seg. fault.
+
+ To fix it, we needed to introduce a new feature and use an
+ old one:
+
+ %feature("self:disown") A::operator+=;
+ %feature("new") A::operator+=;
+
+ here, "self:disown" disable the ownership of the 'self'
+ or input object, and the "new" feature transfers the
+ ownership to the result object.
+
+ The feature/solution could also be used in other languages
+ that use gc and implement the inplace operators, or other
+ operators, in a similar way.
+
+ *** POTENTIAL INCOMPATIBILITY FOR Python MODULE ***
+
+ If you already are using the inplace operators in python,
+ and you implemented some kind of workaround to the problem
+ fixed here, it is possible you could end with 'free'
+ objects that never get deleted. If that is the case, and
+ you want to disable the current fix, use:
+
+ %feature("self:disown","") A::operator+=;
+ %feature("new","") A::operator+=;
+
+
+04/07/2004: cheetah (William Fulton)
+ [C#] C++ enums are no longer wrapped by integers, they are now wrapped by
+ C# enums. For Example, given C++:
+
+ enum AnEnum { foo, bar };
+ typedef AnEnum AnEnumeration;
+ void something(AnEnum e, AnEnumeration f);
+
+ The following is generated:
+
+ public enum AnEnum {
+ foo,
+ bar
+ }
+ public static void something(AnEnum e, AnEnum f) {...}
+
+ Note that a global enum like AnEnum above is generated into its own
+ file called AnEnum.cs. Enums defined within a C++ class are defined
+ within the C# proxy class. Some of the typemaps for modifying C# proxy
+ classes also work for enums. For example global enums can use
+
+ %typemap(csimports) to add in extra using statements.
+
+ Global enums and class enums can use
+
+ %typemap(csclassmodifiers) to make the enum private, public etc.
+ %typemap(csbase) to change the underlying enum type (enum base)
+
+ If we add this for the above example:
+
+ %typemap(csclassmodifiers) AnEnum "protected"
+ %typemap(csbase) AnEnum "long"
+
+ the following is generated:
+
+ protected enum AnEnum : long {
+ foo,
+ bar
+ }
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+04/07/2004: cheetah (William Fulton)
+ Seg fault fix for empty enums, like
+ enum Foo {};
+
+03/21/2004: mmatus
+ [Note: this change revoked on 04/25/2004]
+ [Python] Makes the following 'var' cases more uniform:
+
+ std::string ga;
+
+ struct A {
+ static std::string sa;
+ std::string ma;
+ };
+
+
+ now the three variables (ga, sa, ma) can be assigned as:
+
+
+ cvar.ga = "hello";
+ A.sa = "hello";
+ a.ma = "hello";
+
+ ie, now 'ma' will also use a std::string typemap 'in' if
+ defined, before it was only accepting a 'p_std_string'
+ pointer. Note, however, that 'ma' will not use the
+ 'varin/varout' typemaps (that probably could be more
+ natural), but it will pick up the 'in' typemap for const
+ std::string& (which is easier).
+
+ The changes in cwrap.c and lang.cxx will probably fix the
+ behaviour in other languages that do not overload the
+ membervarHandler method "too much".
+
+
+03/21/2004: mmatus
+ [Python] Disabling the default instantiations like:
+
+ %template() std::pair<int,int>;
+
+ for all the primitive types and STL containers/classes.
+ They are expensive, specially for pair and map, and the
+ previous behaviour also requires the user to perform
+ manual instantiations. Still, if the speed difference is
+ not important, it can be re-enabled by defining the macro
+ SWIG_STD_DEFAULT_INSTANTIATION (see std_common.i).
+
+ Also, normalizing the INPUT/OUTPUT/INOUT typemaps. Now
+ they use the same conversors than the rest of the
+ typemaps, and you can use them for std::pair, std::string
+ and all the other STL types, like in:
+
+ void p_inoutd(std::pair<double, double> *INOUT);
+
+ Added the attribute.i and implicit.i files with macros to
+ transform functions pairs like 'set_x'/'get_x'
+ (or 'T& x()'/'const T& x() const') into an attribute,
+ and allowing the use of implicit constructors in typemaps
+ (see the files for more details).
+
+03/21/2004: mkoeppe
+ [Guile] Fix the documentation strings of functions with
+ anonymous arguments.
+
+03/18/2004: mmatus
+ [Python] More general std_string.i interface.
+ Now you can wrap it using
+
+ %template(string) std::basic_string<char>;
+
+ and use the std::string as a base class:
+
+ struct A : std::string {
+ };
+
+ But more important, swig will recognize
+ both std::basic_string<char> and std::string as
+ the same type.
+
+03/16/2004: mmatus
+ Previously added, but not mentioned before:
+
+ - friend declaration support, swig now emits a global
+ function in the same class scope.
+
+ - ref/unref features: to mix ref counting C++ classes
+ and native script ref counting mechanisms (like in python).
+
+ Use it like:
+
+ %feature("ref") RCObj "$this->ref();"
+ %feature("unref") RCObj "$this->unref();"
+
+ And the class RCObj, and all the derived ones, will
+ perform the right ref/unref calls when a new pointer
+ is returned to the target language, or when the target
+ language attempts to delete the object.
+
+ See the refcount.i file in the test-suite for more
+ details.
+
+
+03/16/2004: mmatus
+ [Python] Using the new %fragment support, major rewrote
+ of the python swig library, including:
+
+ - Almost automatic template/typemap instantiation for
+ the STL components. For example, now you can write:
+
+ %template(vector_i) std::vector<int>;
+
+ and a specialized vector_i class is emitted with all
+ the needed typemaps. No need to use the old
+ 'specialize_vector' macros.
+
+ Note you can also define
+
+ %template(matrix_i) std::vector<std::vector<int> >;
+ %template(vector_pii) std::vector<std::pair<int,int> >;
+
+ - The empty template instantiation
+
+ %template() std::vector<int>;
+
+ defines the vector typemaps, but no proxy class. For all the
+ fundamental types, the empty template instantiation are
+ defined, so, you can say
+
+ %include std_vector
+
+ int func(const std::vector<int>& a);
+
+ where the proper typemap is applied to 'a', but no
+ std::vector<int> proxy is generated.
+
+
+ - All the STL containers present a more uniform behavior and
+ more complete interface declaration. The following are
+ now supported:
+
+ std::vector<T>
+ std::list<T>
+ std::deque<T>
+ std::set<T>
+ std::multiset<T>
+ std::map<T>
+ std::multimap<T>
+
+ not a container, but also supported:
+
+ std::pair<T,U>
+
+ also, more typemaps are defined for all of them,
+ including varin, varout, typecheck, etc.
+
+ - Initial attempt to implement the STL containers
+ considering allocators, ie:
+
+ std::vector<T,A>
+
+ it is partially working, but it is just a workaround
+ while swig improves its template type support.
+
+
+ Please test with your particular setup. It seems to be
+ working with g++ 3.2.2, g++ 2.96, Intel icc and SGI CC
+ compilers, plus python 1.5.2, 2.0 and 2.3, but since
+ we are using templates, there is a chance you can find
+ some problems when using with an old C++ compiler.
+
+03/16/2004: mmatus
+
+ - Allowing the empty %template directive, such as
+
+ %template() std::vector<int>;
+
+ to process the class "typedef"s and "typemap"s. Before
+ only the internal "typedef"s were processed.
+
+ This makes possible to emit the default in/out
+ typemaps without the need of wrapping an specialized
+ vector instance.
+
+ - Adding the preprocessor extension #@ which mangles the
+ following macro argument, like in:
+
+ #define macro(X) #@X
+ macro(int) -> int
+ macro(std::string) -> std_s_s_string
+
+ - Fragments can now be "type specialized", as the typemaps. The
+ syntax is as follows
+
+ %fragment("name","header")
+ { /* a type independent fragment (old syntax) */ }
+ %fragment("name" {Type}, "header")
+ { /* the fragment is type dependent */}
+
+ Now fragments can also be used inside templates:
+
+ template <class T>
+ struct A {
+ %fragment("incode"{A<T>},"header") {
+ /* 'incode' specialized fragment */
+ }
+
+ %typemap(in,fragment="incode"{A<T>}) {
+ /*
+ here we use the 'type specialized'
+ fragment "incode"{A<T>}
+ */
+ }
+ };
+
+
+03/11/2004: cheetah (William Fulton)
+ [Java] Director bug which meant that some virtual functions overridden in
+ Java were not being called on some operating systems. Bug reported and fixed
+ by Robert de Vries and Scott Michel.
+
+03/02/2004: mkoeppe (Matthias Koeppe)
+ [Guile] In -scm mode, don't forget to check the type of string arguments.
+
+02/24/2004: cheetah (William Fulton)
+ [C#] New commandline option -namespace <name>. This allows one to specify
+ a C# namespace into which all C# classes are generated.
+
+02/23/2004: mkoeppe (Matthias Koeppe)
+ [MzScheme] Use FUNC_NAME rather than a bogus typemap variable for signalling
+ errors. Call scheme_wrong_type with a zero-based argument number.
+ Reported by Ondrej Pacovsky, SF #902621.
+
+ [Guile] Define FUNC_NAME also in the dispatch wrapper for overloaded
+ functions. Patch by John Lenz, SF #896255.
+
+02/22/2004: mkoeppe (Matthias Koeppe)
+ [Guile] In -scm mode, don't try to invoke a null destructor function.
+
+02/20/2004: cheetah (William Fulton)
+ Fixes so that the SWIG source will compile using the Digital Mars Compiler
+ (formerly Symantic compiler) on Windows. Submitted by Scott Michel.
+
+02/13/2004: mkoeppe (Matthias Koeppe)
+ [MzScheme] New command-line argument -noinit. Use it for building
+ the runtime library, where we don't want to define the functions
+ scheme_initialize etc. Reported by Tim Brown, SF #891754.
+
+ [MzScheme] Don't produce invalid C code when invoked with the
+ -declaremodule option. Reported by Tim Brown, SF #891108.
+
+ [Guile] Build the runtime library with passive linkage, to rename
+ the SWIG_init function uniquely.
+
+02/12/2004: cheetah (William Fulton)
+ [Java, C#] Patch submitted by Bill Hoffman which prevents SWIG from crashing
+ when a file for the typewrapper class cannot be opened.
+
+02/11/2004: cheetah (William Fulton)
+ [Java, C#] Overloading changes:
+ - Methods which are overloaded in const only no longer generate Java
+ code that won't compile - the first method parsed is used and a
+ warning is displayed. Note that this behaviour is slightly different
+ to the scripting languages which always uses the non-const method.
+ - Warning messages 509 and 512 replaced by new warning number 516, which
+ is more relevant to these statically typed languages as the overloaded
+ methods aren't 'shadowed', they are ignored.
+
+01/23/2004: mkoeppe (Matthias Koeppe)
+ [Guile] Replace the "known_classes" hash table by a node
+ attribute. Methods of classes in C++ namespaces now get
+ the proper specializer in the GOOPS declaration.
+ Reported by [email protected].
+
+01/23/2004: mkoeppe (Matthias Koeppe)
+ [Guile] Uniquify the argument names in GOOPS shadow method
+ declarations. Reported by [email protected].
+
+01/21/2004: sunshine (Eric Sunshine)
+ Revived the NextStep port of SWIG.
+
+ Fixed fatal problem in DohStrstr() caused by difference in strstr()
+ implementation which made %apply become entirely dysfunctional. On
+ NextStep, strstr("foo","") evaluates to NULL; whereas, on modern
+ platforms, it evaluates to "foo". %apply relies extensively upon
+ strstr("foo","") evaluating to non-NULL, therefore it failed
+ catastrophically when faced with NextStep's strstr().
+
+ Added `bool' check to configure.in since NextStep's C++ compiler
+ does not supply this type. swig.h now fakes up `bool' if needed.
+
+ Worked around NextStep C++ compiler bug in which C++ code is
+ disallowed inside extern "C" functions. This problem affected all
+ language modules, since they publish hook functions of the form:
+ extern "C" Language *swig_foo(void) { return new FOO(); }
+ Fixed by creating a C++ wrapper:
+ static Language *new_swig_foo() { return new FOO(); }
+ extern "C" Language *swig_foo(void) { return new_swig_foo(); }
+
+ Ensured that Swig_copy_string() is used in place of strdup() since
+ NextStep does not supply strdup().
+
+ Fixed detection of Ruby library name and location in configure.in.
+ Problem 1: Assumed that library always resided in Ruby's "archdir",
+ which was correct for Ruby 1.6.x, but which is incorrect for Ruby
+ 1.8.x, in which case the library normally resides in Ruby's
+ "libdir". Problem 2: Assumed that the library could always be
+ linked via "-l"+RUBY_INSTALL_NAME (where RUBY_INSTALL_NAME
+ typically is "ruby"), however this failed for platforms, such as
+ NextStep, which do not support shared libraries. In this case, the
+ static library name in 1.8.x is libruby-static.a, thus
+ -lruby-static is required. The new logic works correctly for
+ static and shared libraries for 1.6.x and 1.8.x.
+
+ Fixed detection of Perl CFLAGS in configure.in for NextStep.
+ Detection code extracted CFLAGS from Perl's %Config hash but
+ neglected to add a newline to the value before passing it through
+ `sed'. NextStep's ancient `sed' discards input which is not
+ terminated with a newline, thus Perl CFLAGS always evaluated to the
+ empty string.
+
+01/16/2004: cheetah (William Fulton)
+ Tidy up in the exception handling code that is generated when
+ C++ exception specifications are wrapped with the throws typemap.
+ This redundant code is no longer generated:
+
+ catch(...) {
+ throw;
+ }
+
+01/12/2004: wsfulton on behalf of mmatus (marcelo matus)
+ if a method uses %exception and the method requires the use
+ of the throws typemap, the code in a throws typemap will be
+ generated inside the try body. For example:
+
+ %exception method {
+ try {
+ // method action
+ $action
+ } catch (int i) {
+ // method int catch handler
+ } catch (...) {
+ // method generic catch handler
+ }
+ }
+ %typemap(throws) Except %{
+ // throws typemap Except catch handler
+ %}
+
+ %inline %{
+ class Except {};
+ void method(int i) throw (Except);
+
+ Will generate:
+
+ {
+ try {
+ // method action
+ try {
+ method(arg1);
+ }
+ catch(Except &_e) {
+ // throws typemap Except catch handler
+
+ }
+
+ } catch (int i) {
+ // method int catch handler
+ } catch (...) {
+ // method generic catch handler
+ }
+ }
+
+
+ As can be seen, the inner try catch block is for the throws typemaps.
+ Previously, this was reversed so that the inner try catch block
+ was the %exception code. In the example above, it would have been
+ impossible to catch Except as the catch all (...) would catch the
+ exception instead.
+
+Version 1.3.21 (January 11, 2004)
+=================================
+
+01/10/2004: cheetah (William Fulton)
+ The output format for both warnings and errors can be selected for
+ integration with your favourite IDE/editor. Editors and IDEs can usually
+ parse error messages and if in the appropriate format will easily take you
+ directly to the source of the error. The standard format is used by
+ default except on Windows where the Microsoft format is used by default.
+ These can be overridden using command line options, for example:
+
+ $ swig -python -Fstandard example.i
+ example.i:4: Syntax error in input.
+ $ swig -python -Fmicrosoft example.i
+ example.i(4): Syntax error in input.
+
+01/09/2004: beazley
+ Fixed [ 871909 ] simple namespace problem.
+ This was a problem using anonymous structures in a namespace.
+ For example:
+
+ namespace ns {
+ typedef struct {
+ int n;
+ } S;
+ };
+
+ Reported by Josh Cherry.
+
+01/09/2004: beazley
+ Fixed some broken Perl examples.
+
+12/28/2003: cheetah (William Fulton)
+ [Java and C#] Fixes for wrapping covariant (polymorphic) return types.
+ For example:
+
+ struct Base {
+ virtual ~Base();
+ virtual Base* copy() const = 0;
+ };
+ struct Derived : Base {
+ virtual Derived* copy() const;
+ };
+
+ The Derived::copy proxy method returns Base not Derived. A warning is issued
+ about this. Previously the pointer used by the proxy class was incorrectly
+ treated as a Base* instead of a Derived*.
+
+12/18/2003: cheetah (William Fulton)
+ Fix so that Windows paths are displayed correctly when reporting errors.
+ An error previously would have been shown something like:
+
+ .?xample.i:14: Syntax error in input.
+
+ instead of:
+
+ .\example.i:14: Syntax error in input.
+
+
+Version 1.3.20 (December 17, 2003)
+==================================
+
+12/17/2003: beazley
+ Last minute modifications. Perl5 module now generates shadow classes
+ by default like all of the other modules. PHP4 wrappers no longer
+ include "config.h".
+
+12/14/2003: beazley
+ Weakened warning message related to constructor names so that an
+ unusual nested-class wrapping technique would work again (apparently
+ it worked in some older SWIG releases). For example:
+
+ class Scope {
+ class ClassA;
+ class ClassB;
+ };
+ class Scope::ClassA {
+ ...
+ };
+ class Scope::ClassB {
+ ...
+ }
+
+ Note: There is still some odd interaction with the SWIG symbol
+ table/type system that will need to be looked at in a future release.
+ Reported by Gustavo Niemeyer.
+
+
+12/11/2003: cheetah (William Fulton)
+ [Java] Protected class methods are wrapped as protected Java methods
+ when using the dirprot director feature. This can be changed using
+ %javamethodmodifiers to something else should the need arise, for
+ example, private or package access.
+
+12/11/2003: cheetah (William Fulton)
+ [Java, C#]
+ %javamethodmodifiers (Java) and %csmethodmodifiers (C#) operate slightly
+ differently. Previously this feature had to be present to set the method
+ modifiers. Now it is only used if it exists for the method being wrapped.
+ The default is "public" as previous however, when wrapping protected
+ director methods it is "protected". This change will not affect existing
+ use of the %javamethodmodifiers or %csmethodmodifiers.
+
+12/11/2003: mmatus (Marcelo Matus)
+
+ This fix some recurring reports about keywords not been
+ properly identified and warned, and it solves the problem
+ of how to add a test file to the test-suite such that it
+ doesn't use any keyword of all the supported languages
+ (and doing it without compiling the test for all the
+ supported languages, thing that is not always possible,
+ and without requiring you to know all the supported
+ language keywords, thing that is always impossible).
+
+ So these are the changes globally speaking:
+
+ - Uniform the definition of the keyword warnings through
+ the supported languages: all the languages has now a
+ separate file that defines the keywords or bad names:
+
+ python/pythonkw.swg
+ chicken/chickenkw.swg
+ ....
+
+ - Added keyword list for most of the languages that didn't
+ have one (using the new separated file).
+
+ - Added the "All keywords" warning support: -Wallkw option.
+
+ This option allows you to include all the known keywords
+ for all the supported languages, and can be used as:
+
+ swig -Wallkw ....
+
+ This will help to the process of adding a test-suite
+ file that can be compiled in all the swig supported
+ languages, and it will be also helpful for users who
+ want to create multi-language libraries.
+
+ And these are the detailed changes (mostly file addition):
+
+ - For the languages that already have some sort of keyword
+ warning list, move it to an external languagekw.swg
+ file, ie:
+
+ move keywords from python.swg -> pythonkw.swg
+ move keywords from chicken.swg -> chickenkw.swg
+ move keywords from tcl8.swg -> tclkw.swg
+
+ and re-include languagekw.swg from language.swg.
+
+ - For the language that didn't have a keyword list, and
+ for the ones that I could find a list, add the
+ languagekw.swg file, ie:
+
+ csharp/csharpkw.swg
+ java/javakw.swg
+ php4/phpkw.swg
+ pike/pikekw.swg
+ ruby/rubykw.swg
+
+
+ also add a line in language.swg to include
+ languagekw.swg, but now it is commented!!!, like in
+ java.swg:
+
+ /* java keywords */
+ /* please test and activate */
+ //%include "javakw.swg"
+
+ ie, there will be no change in how swig runs normally
+ until the language maintainer test and uncomment that
+ line.
+
+ So, please check each languagekw.swg file (I left the
+ link to the keyword list source for checking), and after
+ testing, uncomment the %include line.
+
+ - Added the file allkw.swg, which includes all the
+ languagekw.swg files.
+
+ For the languages that has no languagekw.swg file right
+ now, and if they need one, add the file into the
+ language directory, and add the corresponding include
+ line into the allkw.swg file.
+
+ - Added the -Wallkw that includes the allkw.swg file.
+ Note that the old -lallkw.swg option couldn't be used
+ since it include the file after it would be needed.
+
+
+ Hopefully, the -Wallkw option will be added to the default
+ rules in the related test-suite Makefiles, so, when
+ creating a new test, or adding a new swig library file
+ (like _std_deque.i), swig will warn you if you are using a
+ bad name, considering all the language where it needs to
+ run.
+
+ Right now you can test it by using:
+
+ make check-python-test-suite SWIG="swig -Wallkw"
+
+ or using your favorite target language, it doesn't matter.
+
+ And yes, there are several examples that are using
+ reserved keywords, specially from csharp.
+
+ *** Remember ****: the new keyword warning lists are not
+ included by default in any of language that before didn't
+ have one. To enable the keyword warnings as the default
+ behavior, the inclusion of the languagekw.swg file has to
+ be uncommented at each language.swg file.
+
+ So, all the language maintainers, please check the
+ keywords list.
+
+ Also, you can add buit-in names, and not only keywords, like
+ 'True/False' in python. Remember that you can be more
+ specific and refer only to member names, like *::configure
+ or *::cget (see an example in the tcl8/tcl8kw.swg file),
+ or only global names, like ::range (see an example in the
+ python/pythonkw.swg file.
+
+ Just to be consistent, use the following codes:
+
+ - Use code 314 for keyword and/or fatal bad names.
+ - Use code 321 for buit-in and/or not fatal bad names.
+
+ so, they can't be disabled/enabled independently (see
+ python/pyhtonkw.swg for examples).
+
+ **** And don't add any new test file without checking it
+ with the -Wallkw option!! (that includes me) *****.
+
+
+12/11/2003: cheetah (William Fulton)
+ SF bug #854634
+ Added support for accepting the Unix directory separator '/' on
+ Windows and the Mac in addition to the native one ( '\' on
+ Windows). This can be used in %import, %include and commandline
+ options taking a path, for example -I. On Cygwin, both the Windows
+ and Unix directory separator can now be used (was '/' only).
+
+12/10/2003: mmatus (Marcelo Matus)
+
+ [python] Implementing the runtime "reprotected" director
+ members, if you have:
+
+ %feature("director") B;
+
+ class Bar {
+ public:
+ virtual ~Bar();
+ virtual int hello() { return do_hello();)
+
+ protected:
+ virtual int do_hi() {return 0;}
+ virtual int do_hello() {return 0;}
+ };
+
+ then, at the python side
+
+ import my_module
+
+ class Foo(my_module.Bar):
+ def do_hello(self):
+ return 1
+ pass
+
+ b = Bar() # Pure C++ Director class
+ f = Foo() # C++ Director + python methods
+
+ b.hello() # Ok, and it calls C++ Bar::do_hello()
+ f.hello() # Ok, and it calls Python Foo::do_hello()
+
+ b.do_hi() # RuntimeError, do_hi() is protected!!
+ f.do_hi() # RuntimeError, do_hi() is protected!!
+
+ b.do_hello() # RuntimeError, do_hello() is protected!!
+ f.do_hello() # Ok, since it its redefined in python.
+
+ Here Bar.do_hello is always protected, but Foo.do_hello
+ is "public", because it is redefined in python. Before,
+ all the 'do_hello' methods were public.
+
+ This seems to be a good compromise between C++ and python
+ philosophies, ie, all the director protected methods keep
+ protected at the user side (C++ way) until they are
+ redefined (python way, were all defined methods are always
+ public). And this is not only a good compromise, it also
+ seems to be the only way to do it :).
+
+ Now ruby has native director protected members, and python
+ pure runtime support. I guess these are the two possible
+ extreme cases. And hopefully, they could be used as
+ templates to modify the other languages that support
+ directors, so they can "reprotect" the protected director
+ members at the target language side.
+
+ This finished the director protected support for the
+ python language. Ocalm will need to add the
+ "reprotection" later.
+
+12/10/2003: mmatus (Marcelo Matus)
+
+ The following case (reported by Lyle Johnson) was fixed:
+
+ %rename(x) Foo::y();
+
+ class Foo {
+ public:
+ void y();
+
+ protected:
+ int x;
+ };
+
+ swig warned that the symbol 'x' was already defined, and
+ the renaming fails. 'x' was not emitted, since it is
+ protected, but it was kept in the symbol table with too
+ much information.
+
+ Now swig works for all the cases (plain, director and
+ dirprot) again. This was fixed by allowing the parser.y to
+ decide much closer what to do with 'x'. Before all the
+ discarding or generation was resolved at the lang.cxx
+ stage. Also the changes in parser.y to implement the
+ director protected mode are now much more encapsulated, and
+ they get disabled if the mode is not enabled. Before the
+ deactivation was done at the generation stage (lang.cxx).
+
+ By the other hand, if the director mode is enabled, and
+ %rename is done, reusing a protected member name, there is
+ a pathological case:
+
+ %rename(x) Foo::y();
+
+ class Foo : public A {
+ public:
+ void y();
+
+ protected:
+ int x; /* works */
+ static int x; /* works */
+ static void x(); /* works */
+ typedef void x(); /* works */
+
+ virtual void x(); /* always fails, as it should, since
+ Foo::x() will be emitted in the
+ director */
+
+ void x(); /* always fails, but sometimes it shouldn't,
+ since the Foo::x() will not be emitted if
+ it is not virtual */
+
+ };
+
+ The last case is not always right because at the parser.py
+ stage it is not possible to decide if the protected member
+ Foo::x() could or not conflict with the renamed Foo::y(),
+ since Foo::x() could be virtual by inheritance.
+
+ I guess this just an intrinsic limitation, and no much can
+ be done about it without resorting into larger changes to
+ postpone, under certain conditions, the multiply symbol
+ detection (lang.cxx stage).
+
+ So, by now, it is just considered a well known "feature" in
+ the director protected mode. The good news is that it seems
+ to be a rare case, and it can be avoided by the user by
+ hiding 'x' before renaming 'y':
+
+ %rename(_x) Foo::x();
+ %rename(x) Foo::y();
+
+
+12/08/2003: mmatus (Marcelo Matus)
+ The virtual method detections now properly
+ treats the following cases:
+
+ namespace foo { typedef int Int; }
+ struct A {};
+ typedef A B;
+
+ struct Foo {
+ virtual ~Foo() {}
+
+ virtual Foo* cloner() = 0;
+ virtual int get_value() = 0;
+ virtual A* get_class() = 0;
+ virtual void just_do_it() = 0;
+ };
+
+ struct Bar : Foo
+ {
+ Bar* cloner();
+ foo::Int get_value();
+ B* get_class();
+ void just_do_it();
+ };
+
+ All the Foo and Bar methods are virtual. A new attribute
+ "virtual:type" record the base polymorphic type. In the
+ previous cases we have:
+
+ type : Bar virtual:type : Foo
+ type : foo::Int virtual:type : int
+ type : B virtual:type : A
+ type : void virtual:type : void
+
+ This attribute is useful in languages (java+directors)
+ that could have problems redefining Bar* Bar::cloner().
+
+ If you never had code like the above, you will see no
+ effects. But if you have some code like that, you
+ will see some effects since some methods that
+ before were not properly treated as virtual,
+ will start to act like that. This could enlarge
+ your director classes.
+
+
+12/08/2003: mmatus (Marcelo Matus)
+ The director protected member support (dirprot)
+ is disabled by default.
+
+ It can be enable by using '-dirprot' or by adding
+ the option to the module declaration, like:
+
+ %module(directors="1",dirprot="1") my_module
+
+ This module option was added to properly compile the
+ director_protected.i and director_nested.i examples.
+
+ The feature has been tested with python[2.2,2.3]
+ and ruby[1.6.7], both at compilation and runtime, and
+ java[j2sdk1.4.1_01], but only at compilation (my java
+ installation doesn't run any of the director examples,
+ olds nor news).
+
+ Please test for ocaml and java.
+
+ The errors reported by William and Scott were fixed,
+ except for a warning about SWIG_JavaThrowExecption()
+ multiply defined. I can't reproduce this error with my
+ examples. We will wait for Scott to send us a minimal
+ case.
+
+
+12/07/2003: mmatus (Marcelo Matus)
+ The director protected member support has been
+ completly moved out from python.cxx, and now
+ resides in the common lang.cxx, emit.cxx and
+ allocate.cxx files.
+
+ This means it should work for all the other languages
+ that currently support directors, ie, python, java, ocalm
+ and ruby.
+
+ The change has been tested with python (compilation+runtime)
+ and java (just compilation).
+
+ Please add runtime tests for the missing languages
+ and test it.
+
+ The '-nodirprot' option was moved to the principal main,
+ and can be used from all the languages.
+
+12/07/2003: cheetah (William Fulton)
+ [Java] Fixed and improved error checking of STRING_OUT typemaps in
+ various.i.
+
+12/04/2003: mmatus (Marcelo Matus)
+
+ - Now the virtual members with no explicit declarator
+ are properly identified:
+
+ struct A {
+ virtual int f() = 0;
+ };
+
+ struct B : A {
+ int f();
+ };
+
+ Here, B::f() is virtual, and the director and the
+ virtual elimination mechanism now recognize that.
+
+ - [C#] This fix also fixes the problem where 'override' was not being
+ used on any overridden virtual method, so for struct B above,
+ this C# code is generated:
+
+ public class B : A {
+ ...
+ public override int f() {
+ ...
+ }
+ ...
+ }
+
+ - Initial support for protected virtual methods. They are now
+ properly emitted when using with director (python only by
+ now).
+
+ %feature("director") A;
+ struct A {
+ protected:
+ virtual int f1() = 0;
+ };
+
+ %feature("director") B;
+ struct B : A{
+ protected:
+ int f1();
+ virtual f2();
+ };
+
+ This can be disabled by using the '-nodirprot' option.
+
+ - The feature 'nodirector' is working now at the top level,
+ so, it must work for all the languages:
+
+ %feature("director") A;
+ %feature("nodirector") A::f2;
+
+ struct A {
+ virtual int f1();
+ virtual int f2();
+ };
+
+ in this case, only 'f1' is exported to the director class.
+
+ - Added director support for const TYPE& arguments (python).
+
+12/02/2003: cheetah (William Fulton)
+ [Java] Fix for INOUT and OUTPUT typemaps in typemaps.i for when the JNI type
+ is bigger than the C type. For example, unsigned long (32bits on most systems)
+ is mapped to jlong (64bits). Returned value was incorrect. Bug reported by
+ Brian Hawley.
+
+12/02/2003: cheetah (William Fulton)
+ [C# and Java] Better fix for entry dated 05/11/2003. Fixes the following
+ typemaps:
+
+ Java: javabase, javainterfaces, javaimports, javaclassmodifiers,
+ javaptrconstructormodifiers, javafinalize, javagetcptr & javacode.
+ C#: csbase, csinterfaces, csimports, csclassmodifiers,
+ csptrconstructormodifiers, csfinalize, csgetcptr & cscode.
+
+ It also fixes bug in using arrays of C structs with arrays_java.i
+ as reported Scott Michel.
+
+12/02/2003: beazley
+ [Perl] Fixed [ 852119 ] recursive inheritance in output .pm, perl5.
+ Reported by William Dowling.
+
+12/02/2003: beazley
+ [Tcl] Fixed [ 755382 ] calling func(const vector<T>& p) evaluates p[0] in interp.
+ The Tcl type checker was improperly handling the interpreter result when
+ type violations were supposed to be ignored.
+ Reported by Flaviu Popp-Nowak.
+
+11/30/2003: cheetah (William Fulton)
+ Fixed [ 545058 ] configure's --with-tclincl has no effect
+
+11/30/2003: cheetah (William Fulton)
+ [Java] Fixed [ 766409 ] missing symbol SWIG_JavaThrowException during module load
+ SWIG's internal functions are all static as there is no need for different SWIG
+ generated modules to share any code at runtime.
+
+11/30/2003: beazley
+ [Tcl] Added support for C++ pointers to members.
+
+11/28/2003: cheetah (William Fulton)
+ Fixed [ 848335 ] Directors: #include wrapper .h file - was incorrectly
+ adding a directory to the generated #include "foo_wrap.h" statement
+ in some situations.
+
+11/28/2003: cheetah (William Fulton)
+ [Java] Fixed [ 849064 ] JAVA : Access modifier for derived class wrong.
+ The delete() method is always public now. It used to be protected whenever a
+ destructor was non public. An UnsupportedOperationException runtime
+ exception is thrown instead of making delete() protected now.
+
+11/28/2003: beazley
+ [Perl5] Added support for C++ pointers to members.
+
+11/28/2003: beazley
+ Fixed [ 850151 ] PYVERSION with python2.3 in configure of SWIG 1.3.19 (Maybe).
+
+11/28/2003: beazley
+ Fixed [ 850666 ] #include extra line added.
+ This should fix some problems with getting correct line numbers on
+ error messages.
+
+11/26/2003: beazley
+ Fixed another one of Marcelo's evil template bugs (infinite
+ recursion). [ 849504 ] template and typedef -> inf. recursion.
+
+11/26/2003: beazley
+ Fixed parsing problem with declarations like this:
+
+ int *x = &somearray[0];
+
+11/25/2003: beazley
+ Fixed [ 756552 ] missing default argument class scope with "|".
+ This is really only a band-aid fix for use of class-enums in
+ expressions. For example:
+
+ class A {
+ public:
+ enum Flag { flag1 = 0x1, flag2 = 0x2 };
+ void foo(int x = flag1 | flag2);
+ };
+
+ Note: there are still some (more subtle) cases that are broken,
+ but hard to fix due to an issue with template expansion. Will
+ address later.
+ Reported by Dmitry Mironov.
+
+11/25/2003: beazley
+ Incorporated [ 840878 ] support for %inline { ... } (PATCH).
+ This adds support for the following:
+
+ %inline {
+ ... some code ...
+ }
+
+ The difference between this and %inline %{ ... %} is that the
+ enclosed text is processed by the SWIG preprocessor. This
+ allows special macros and other processing to be used in
+ conjunction with %inline.
+ Contributed by Salvador Fandino Garcia.
+
+11/25/2003: beazley
+ Fixed [ 836903 ] C++ inconsistency (with void arguments).
+ SWIG was having difficulty with f() vs f(void) in C++ programs.
+ For instance:
+
+ class A {
+ public:
+ virtual void f(void) = 0;
+ };
+
+ class B {
+ public:
+ virtual void f(); // Not matched to f(void) correctly
+ };
+
+ The parser now normalizes all declarations of the form f(void)
+ in C++ classes to f(). This should fix a variety of subtle
+ problems with inheritance, optimizations, overloading, etc.
+ Problem reported by Partho Bhowmick.
+
+11/25/2003: beazley
+ [Perl5] Incorporated [ 841074 ] better croaking (PATCH). This fixes some problems
+ with strings and provides some new error functions.
+ Contributed by Salvador Fandino Garcia.
+
+11/25/2003: beazley
+ Fixed [ 791835 ] Default argument with cast: txt = (char *)"txt" syntax Error.
+ The parser should now accept things like this:
+
+ void foo(char *s = (char *) "Hello");
+
+ Problem reported by Claudius Schnorr.
+
+11/24/2003: beazley
+ [Tcl] Fixed problem with cross module linking. Previously modules referred
+ to base classes through a global variable. Now, the module looks up base
+ classes through the type system itself---avoiding the need to link to a global
+ like before. Caveat: modules with base classes must be loaded before
+ modules with derived classes.
+
+11/24/2003: mkoeppe (Matthias Koeppe)
+ [Guile] In -scm mode, use () to represent null pointers,
+ as it is done in -gh mode.
+
+11/23/2003: mkoeppe (Matthias Koeppe)
+ Add a generated script "preinst-swig", which can be used
+ to invoke SWIG before it has been installed. It arranges
+ that the runtime libraries from the source directory are
+ used.
+
+11/23/2003: mkoeppe (Matthias Koeppe)
+ [Guile] In -gh mode, don't forget to call SWIG_Guile_Init.
+ Add a SWIG_contract_assert macro.
+
+11/23/2003: mkoeppe (Matthias Koeppe)
+ [MzScheme] Update the configure check for the dynext object to work
+ with MzScheme 205.
+
+11/20/2003: mmatus
+ Fixed the include/import error reported by Kerim Borchaev,
+ where two files with names like
+
+ 'dir1/hello.i'
+ 'dir2/hello.i'
+
+ can not be include at the same time. Swig was including
+ just the first one, assuming the second one was not a
+ different one, since it was checking/keeping just the
+ basename 'hello.i'.
+
+11/19/2003: beazley
+ Changes to the SWIG runtime library support.
+ - The -c command line option has been renamed to -noruntime
+ - New command line option: -runtime. When supplied, this
+ inserts the symbol SWIG_GLOBAL into the wrapper code. This,
+ in turn, makes all of the runtime support functions globally
+ visible.
+ - New library file: swigrun.i. Used to create modules
+ for runtime library (if needed).
+
+11/18/2003: cheetah (William Fulton)
+ 'make srcrpm' rpmbuild fix - patch from Joe Cooper
+
+11/18/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Change meaning of configure option --with-guile to
+ the name of the Guile executable. The new option --with-guile-prefix
+ can be used to specify the tree where Guile is
+ installed. (However, usually it suffices to use the
+ single option --with-guile-config.)
+ When running the run tests test-suite, make sure to use the
+ version of Guile that SWIG was configured for.
+
+11/17/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Improvements to object-ownership management in
+ "-scm" mode. (They do not apply to the default "-gh" mode.)
+ * Renamed the smob type that indicates that the object can
+ be garbage collected from "collected swig" to "collectable
+ swig", which is more precise.
+ * Export the destructor functions again. It is now
+ allowed to explicitly call destructors, even for
+ garbage-collected pointer objects. A pointer object
+ that has been passed to a destructor is marked in a
+ special way using a new smob type, "destroyed swig".
+ (This helps avoid nasty memory bugs, where references to
+ dead C objects are still held in Scheme. Moreover, the
+ garbage collector will not try to free a destroyed
+ object once more.)
+ * Destructor-like functions can also mark their arguments
+ as destroyed by applying the typemap SWIGTYPE *DESTROYED.
+ (It calls the function SWIG_Guile_MarkPointerDestroyed.)
+ * Functions that "consume" their objects (or that "own"
+ them after the call) can mark their arguments as
+ not garbage collectable. This can be done by applying
+ the typemap SWIGTYPE *CONSUMED. (It calls the function
+ SWIG_Guile_MarkPointerNoncollectable.)
+ * The macro TYPEMAP_POINTER_INPUT_OUTPUT from library
+ pointer-in-out.i creates additional typemaps
+ PTRTYPE *INPUT_CONSUMED, PTRTYPE *INPUT_DESTROYED.
+ They mark the passed pointer object likewise.
+ The typemap PTRTYPE *OUTPUT creates a garbage-collectable
+ pointer object, like %newobject does for a returned
+ pointer. Use the new typemap PTRTYPE *OUTPUT_NONCOLLECTABLE
+ to create a pointer object that will not be garbage collected.
+
+11/17/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Handle $input in "freearg" typemaps.
+ Never qualify GOOPS slot names with the class name.
+ Handle optional arguments properly in the GOOPS methods.
+
+11/16/2003: cheetah (William Fulton)
+ Fixes for installation to work with the upcoming Automake-1.8.
+ mkinstalldirs was being used by a non-Automake makefile.
+ mkinstalldirs is being phased out and so was not being
+ created by Automake. install-sh used instead.
+
+11/16/2003: cheetah (William Fulton)
+ [Java] Numerous director improvements, tweaks and bug fixes since
+ the initial implementation have been contributed by Scott Michel.
+
+11/12/2003: beazley
+ [Python] When %feature("shadow") is used to add code to shadow
+ classes, the special variable $action expands to the name of the
+ underlying wrapper function that would have been called normally.
+
+11/12/2003: beazley
+ [Python] When generating proxy class code, SWIG emits a few
+ default methods for __repr__() and other Python special
+ methods. Some of these methods are emitted after all of the
+ contents of a class. However, this makes it hard to override
+ the methods using %pythoncode and some other directives that
+ allow code to be inserted into a class. These special methods
+ are now emitted into the code *before* all of the other methods.
+ Suggested by Eric Jones.
+
+11/11/2003: beazley
+ Preprocessor enhancement. For include statements like this:
+
+ %include "foo/bar.i"
+
+ the directory "foo" is now added to the search path while
+ processing the contents of bar.i. Thus, if bar.i includes other
+ files in the same directory, they will be found. Previously,
+ you would have to add additional directories using -I to make this
+ work correctly. Note: the C preprocessor seems to behave in
+ an identical manner on many (most? all?) systems.
+ Suggested by Kerim Borchaev.
+
+11/11/2003: beazley
+ Configuration changes to make SWIG work on Mac OS X 10.3.x (Panther).
+ Tested with Python, Tcl, Perl, and Ruby---all of which seem to work.
+
+11/08/2003: cheetah (William Fulton)
+ [Java] Fixed the typemaps in various.i which were mostly broken.
+ char **STRING_IN and char **STRING_RET typemaps replaced with
+ STRING_ARRAY. float *FLOAT_ARRAY_RETURN typemap removed.
+
+11/08/2003: beazley
+ [Tcl] Tcl module now emits a safe module initialization function by
+ default. It can be removed by running 'swig -nosafe'.
+
+11/04/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Only use the SCM_ API when the function
+ `scm_slot_exists_p' exists (needed for GOOPS support).
+ This function was renamed during the Guile 1.5 series
+ from `scm_slots_exists_p'.
+ Report the right runtime library when invoked with
+ -scm -ldflags.
+
+11/03/2003: mkoeppe (Matthias Koeppe)
+ [Chicken] Fix #782052. The --with-chickencfg configure
+ option (and others) were not accepted.
+
+11/02/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Merge new set of GOOPS changes by John Lenz.
+ GOOPS objects are now manipulated directly by the C code.
+ Some fixes to typemap-GOOPS interaction.
+
+11/02/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Remove the file argument to -scmstub and -goops.
+ The Scheme files are now always called MODULE.scm or
+ MODULE-primitive.scm, where MODULE is the module name and
+ "primitive" can be changed by the -primsuffix option.
+ The Scheme files are now placed in the directory given by
+ the -outdir option, or the current directory.
+ (Patch by John Lenz, slightly modified.)
+
+ *** INCOMPATIBILITY [Guile] ***
+
+11/02/2003: mkoeppe (Matthias Koeppe)
+ Unify the pointer-conversion runtime API. The standard
+ functions are:
+ * SWIG_NewPointerObj (POINTER, TYPE, FLAGS)
+ -- Create an scripting object that represents a typed
+ pointer. FLAGS are language specific.
+ * SWIG_ConvertPtr (INPUT, RESULT, TYPE, FLAGS)
+ -- Get a pointer from the scripting object INPUT and
+ store it in the place RESULT. When a type mismatch
+ occurs, return nonzero.
+ * SWIG_MustGetPtr (INPUT, TYPE, ARGNUM, FLAGS)
+ -- Get a pointer from the scripting object INPUT and
+ return it. When a type mismatch occurs, throw an
+ exception. If ARGNUM > 0, report it as the
+ argument number that has the type mismatch.
+ [Guile]: No changes.
+ [MzScheme]: No changes.
+ [Perl]: Add the function SWIG_NewPointerObj.
+ The function SWIG_MakePtr is kept.
+ The function SWIG_MustGetPtr is currently not
+ supported.
+ [Python]: Add the function SWIG_MustGetPtr.
+ [Ruby]: Add the function SWIG_MustGetPtr.
+ [Tcl]: Remove the "interp" argument of
+ SWIG_NewInstanceObj, SWIG_ConvertPtr,
+ SWIG_ConvertPacked, and SWIG_ConvertPtrFromString.
+ The function SWIG_MustGetPtr is currently
+ not supported.
+ No changes to Pike because its pointer conversion code did
+ not look complete. No changes to PHP4, because I did not
+ understand its runtime code. No changes to Chicken
+ because major changes are expected soon anyway. No
+ changes to Java, OCaml, C# because they do not seem to
+ have a pointer-conversion runtime API.
+
+ *** INCOMPATIBILITY [Tcl] ***
+
+11/02/2003: mkoeppe (Matthias Koeppe)
+ [Perl5, PHP4, Pike, Python, Ruby, Tcl]: Use the
+ preprocessor to rename external functions of the SWIG
+ runtime API to follow the naming convention
+ SWIG_<language>_<function>. This should allow linking
+ more than one interpreter into a program.
+
+10/31/2003: cheetah (William Fulton)
+ [C#] Fix since introducing the exception and std::string delegates.
+ The fix overcomes linker errors when using more than one SWIG module.
+ Problem reported by Andreas Sch�rk.
+
+10/31/2003: beazley
+ Incorporated patch: [ 823302 ] Incr Tcl support.
+ Contributed by Alexey Dyachenko.
+ Note: needs documentation.
+
+10/31/2003: beazley
+ Incorporated patch: [ 829325 ] new Python Module options and features.
+ Robin Dunn writes:
+
+ This patch makes a number of changes to the SWIG python module.
+
+ 1. Add -apply option, and change the default code
+ output to use the foo(*args, **kw) calling syntax
+ instead of using apply(). If the -apply option is
+ given then code is generated as before. This is very
+ similar to Patch #737281 but the new -modern option
+ makes the second half of that patch unnecessary so it
+ is not included here.
+
+ 2. Add -new_repr option. This is the same as my Patch
+ #797002 which I will mark as closed since it is no
+ longer needed. When this new option is used then the
+ __repr__ methods that are generated for proxy classes
+ will be more informative and give details about the
+ python class and the C++ class.
+
+ 3. Add %feature("addtofunc"). It allows you to insert
+ one or more lines of code inside the shadow method or
+ function that is already generated, instead of
+ replacing the whole thing like %feature("shadow") does.
+ For __init__ it goes at the end, for __del__ it goes
+ at the begining and for all others the code generated
+ is expanded out to be like
+
+ def Bar(*args, **kwargs):
+ val = _module.Foo_Bar(*args, **kwargs)
+ return val
+
+ and the "addtofunc" code is inserted just before the
+ return statement. If the feature is not used for a
+ particular method or function then the shorter code is
+ generated just like before.
+
+ 4. A little bit of refactoring to make implementing
+ addtofunc a little easier.
+
+ 5. Added a -modern command-line flag that will cause
+ SWIG to omit the cruft in the proxy modules that allows
+ it to work with versions of Python prior to 2.2. The
+ result is a simpler, cleaner and faster python proxy
+ module, but one that requires Python 2.2 or greater.
+
+10/31/2003: beazley
+ Incorporated patch: [ 829319 ] XML module tweaks.
+ This adds a new command line option -xmllite that
+ greatly reduces the amount of emitted XML code by
+ eliminating some fields mostly used in SWIG's
+ internal processing. Contributed by Robin Dunn.
+
+10/31/2003: beazley
+ Incorporated patch: [ 829317 ] Adds DohSplitLines function.
+ Contributed by Robin Dunn.
+
+10/29/2003: beazley
+ Fixed [ 827907 ] argout objects not being wrapped properly (PATH).
+ Patch contributed by Salvador Fandi�o Garc�a.
+
+10/29/2003: beazley
+ Fixed [ 826996 ] perl type checking ignores perl subclasses.
+ This enhancement makes it so wrapped classes and structs can
+ be subclassed in Perl and used normally.
+ Patch contributed by Salvador Fandi�o Garc�a.
+
+10/16/2003: cheetah (William Fulton)
+ [C#] IntPtr marshalled with a void* instead of int in C function
+ declarations. The casts thus look more conventional, for example:
+
+ // old
+ DllExport double SWIGSTDCALL CSharp_get_Shape_x(int jarg1) {
+ ...
+ Shape *arg1 = (Shape *) 0 ;
+ arg1 = *(Shape **)&jarg1;
+ ...
+ }
+ // new
+ DllExport double SWIGSTDCALL CSharp_get_Shape_x(void * jarg1) {
+ ...
+ Shape *arg1 = (Shape *) 0 ;
+ arg1 = (Shape *)jarg1;
+ ...
+ }
+
+
+10/14/2003: beazley
+ Fixed a subtle problem with overloaded methods and smart pointers.
+ If a class has overloaded methods like this:
+
+ class Foo {
+ public:
+ int bar(int x);
+ static int bar(int x, int y);
+ };
+
+ and the class is used as a smart pointer:
+
+ class FooPtr {
+ public:
+ Foo *operator->();
+ };
+
+ The SWIG would try to expose the static member Foo::bar
+ through FooPtr---resulting bogus wrapper code and a compiler
+ error.
+
+ Due to the way in which overloading is handled, it is
+ extremely difficult to eliminate the static method in
+ this case. Therefore, it is still exposed. However,
+ the generated code now compiles and works.
+
+10/05/2003: mkoeppe (Matthias Koeppe)
+ [Guile, MzScheme, Chicken]: Remove symbol clashes between
+ the runtime libraries by renaming all extern common.swg
+ functions with the preprocessor.
+
+10/05/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Added basic GOOPS support, contributed by John Lenz.
+ See the documentation for details.
+
+ *** NEW FEATURE ***
+
+10/04/2003: mkoeppe (Matthias Koeppe)
+ [Guile] New option, -only-setters, which disables
+ traditional getter and setter procedures for structure slots.
+
+10/03/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Added run test for reference_global_vars by John Lenz.
+
+09/30/2003: beazley
+ Partial solution to [ 792180 ] C++ smart-pointer/namespace mixup revisited.
+ The problem is not easy to fix (at least it doesn't seem so), but is
+ related to the instantiation of qualified templates inside of other
+ namespaces. SWIG now generates an error message in this case rather
+ than generating broken wrappers.
+
+09/30/2003: beazley
+ Fixed [ 800012 ] ENTER macro from CORE/scope.h clashes with libc search.h.
+ Reported by Britton Leo Kerin.
+
+09/30/2003: beazley
+ Fixed [ 811518 ] Casting ints to doubles (w/ solution?)
+ Addresses a problem with overloading in the Perl module.
+ Reported by Gerald Dalley.
+
+09/28/2003: mkoeppe
+ [Guile with -scm option] Fix typo in generated code for
+ procedures-with-setters. Reported by John Lenz.
+
+09/26/2003: beazley
+ Fixed [ 812528 ] externs not correct when throw is in signature.
+ Reported by Joseph Winston.
+
+09/23/2003: cheetah (William Fulton)
+ SWIG was generating a number of symbols that didn't comply with
+ the ISO C/C++ standard, in particular ISO/IEC 14882:1998(E) 17.4.3.1.2
+ where double underscores are forbidden as well as symbols starting with
+ an underscore followed by an upper case letter. Most of these have
+ been rooted out. See new section added to internals.html development
+ manual 'Symbol Naming Guidelines for Generated C/C++ Code'.
+
+09/23/2003: cheetah (William Fulton)
+ Director typemap name changes:
+ inv => directorin
+ outv => directorout
+ argoutv => directorargout
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+09/19/2003: mrose (Mark Rose)
+ [Python] Director constructors now default to __disown = 0,
+ which is the intended behavior and fixes the director_finalizer
+ test case under python.
+
+09/12/2003: cheetah (William Fulton)
+ [C#] - Typemaps added for std::string and const std::string &.
+ - New delegate for creating a C# string given a char *. It
+ can be used by calling SWIG_csharp_string_callback as shown
+ in the std::string 'out' typemap. Useful if the return type is
+ mapped to a C# string and the calling function is responsible
+ for cleaning up memory as the C# garbage collector doesn't
+ free the memory created in C/C++ and then returned as a C# string.
+ - The exception delegates have moved into an inner class in the
+ intermediate class, thereby freeing up the static constructor.
+
+09/11/2003: beazley
+ (Internals)
+ Major refactoring of iteration over lists and hashes. The
+ DOH library now uses iterators. They work like this:
+
+ List *l = (some list);
+
+ Iterator i;
+ for (i = First(l); i.item; i = Next(i)) {
+ // i.item contains the actual list item.
+ // i.item is NULL at end of list
+ ...
+ }
+
+ Hash *h = (some hash);
+ Iterator j;
+ for (j = First(h); j.item; j = Next(j)) {
+ // j.item contains hash table item
+ // j.key contains hash table key
+ // Both j.item and j.key are NULL at end
+ ...
+ }
+
+ The old iteration functions Firstitem(), Nextitem(), Firstkey(),
+ and Nextkey() are gone.
+
+ The new iterators are simpler, result in better memory use,
+ and may be faster. Also, there are no longer any problems
+ iterating over the same list/hash in multiple places at
+ the same time. For example, this is fine:
+
+ Iterator i,j;
+ for (i = First(l); i.item; i = Next(i)) {
+ for (j = First(l); j.item; j = Next(j)) {
+ ...
+ }
+ }
+
+ (This never worked in previous versions).
+ *** POTENTIAL INCOMPATIBILITY ***. This will probably break
+ third party extensions to SWIG (or give them further encouragement
+ to join the SWIG CVS-tree :-).
+
+09/10/2003: mkoeppe (Matthias Koeppe)
+ [Guile] Fix memory leaks in the "list-vector.i" typemaps.
+
+09/09/2003: mkoeppe (Matthias Koeppe)
+ [Chicken] Use C_mk_bool rather than C_mkbool. This fixes
+ the wrapping of boolean values for Chicken 1.10 and newer.
+ Reported by Dave <[email protected]> / Felix Winkelmann
+
+09/05/2003: cheetah (William Fulton)
+ [Java] Directors implemented for Java. In summary this is a big new feature
+ which supports upcalls from C++ to Java. Code is generated to support C++
+ callbacks to call into Java and true polymorphic behaviour for Java classes
+ derived from C++ classes. See java.html for details. Contributed by
+ Scott Michel.
+
+09/05/2003: Tiger
+ Created contract example directory at /SWIG/Examples/contract
+ Added simple contract examples (simple_c & simple_cxx)
+ Modified contract module's output format
+
+ *** NEW FEATURE ***
+
+09/01/2003: cheetah (William Fulton)
+ Test-suite build improvements:
+ - Multiple build directories working for the test suite, so it is now
+ possible to run configure in multiple subdirectories and run the test
+ suite in each of these sub directories.
+ - 'make distclean' fixed so it doesn't bomb out on the Examples directory
+ when using multiple subdiretory builds. Required the following directories
+ to be moved:
+ Examples/GIFPlot/Perl -> Examples/GIFPlot/Perl5
+ Examples/GIFPlot/Php -> Examples/GIFPlot/Php4
+ These new directories used to be symbolic links to the old directory.
+ Also the Examples/test-suite/Perl symbolic link has been removed.
+ - Running the test-suite, other than from the root directory, say
+ in Examples/test-suite/python will now display all the code being
+ executed.
+ - The following 3 C# compilers are detected during configure and work with
+ the test-suite: Mono, Portable.NET and Microsoft.
+
+09/01/2003: Tiger
+ Added inheritance support for design by contract feature.
+
+09/01/2003: beazley
+ Fixed [ 794914 ] Wrong types in template specialization.
+ SWIG was not handling arguments correctly in template
+ partial specialization. For example,
+
+ template<class T> class Foo<T *> {
+ public:
+ T *blah();
+ };
+
+ %template(FooInt) Foo<int *>;
+
+ in this class, the return type of blah was set to
+ 'int **', but it should really be 'int *'. This has been
+ fixed, but it will affect all prior uses of partial
+ specialization.
+
+09/01/2003: beazley
+ Fixed [ 786394 ] Patch for generated perl code does not compile under RedHat9.
+ Reported by Scott Finneran.
+
+09/01/2003: beazley
+ Fixed [ 791579 ] (unsigned) long long handled incorrectly (Tcl).
+ This was an error in the Tcl typemaps.i file.
+ Reported by Kjell Wooding.
+
+09/01/2003: beazley
+ Fixed [ 797573 ] no way to rename classes coming from C structures.
+ This problem relates to renaming of anonymous structures with a
+ typedef. For example:
+
+ %rename(Bar) Foo;
+ typedef struct {
+ ...
+ } Foo;
+
+ Reported by Britton Leo Kerin.
+
+09/01/2003: beazley
+ Fixed [ 797576 ] -help seems to imply that only tcl-specific options exist.
+ Added a comment to alert user to other options.
+ Reported by Britton Leo Kerin.
+
+09/01/2003: beazley
+ Fixed [ 798205 ] Segfault in SWIG_ConvertPtr.
+ Reported by Prabhu Ramachandran.
+
+08/30/2003: mrose (Mark Rose)
+ Modified the director typemaps in python/std_complex.i to use the
+ new-style macro and conversion functions, which eliminated some
+ redundant code. Fixed a few bugs in these typemaps as well, although
+ more testing is needed.
+
+08/29/2003: mrose (Mark Rose)
+ Completed initial support for wrapping abstract classes with directors.
+ Constructor wrappers will be generated for abstract classes that have
+ directors, and instances of the director classes will be created regardless
+ of whether the proxy class has been subclassed in the target language.
+ No checks are made during construction to ensure that all pure virtual
+ methods are implemented in the target language. Instead, calls to
+ unimplemented methods will throw SWIG_DIRECTOR_PURE_VIRTUAL_EXCEPTION
+ exceptions in C++.
+
+ Integrated Prabhu Ramachandran's typemap patches, which provide director
+ typemap support for enums and std::size_t, and fix a couple bugs in the
+ director std::vector<> typemaps.
+
+08/29/2003: cheetah (William Fulton)
+ [C#] Implemented exception handling for throwing C# exceptions from C/C++ code.
+ A few delegate functions are available for calling which then throw the C#
+ exception. Use the SWIG_CSharpThrowException function from C/C++ typemaps.
+ See the generated wrapper code or csharphead.swg for all available exceptions.
+ Example:
+
+ SWIG_CSharpThrowException(SWIG_CSharpException, "exception description");
+
+ The 'throws' typemaps are also now implemented, so code is automatically
+ generated to convert any C++ exception into a C# System.Exception when the C++
+ method declares an exception specification such as:
+
+ int foo() throw(Bar);
+
+ Also any parameters that are references to a C++ class or a class passed by value
+ and are passed as a C# null will now throw a C# NullReferenceException.
+
+08/29/2003: cheetah (William Fulton)
+ [C#] Fix to match the calling convention of all pinvoke methods so that they
+ match the calling convention used by default in the C# 'static extern' declarations
+ (__stdcall is used on Windows).
+
+08/19/2003: cheetah (William Fulton)
+ [Java] Reworked std::string typemaps. Fixes a number of string in std namespace
+ problems. For example %template vector<string>. The templated class' get method
+ wasn't returning a Java String, but a SWIGTYPE_p_string. Reported
+ by Zach Baum.
+
+08/15/2003: beazley
+ Fixed [ 763522 ] 1.3.19 segfault in SwigType_add_pointer/DohInsertitem.
+ Related to problem with unnamed class handling in Perl module.
+
+08/15/2003: beazley
+ Fixed [ 763563 ] Missing indication of optional arguments.
+ Tcl module. Reported by Krzysztof Kozminski.
+
+08/15/2003: beazley
+ Fixed [ 787432 ] long param handled as int. Tcl module
+ now uses Tcl_GetLongFromObj to convert integer values.
+
+08/11/2003: beazley
+ Fixed [ 775989 ] numeric template parameters. There were
+ some errors in template expansion related to the use of
+ arrays where the array dimension was a template parameter.
+ It should work now. Reported by Bryan Green.
+
+08/10/2003: mrose (Mark Rose)
+ Added a director typemap (outv) for return by value and cleaned up up a few
+ of the commented director typemaps.
+
+08/10/2003: mrose (Mark Rose)
+ Fixed constructor generation for director classes to ignore private
+ constructors. Protected constructors are also ignored for now, pending
+ a solution to the problem of wrapping classes that only define protected
+ constructors.
+
+08/07/2003: cheetah (William Fulton)
+ New commandline option -outdir <dir> to specify where the language specific
+ files are to be generated. This is useful for target languages like Python,
+ Java etc which generate proxy files in the appropriate language.
+ This option does not apply to the C/C++ wrapper file.
+
+08/07/2003: cheetah (William Fulton)
+ On Windows the generated files (other than the _wrap.c or _wrap.cxx files)
+ were sometimes incorrectly being generated into the current directory unless
+ the input file used the Unix path separator. The Windows path separator
+ should now be used. Bug reported by Robert Davies.
+
+08/07/2003: beazley
+ Added array variable set typemap to Perl module.
+
+08/07/2003: beazley
+ Fixed [ 775677 ] Array init causes codegen bug..
+
+08/07/2003: beazley
+ Fixed [ 779062 ] Class"\n"::foo not supported. SWIG
+ should now correctly handle whitespace in between
+ namespace qualifiers. For example "A :: Foo :: Bar".
+
+07/31/2003: cheetah (William Fulton)
+ Fixes for parameters which are classes that are passed by value and have
+ a default value. A copy constructor for SwigValueWrapper is required
+ (SF #780056). Also fixed memory leak in these circumstances. These mods
+ also fix SF #780054.
+
+07/28/2003: beazley
+ Improved run-time error message for pointers in Python module.
+ Contributed by Zooko.
+
+07/10/2003: ballabio (Luigi Ballabio)
+ [Almost all languages] Wrappers for std::pair added.
+ Typemaps for Python, Ruby, Guile and MzScheme.
+
+07/01/2003: mkoeppe (Matthias Koeppe)
+ [Chicken] Handle the case of more than one argout typemap
+ per function.
+
+06/29/2003: cheetah (William Fulton)
+ [Java, C#] SF #670949 request. The destructor wrapper function name is now
+ configurable. A new attribute called methodname in the
+ javadestruct/javadestruct_derived (Java) or csdestruct/csdestruct_derived (C#)
+ typemaps specifies the method name. For example in Java the destructor is
+ wrapped by default with the delete method:
+
+ %typemap(javadestruct, methodname="delete") SWIGTYPE {...}
+
+06/27/2003: cheetah (William Fulton)
+ [Java, C#] The throws attribute for adding exception classes to the throws
+ clause also now works with the following typemaps:
+ newfree
+ javain, javaout (Java)
+ csin, csout (C#)
+
+ For example, the 'AnException' will be added to the throws clause in the
+ proxy function:
+
+ %typemap(javaout, throws="AnException") int {
+ int returnValue=$jnicall;
+ if (returnValue==0) throw new AnException("Value must not be zero");
+ return returnValue;
+ }
+
+06/25/2003: mrose (Mark Rose)
+ [Python] Director typemap marshalling checks for null pointers when
+ walking the parameter list instead of relying soley on the parameter
+ count. Cures a segfault that occurred for multiple argument inv typemaps.
+ Someone with more Swig experience should probably review this code.
+
+06/24/2003: mkoeppe (Matthias Koeppe)
+ [Chicken] Don't emit calls to "C_check_for_interrupt",
+ which may result in an endless loop. Patch by [email protected].
+
+06/20/2003: cheetah (William Fulton)
+ [C#] Finalizers now use destructor syntax as the override which was used in
+ the Finalize method is not in the ECMA standards, spotted by the MS compiler.
+
+06/10/2003: cheetah (William Fulton)
+ [C#] A number of changes have been made to remove the Java naming
+ that was used in the C# module.
+
+ Typemap name changes:
+ jni -> ctype
+ jtype -> imtype
+ jstype -> cstype
+ javain -> csin
+ javaout -> csout
+ javainterfaces -> csinterfaces
+ javabase -> csbase
+ javaclassmodifiers -> csclassmodifiers
+ javacode -> cscode
+ javaimports -> csimports
+ javaptrconstructormodifiers -> csptrconstructormodifiers
+ javagetcptr -> csgetcptr
+ javafinalize -> csfinalize
+
+ Feature name changes:
+ javaconst -> csconst
+ javamethodmodifiers -> csmethodmodifiers
+
+ Pragma changes:
+ pragma(java) -> pragma(csharp)
+ jniclassbase -> imclassbase
+ jniclassclassmodifiers -> imclassclassmodifiers
+ jniclasscode -> imclasscode
+ jniclassimports -> imclassimports
+ jniclassinterfaces -> imclassinterfaces
+
+ Special variable name changes:
+ $javaclassname -> $csclassname
+ $javainput -> $csinput
+ $jnicall -> $imcall
+
+ This will break SWIG interface files that use these typemaps, features
+ and pragmas. Please update your code or use macros for backwards
+ compatibility.
+
+ *** POTENTIAL INCOMPATIBILITY FOR C# MODULE ***
+
+06/10/2003: mkoeppe (Matthias Koeppe)
+ [MzScheme] Applied MzScheme module updates contributed by
+ John Lenz <[email protected]>.
+
+ - Updated mzscheme to use SWIG's common runtime type
+ system from common.swg.
+
+ - The Lib/mzscheme directory has been reorganized to
+ standardize names across the language modules:
+ mzscheme.i was moved to mzscheme.swg, mzscheme.swg and
+ mzschemedec.swg have been removed, mzrun.swg (which
+ contains the runtime code) has been added.
+
+ - The swig_proxy structure was renamed to swig_mz_proxy.
+ swig_mz_proxy now contains a pointer to a swig_type_info
+ structure.
+
+ - Added varin and varout typemaps for SWIGTYPE [] and
+ SWIGTYPE &.
+
+ - Garbage collection by calling scheme_add_finalizer() has
+ been added.
+
+ *** NEW FEATURE [MzScheme] ***
+
+06/10/2003: cheetah (William Fulton)
+ [Java] New typemaps: javadestruct and javadestruct_derived
+ for the C++ destructor wrapper. The javadestruct version gets used by
+ classes at the top of an inheritance chain and the javadestruct_derived
+ version gets used by other classes.
+
+ [C#] cildispose and cildisposeoverride typemaps replaced by
+ csdestruct and csdestruct_derived typemaps. The delete()
+ method has been removed and its functionality put into these
+ typemaps designed for the Dispose() method.
+
+ - New typemaps csinterfaces and csinterfaces_derived replace
+ the javainterfaces typemap. Also fixes the peculiarity of all classes
+ in an inheritance chain individually deriving from the IDisposable
+ interface.
+
+ - New typemap csfinalize for finalizers. C++ destructors are now called
+ by garbage collector during finalization. Problem reported by
+ Andreas Sch�rk.
+
+06/10/2003: Tiger
+ Modified contract code for error message output.
+ Contract code can now print out simple error message.
+ Modified contract code to prepare for inheritance
+
+06/03/2003: mkoeppe
+ [Guile] Applied Guile module updates contributed by
+ John Lenz <[email protected]>.
+
+ - SWIG currently uses Guile's gh_ API, which is marked as
+ deprecated in Guile 1.6 and will be removed in Guile
+ 1.9. This change introduces a command-line flag "-scm"
+ which causes SWIG to generate wrappers that use Guile's
+ SCM API instead; this requires Guile >= 1.6.
+
+ - The Lib/guile directory has been reorganized to
+ standardize names across language modules: guiledec.swg
+ and guile.swg have been moved into guile_gh_run.swg,
+ guile.i has been moved to guile_gh.swg, guile_scm.swg
+ and guile_scm_run.swg which contain the SCM API stuff
+ have been added
+
+ - ghinterface.i, which contains the defines from the gh_
+ functions to the scm_functions has been added
+
+ - The API for dealing with pointer objects is now
+ SWIG_ConvertPtr, SWIG_MustGetPtr, SWIG_NewPointerObj.
+
+ - Added varin and varout typemaps for SWIGTYPE [] and SWIGTYPE &
+
+ - Garbage collection has been added.
+
+ *** NEW FEATURE [Guile] ***
+
+06/01/2003: cheetah (William Fulton)
+ Dimensionless arrays such as
+
+ int foo[] = {1, 2};
+ extern int bar[];
+
+ produce a warning that the variable is read-only. Depending on the target
+ language, this used to cause compile errors or generate a setter that
+ generated a runtime error. A setter cannot be automatically generated
+ because the array size cannot be determined by SWIG. A varin, globalin
+ or memberin typemap (depending on the target language) must be written
+ by the user.
+
+05/29/2003: beazley
+ Refinement to default typemap matching and arrays. When an
+ array is declared like this:
+
+ int foo[4];
+
+ The default typemap now resolves to
+
+ SWIGTYPE [ANY]
+
+ If no match is found for that, it then resolves to
+
+ SWIGTYPE []
+
+ If no array dimension is specified in the original declaration,
+ the SWIGTYPE [] is used right away.
+
+ Note: This change has been made to resolve problems related to
+ arrays with and without dimensions. For example, sometimes SWIG
+ was generating setter functions for array variables with no dimensions
+ (an error). Likewise, SWIG sometimes made arrays with dimensions
+ read-only (also an error). This fixes the arrays_global test
+ problem.
+
+05/28/2003: beazley
+ Fixed subtle type handling bug with references and pointers.
+ If you had functions like this:
+
+ typedef Foo Bar;
+
+ Foo *func1();
+ void func2(Bar &x);
+
+ Then func2() wouldn't accept objects returned by func1()
+ because of a type error. It should work now.
+ Reported by Brian Yang.
+
+05/21/2003: cheetah (William Fulton)
+ Fixes to some of the Visual C++ example project files which would not
+ work with spaces in the paths held in the environment variables used to
+ point to the target language's library / include directory.
+ SF bug #740769
+
+05/21/2003: songyanf (Tiger)
+ Added -contracts option.
+ First try of the idea of "Wrap by Contract":
+ build up realiable cross-language module by wrapping with SWIG.
+ Implemented basic assertion
+ (preassertion & postassertion & invariant)
+ for simple C/C++ functions.
+
+ Current format of contracts are:
+ %contract class_name :: func_name (paras...) {
+ require:
+ boolean exprs;
+ exprs;
+ ensure:
+ boolean expr;
+ exprs;
+ invariant:
+ boolean expr;
+ exprs;
+ }
+
+ *** NEW FEATURE ***
+
+05/19/2003: cheetah (William Fulton)
+ Build tweaks. There were a few preprocessor definitions which were
+ specified in the Makefile for passing on the commandline when compiling.
+ These are now all defined in swigconfig.h. Autoconf doesn't normally
+ allow installation directories to be defined in this config header file,
+ but an autoconf archive macro enables this. This macro along with future
+ autoconf macros are going to be put in the Tools/config directory.
+
+ 'swig -version' now reports the target build platform.
+
+05/11/2003: cheetah (William Fulton)
+ [C# and Java] Fix to the following typemaps:
+
+ javabase, javainterfaces, javaimports, javaclassmodifiers,
+ javaptrconstructormodifiers, javafinalize, javagetcptr & javacode.
+
+ These are the typemaps for modifying/generating proxy classes.
+ Previously the typemaps would use the proxy class name and not the
+ C++ type, which was inconsistent with all other typemaps.
+
+ In most circumstances the proxy class name and the C++ class name/type
+ is the same except for classes in namespace, templated classes etc. so
+ this shouldn't affect most cases.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA and C# MODULES ***
+
+05/09/2003: cheetah (William Fulton)
+ Visual C++ Project files have been added so that the runtime libraries
+ can be built on Windows (for Tcl, Perl, Python and Ruby).
+
+05/01/2003: beazley
+ Fixed problem with return by value, const, and private constructors.
+ For example:
+
+ class B {
+ private:
+ B();
+ public:
+ B(const B&);
+ };
+
+ class A {
+ ...
+ const B returnB() const;
+ ...
+ };
+
+ Problem and patch suggestion reported by Bill Hoffman.
+
+04/29/2003: cheetah (William Fulton)
+ Build changes:
+ - Single autoconf invocation - autoconf in the Tools directory has gone.
+
+ - Libtool bootstrapped when running autogen.sh. This requires anyone
+ using the cvs version of SWIG to have libtool installed on their
+ machine. Suggest version 1.4.2 or higher, preferably the latest - 1.5.
+
+ - Automake is now used to build the runtime libraries in conjunction
+ with libtool.
+
+ - Runtime libraries are now successfully built as DLLs on Cygwin.
+
+ - Skipping languages is no longer just determined in the top level
+ makefile but in configure.in. This info is used for building
+ the runtime libraries and for running the examples and test-suite.
+
+ - These changes have fixed multiple build directory builds, that is
+ building from directories other than the top level directory.
+ Installation from multiple build directories also working. An initial
+ configure in the top level directory is no longer needed as described
+ in 04/02/2003 entry. A 'make distclean' will be needed before building
+ in a directory other than the top level directory if the autotools
+ have been run from this top level directory at some point, but
+ autoconf will tell you this. Note that 'make check' only works from
+ the top level directory at the moment.
+
+04/28/2003: beazley
+ Fixed [ 723471 ] Wrapper_print() fails with preprocessor directives.
+
+04/28/2003: beazley
+ Minor refinement of const static member variable handling
+ described in CHANGES 08/11/2002. Previously, SWIG merely
+ checked to see if there was an initializer in the declaration.
+ Now, SWIG additionally checks to make sure the static member
+ is const.
+
+04/25/2003: ljohnson (Lyle Johnson)
+ [Ruby] Added a kind of limited support for multiple inheritance,
+ activated using the -minherit command-line option. I've also updated
+ the "C++ Inheritance" section of the Ruby documentation to discuss
+ how this works, and its limitations. Also also modified the minherit.i
+ test case to run against this.
+
+04/25/2003: ljohnson (Lyle Johnson)
+ [Ruby] Added the -globalmodule command-line option for the Ruby
+ module, for wrapping stuff into the global module (Kernel) instead
+ of a nested module. Updated documentation accordingly.
+
+04/23/2003: mrose (Mark Rose)
+ Fixed symname error in director calls to Python methods
+ that extend C++ operators.
+
+ Stopped director destructor wrappers from calling __set_up,
+ which was leaving the director flag in an inconsistent state.
+
+04/23/2003: beazley
+ Fixed problem with namespace resolution and nested namespaces.
+ Reported by Alfred Lorber (and Marcelo Matus).
+
+04/16/2003: cheetah (William Fulton)
+ Patch for Java examples and test-suite to run on Mac OS X.
+
+04/15/2003: ljohnson (Lyle Johnson)
+ [Ruby] Incorporated Nobu Nakada's patches for supporting the Ruby
+ 1.8 allocation framework.
+
+04/15/2003: ljohnson (Lyle Johnson)
+ [Ruby] Replaced all uses of the deprecated STR2CSTR() macro with the
+ safer StringValuePtr() macro. For more information, see ruby-talk:67059
+ and follow-ups to that post.
+
+04/11/2003: beazley
+ Fixed problem with preprocessor macro expansion. For example:
+
+ #define min(x,y) ((x) < (y)) ? (x) : (y)
+ int f(int min);
+
+ Reported by Sebastien Recio.
+
+04/10/2003: cheetah (William Fulton)
+ [Java] Added a runtime check to typemaps in arrays_java.i library to check
+ that the Java array passed in is the same size as the C array and throw an
+ exception if not.
+
+ Also fix to use delete instead of free for arrays created using new.
+
+04/07/2003: cheetah (William Fulton)
+ Remove GCC3 warning when compiling the examples and test-suite:
+
+ cc1plus: warning: changing search order for system directory "/usr/include"
+ cc1plus: warning: as it has already been specified as a non-system directory
+
+ See SF patch #715531 submitted by Gerald Williams
+
+04/03/2003: cheetah (William Fulton)
+ [C#] Improved wrapping of enums and constants. These were previously
+ wrapped as C# variables rather than constants. Either these are wrapped
+ as readonly (runtime) constants or compile time constants, depending on
+ the %javaconst directive (The directive is likely to change name soon).
+ For example wrapping:
+ %javaconst(0);
+ #define ABC 22
+ %javaconst(1) XYZ;
+ #define XYZ 33
+ is now:
+ public static readonly int ABC = examplePINVOKE.get_ABC();
+ public const int XYZ = 33;
+
+04/03/2003: cheetah (William Fulton)
+ [Java] Global constants and enums are put in their own interface called
+ xxxConstants, where xxx is the module name. This is an improvement as
+ it is possible to derive (implement) a Java class from the xxxConstants
+ interface to improve the syntax; namely when wrapping:
+ enum {ONE=1, TWO, THREE};
+ accessing these from a Java class implementing xxxConstants is neater:
+ int number = ONE;
+ than the previous:
+ int number = xxx.ONE;
+
+ Patch submitted by Dave Dribin.
+
+04/02/2003: cheetah (William Fulton)
+ Build improvements for multiple builds. This allows one to build
+ the SWIG executable and runtime libraries for different platforms/compilers
+ etc by running configure in different directories. This isn't 100% just
+ yet and won't be until libtool is better configured... a 'configure' and
+ 'make distclean' needs to be run in the root directory before it all works.
+ For example:
+ $ ./configure
+ $ make distclean
+ $ mkdir config1; cd config1; ../configure CC=gcc CXX=g++; make; cd ..
+ $ mkdir config2; cd config2; ../configure CC=cc CXX=c++; make; cd ..
+
+ To be improved. A 'make check' does not work yet either.
+
+04/01/2003: beazley
+ Fixed template partial specialization argument expansion bug.
+ This showed up when trying to use std_vector.i with vectors
+ of pointers.
+
+03/31/2003: cheetah (William Fulton)
+ Fix for parallel make builds of SWIG, for example
+ make -j 4
+ Build failure reported by Bill Clarke.
+
+03/28/2003: beazley
+ Released 1.3.19.
+
+
+
+Version 1.3.19 (March 28, 2003)
+===============================
+
+03/28/2003: beazley
+ Variety of minor bug fixes to the 1.3.18 release including:
+
+ - Segmentation fault with %extend directive.
+ - Typemap variable substitution bug.
+ - Expression evaluation bug.
+ - Large memory leak with template expansion.
+
+Version 1.3.18 (March 23, 2003)
+===============================
+
+03/21/2003: beazley
+ Fixed two problems with the %extend directive, overloading, and
+ template expansion. See the 'template_extend_overload' and
+ 'template_extend_overload_2' tests in Examples/test-suite for
+ details.
+
+03/20/2003: cheetah (William Fulton)
+ [C#] Added some typemaps as suggested by Andreas Schoerk for handling
+ parameters that are passed as pointers or by reference. These have
+ been put in typemaps.i.
+
+03/20/2003: beazley
+ Fixed a C++ scoping bug related to code like this:
+
+ class Foo {
+ public:
+ int Foo::bar();
+ };
+
+ Previously, SWIG just tossed out the Foo::bar() declaration. Now,
+ the declaration is wrapped provided that the prefix is exactly the
+ same as the current scope (including any enclosing namespaces).
+ Reported by Bruce Lowery.
+
+03/20/2003: beazley
+ Incorporated [ 696516 ] Enabling exception processing for data member access.
+ In some compilers, attribute access can generate exceptions. However,
+ SWIG ordinarily assumes that no exceptions will be raised. To disable this,
+ use the %feature("allowexcept"). For example:
+
+ %feature("allowexcept") Foo::x;
+ ...
+ class Foo {
+ public:
+ int x; /* Exception handling enabled */
+ ...
+ };
+
+ Patch contributed by Yakov Markovitch.
+
+03/20/2003: beazley
+ Incorporated Patch. [ 701860 ] Improve Performance (python proxies).
+ Gives a performance boost to proxy class code and the management of the
+ .this and .thisown attributes. Contributed by Mike Romberg.
+
+03/19/2003: cheetah (William Fulton)
+ [C# and Java] Added missing vararg support.
+
+03/18/2003: mrose (Mark Rose)
+ Removed code related to tagging individual methods for directors.
+ The concept of having directors for some but not all virtual methods
+ of a class is deeply flawed. The %feature("nodirector") tag is also
+ gone.
+
+ Directors are off by default. To enable them for a class, issue
+ %feature("director") classname; which will create director methods
+ for every virtual method in the hierarchy of the class.
+
+03/17/2003: beazley
+ Fixed a subtle problem with passing arguments of type function. For
+ example:
+
+ int foo(int x(int, int));
+
+ or
+
+ typedef int binop_t(int, int);
+ int foo(binop_t x);
+
+ In old versions, this would produce code that wouldn't compile. Now,
+ SWIG merely adds an extra pointer, making these declarations the same
+ as:
+
+ int foo(int (*x)(int, int));
+
+ typedef int binop_t(int, int);
+ int foo(binop_t *x);
+
+ Reported by Garth Bushell.
+
+03/17/2003: mrose (Mark Rose)
+ Fixed the return statement for director base class calls that have no
+ return value.
+
+03/15/2003: beazley
+ Fixed a problem with const smart-pointer wrapping. For example:
+
+ class Foo {
+ public:
+ int x;
+ void bar() const;
+ void spam();
+ };
+
+ class Blah {
+ ...
+ const Foo *operator->();
+ ...
+ };
+
+ In this case, only "x" and "bar" are visible from Blah (since application
+ of spam violates constness). Moreover, access to "x" is read-only.
+
+03/15/2003: mrose (Mark Rose)
+ Cleaned up two signed versus unsigned comparisons in python/std_vector.i.
+
+03/15/2003: cheetah (William Fulton)
+ [C#] Global variables are wrapped using properties instead of get and set methods.
+ Member variable wrapping bug fixes, for example wrapping pointers work now.
+ Typemaps are used for all variable wrapping to generate the property code.
+
+03/13/2003: mrose (Mark Rose)
+ Fixed a bug in the virtual method unrolling for directors.
+ The order of unrolling is now from base to derived, to ensure
+ that the most derived implementation of a director method is
+ found.
+
+ Director methods for pure virtual methods now throw
+ DIRECTOR_PURE_VIRTUAL_EXCEPTION if _up is set.
+
+03/12/2003: cheetah (William Fulton)
+ [C#] Polymorphism fix: virtual functions now use the appropriate
+ keyword in the C# proxy class, virtual or override.
+ Some 'using System;' statement fixes needed by the Mono compiler.
+
+03/11/2003: beazley
+ Fixed subtle bug in the application of SwigValueWrapper<> to
+ template classes with default constructors. Reported by
+ Bruce Lowery.
+
+03/11/2003: beazley
+ The $descriptor(type) variable is now expanded in code supplied to
+ %extend. This is useful for certain kinds of advanced wrapping
+ (especially container classes).
+
+03/11/2003: luigi
+ Support for std::map.
+ (a) Integration with scripting language (a la std::vector) for
+ Python, Ruby, MzScheme, and Guile;
+ (b) Simple wrapper for other languages
+
+03/10/2003: beazley
+ Fixed problem with escape sequences in string and character constants. SWIG
+ wasn't parsing certain octal codes correctly.
+
+03/07/2003: beazley
+ Fixed a variety of subtle preprocessor problems reported by
+ Sebastien Recio.
+
+ (a) Empty preprocessor values no longer generate "bad constant
+ value" errors. For example:
+
+ #define FOO
+ #define FOO BAR
+
+ (b) Macro names can now span multiple lines (technically valid,
+ although questionable practice). For example:
+
+ #define A_LONG_MACRO_\
+ NAME 42
+
+ (c) Whitespace is no longer required before certain macro values.
+ For example:
+
+ #define FOO"Hello"
+ #define BAR\
+ "Hello"
+
+03/07/2003: ljohnson (Lyle Johnson)
+ [Ruby] Added missing long long and unsigned long long typemaps
+ in the Lib/ruby/typemaps.i library file.
+
+03/07/2003: mrose (Mark Rose)
+ Added Examples/python/callback to demostrate how directors can
+ be used to implement callbacks in Python
+ Added Examples/python/extend to demonstrate virtual method
+ calls from C++ to Python (really the same as the callback
+ example, just a different context).
+ Added four tests for very basic director functionality. These
+ have runtime tests under python.
+ The Python module now emits #define SWIG_DIRECTORS near the
+ top of the output file if directors are enabled. This is useful
+ for disabling parts of tests in target languages that don't
+ support directors.
+
+03/06/2003: mrose (Mark Rose)
+ Added a section to Doc/Manual/Python.html on cross language
+ polymorphism (directors).
+
+03/06/2003: mrose (Mark Rose)
+ The short-lived "-fdirectors" command line option has been
+ removed. To enable directors, instead use the extended %module
+ directive as follows:
+
+ %module(directors="1") modulename
+
+03/06/2003: cheetah (William Fulton)
+ The long long typemaps have been rewritten so that they can be more
+ easily used with non ISO compilers, like Visual C++. For example
+ if you are wrapping the Windows 64 bit type __int64 the long long
+ typemaps can be used with %apply:
+
+ %apply long long { __int64 };
+ __int64 value1(__int64 x);
+
+ __int64 will now appear in the generated code instead of long long.
+
+03/06/2003: beazley
+ *** DEVELOPER CHANGE ***
+ Swig module mutation has been changed slightly. When a language
+ class method wants to save node attributes, it now uses one of the
+ following functions:
+
+ Swig_require()
+ Swig_save()
+
+ The first argument to these functions is a namespace in which
+ saved attributes are placed. For example,this code
+
+ Node *n;
+ Swig_save("cDeclaration",n,"type","parms","name",NIL);
+
+ saves the attributes as "cDeclaration:type", "cDeclaration:parms",
+ and so forth. If necessary, a language module can refer to
+ old values by using this special namespace qualifier.
+
+ In addition to this, a special attribute "view" contains the name
+ of the last namespace used to save attributes. In the above
+ example, "view" would have the value "cDeclaration". The value
+ of "cDeclaration:view" would have the previous view and so forth.
+
+ Swig_restore(n) restores a node to the state before the last
+ Swig_require() or Swig_save() call.
+
+ Note: This change makes it easier for language modules to refer
+ to old values of attributes.
+
+
+03/06/2003: mrose (Mark Rose)
+ Merged the cross-language polymorphism patch. When enabled, C++
+ "proxy" classes (called directors) are generated for each specified
+ C++ class. Directors pass method calls from C++ to Python, similar
+ to the way the usual proxy (shadow) classes pass method calls from
+ Python to C++. Together, these two types of proxies allow C++
+ classes that are extended in Python to behave just like ordinary
+ C++ classes and be used in C++ like native objects.
+
+ This feature is still very experimental and is disabled by default.
+ To enable director support, specify '-fdirectors' on the SWIG command
+ line or in the SWIG_FEATURES environment variable. In the interface
+ file, add %feature("director") to generate directors for all classes
+ that have virtual methods.
+
+ See http://stm.lbl.gov/~tm2/swig/ProxyDoc.html for more details.
+
+
+03/03/2003: beazley
+ Fixed a small glitch in typemap local variable replacement. If you had
+ a typemap like this:
+
+ %typemap(in) type ($1_type temp) {
+ ...
+ temp = ...;
+ ...
+ }
+
+ and no occurrence of "$1_type" appeared in the body, then the local
+ variable type wouldn't be substituted.
+
+03/03/2003: cheetah (William Fulton)
+ [C#] New version of the CSharp module which is typemap based.
+ It also uses ECMA C# and no longer uses Microsoft Visual C++.NET
+ glue. This means that it will work on non-Windows platforms.
+ Contributed by Neil Cawse.
+
+02/27/2003: beazley
+ Fixed [ 653548 ] error parsing casting operator definition.
+ SWIG now ignores casting operators declared outside of a class.
+ For example:
+
+ inline A::operator char *() { ... }
+
+ Bug reported by Martin Casado.
+
+02/27/2003: beazley
+ Added support for anonymous bit-fields. For example:
+
+ struct Foo {
+ int x : 4;
+ int : 4;
+ int y : 8;
+ };
+
+ Anonymous bit-fields are ignored by SWIG. Problem
+ reported by Franz H�pfinger.
+
+02/26/2003: cheetah (William Fulton)
+ [Java] Better typemaps in the Examples/java/typemap example and also
+ fixes subtle bug when using the StringBuffer typemaps more than once.
+
+02/26/2003: beazley
+ Fixed [ 642112 ] Constants char bug.
+
+02/26/2003: beazley
+ Fixed [ 675337 ] Partial template specialization not entirely working.
+ There was a subtle problem related to the naming and ordering of
+ template partial specialization arguments. Matching worked okay,
+ the resulting templates weren't expanded correctly.
+
+02/25/2003: beazley
+ Fixed problem with parsing (and generating code) for
+ references to arrays. For example:
+
+ int foo(int (&x)[10]);
+
+02/25/2003: beazley
+ Fixed [ 635347 ] Compilation warning from libpy.c.
+ Reported by Daniel L. Rall.
+
+02/25/2003: beazley
+ Fixed a subtle problem with virtual method implementation
+ checking and typedef.
+
+ typedef int *intptr;
+
+ struct A {
+ virtual int *foo() = 0;
+ };
+ struct B : public A {
+ virtual intptr foo() { };
+ };
+
+ SWIG was treating these declarations as different even though
+ they are the same (via typedef).
+
+02/25/2003: ljohnson (Lyle Johnson)
+ [Ruby] Added range checking for the NUM2USHRT macro, per [ 675353 ].
+
+02/24/2003: beazley
+ Fixed a subtle problem with the code that determined if a class is abstract
+ and can be instantiated. If you had classes like this:
+
+ struct A {
+ virtual int foo(int) = 0;
+ };
+ struct B : virtual A {
+ virtual int foo(int);
+ };
+
+ struct C : virtual A {
+ };
+
+ /* Note order of base classes */
+ struct D : B, C { }; /* Ok */
+ struct E : C, B { }; /* Broken */
+
+ then SWIG determined that it could instantiate D(), but not E().
+ This inconsistency arose from the depth-first search of the
+ inheritance hierarchy to locate the implementations of virtual
+ methods. This problem should now be fixed---SWIG will attempt
+ to locate any valid implementation of a virtual method by
+ traversing over the entire hierarchy.
+
+02/22/2003: cheetah (William Fulton)
+ [Java] Fix for using enum typemaps. The Java final static variable type
+ can be set using the jstype typemap, enabling enums to be mapped to
+ something other than int. Bug reported by Heiner Petith.
+
+02/21/2003: songyanf (Tiger)
+ Added CSharp (C#) module prototype
+ i.e. csharp.cxx & csharp.h at Source/Modules/.
+ They are for test usage only now and need improvement.
+ The interface also need to be modified.
+
+ *** NEW FEATURE ***
+
+02/20/2003: songyanf (Tiger)
+ Fixed problem with typedef with -fvirtual.
+ Similar as beazley's modification today.
+
+02/20/2003: beazley
+ Added support for gcc-style variadic preprocessor macros.
+ Patch [ 623258 ] GCC-style vararg macro support.
+ Contributed by Joe Mason.
+
+02/20/2003: beazley
+ Fixed [ 605162 ] Typemap local variables.
+ Reported by Lyle Johnson.
+
+02/20/2003: beazley
+ Fixed problem with abstract classes and typedef. For example:
+
+ class Foo {
+ public:
+ virtual void foo(int x) = 0;
+ };
+
+ typedef int Integer;
+ class Bar : public Foo {
+ public:
+ virtual void foo(Integer x);
+ };
+
+ SWIG was getting confused about the latter method---making Bar
+ abstract. Reported by Marcelo Matus.
+
+02/19/2003: cheetah (William Fulton)
+ [Java] %javaconst(flag) can also be used on enums as well as constants.
+ This feature enables true Java compiler constants so that they can be
+ used in Java switch statements. Thanks to Heiner Petith for patches.
+
+02/19/2003: songyanf (Tiger)
+ Modified -fcompact feature to deal with PP lines
+
+02/18/2003: beazley
+ Fixed [ 689040 ] Missing return value in std_vector.i.
+ Reported by Robert H. de Vries.
+
+02/18/2003: beazley
+ Fixed a few evil scoping problems with templates, namespaces, and the
+ %extend directive. Problem reported by Luigi Ballabio.
+
+
+02/18/2003: cheetah (William Fulton)
+ [Ruby] Improved support for Visual C++ and other native Windows compilers.
+ It is no longer necessary to specify "/EXPORT:Init_<module>", where <module> is the
+ swig module name when linking using these native Windows compilers.
+
+02/15/2003: songyanf (Tiger)
+ Added -fvirtual option.
+ Reduce the lines and size of the wrapper file
+ by omitting redifined virtual function in children classes.
+
+ Modified -compact option to -fcompact option
+
+ Added -small option.
+ -small = -fvirtual -fcompact
+ And it can be extended by future feature options,
+ which are used to reduce wrapper file szie.
+
+ Added SWIG_FEATURES environment variable check.
+ To dynamically set the feature options such as -fcompact & -fvirtual
+ *** NEW FEATURE ***
+
+02/13/2003: lenz
+ Updated Doc/Manual/Perl5.html to talk about C++ compile problems
+ configure.in now checks for PERL5_CCFLAGS
+ Runtime/Makefile.in and Example/Makefile.in now use PERL5_CCFLAGS
+ Added Lib/perl5/noembed.h which contains all the known macro conflicts
+
+02/12/2003: beazley
+ Fixed [ 685410 ] C++ Explicit template instantiation causes SWIG to exit.
+ Fixes a syntax error with declarations similar to this:
+
+ template class std::vector<int>;
+
+ SWIG now ignores the instantiation and generates a warning message.
+ We might do more later. Reported by Thomas Williamson.
+
+02/11/2003: cheetah (William Fulton)
+ Rewrote bool typemaps to remove performance warning for compiling generated code
+ under Visual C++.
+
+02/11/2003: cheetah (William Fulton)
+ Fix for wrapping reference variables (const non-primitive and all non-const types)
+ for example:
+ int& i;
+ Class& c;
+ const Class& c;
+
+02/11/2003: beazley
+ Fixed more very subtle preprocessor corner cases related to recursive
+ macro expansion. For example:
+
+ #define cat(x,y) x ## y
+
+ cat(cat(1,2),3) // Produces: cat(1,2)3
+
+ #define xcat(x,y) cat(x,y)
+
+ xcat(xcat(1,2),3) // Produces 123
+
+ See K&R, 2nd Ed. p. 231.
+
+02/10/2003: cheetah (William Fulton)
+ Fixed [ 683882 ] - patch submitted by F. Postma for SWIG to compile on HP-UX.
+
+02/10/2003: beazley
+ Fixed subtle preprocessor argument expansion bug. Reported by Marcelo Matus.
+
+02/10/2003: songyanf
+ Added -compact option.
+ Reduce the lines and size of the wrapper file
+ by omitting comments and combining short lines.
+ *** NEW FEATURE ***
+
+02/07/2003: beazley
+ Fixed [ 651355 ] Syntax error with cstring.i
+ Reported by Omri Barel.
+
+02/07/2003: beazley
+ Fixed [ 663632 ] incompatibility with standard cpp.
+ This is a refinement that fixes this problem:
+
+ // Some macro with an argument
+ #define FOO(x) x
+
+ int FOO; /* Not a macro---no arguments */
+
+02/05/2003: beazley
+ Fixed [ 675491 ] parse error with global namespace qualification.
+ Submitted by Jeremy Yallop.
+
+02/04/2003: beazley
+ Fixed bug in varargs processing introduced by the numinputs typemap parameter.
+
+01/08/2003: ttn
+ [xml] Fix string-replacement ordering buglet.
+ Thanks to Gary Herron.
+
+12/23/2002: cheetah (William Fulton)
+ Further build changes:
+ - The SWIG executable is now built using a single Makefile.
+ - This makefile is generated by Automake (Source/Makefile.am).
+ - Dependency tracking and tags support are in this makefile.
+ - Automake 1.7.2 and Autoconf 2.54 minimum versions are needed to build SWIG from CVS.
+ - Running ./autogen.sh now installs Autoconf/Automake support files into
+ Tools/config and these files are no longer stored in CVS.
+ - Bug fixes in 'make install' for systems using .exe executable extension and
+ ./configure --with-release-suffix=whatever
+
+12/16/2002: cheetah (William Fulton)
+ More build changes:
+ - Autoconf's AC_CANONICAL_HOST replaces proprietary approach for detecting build host.
+ - Autoconf support files moved to Tools/config.
+
+12/16/2002: cheetah (William Fulton)
+ Modifications to run on MacOS, submitted by Bernard Desgraupes.
+ Mainly ensuring generated files are output in the appropriate directory for
+ some modules.
+
+12/11/2002: cheetah (William Fulton)
+ Various build modifications and bug fixes:
+ - Simplification of version string. Use autoconf's PACKAGE_VERSION instead.
+ - Build time removed from SWIG version.
+ - Using standard autoconf config header generation.
+ - Updated old autoconf macros as reported by autoupdate.
+ - Removed $prefix in autoconf from search paths as autoconf won't expand them.
+ - Subtle bug fix where 'make prefix=/somewhere; make clean; make prefix=/somwhere/else'
+ produced an executable using the incorrect library directories.
+ - Added -ldflags commandline option for MzScheme, Ocaml, Pike and PHP.
+ - Fixed reporting of compiler used when using -version commandline option.
+ - SWIG web address added to -version commandline option.
+
+12/11/2002: beazley
+ Minor fix to Tcl dynamic cast typemaps. Reported by
+ Kristopher Blom.
+
+12/10/2002: beazley
+ Fixed subtle template argument replace bug. Reported by
+ Chris Flatley.
+
+12/10/2002: beazley
+ Reverted CHANGES 09/03/2002, preprocessor argument evaluation. Arguments
+ are not evaluated during collection, K&R, p. 230.
+
+12/06/2002: beazley
+ Fixed [ 649022 ] Compilation problems with KAI/KCC
+
+12/02/2002: beazley
+ SWIG 'rel-1-3' CVS branch merged back into the main branch.
+
+
+Version 1.3.17 (November 22, 2002)
+==================================
+
+11/19/2002: beazley
+ Fixed [ 613922 ] preprocessor errors with HAVE_LONG_LONG.
+
+11/19/2002: beazley
+ Fixed [ 615480 ] mzscheme SWIG_MustGetPtr_.
+
+11/19/2002: beazley
+ Fixed [ 635119 ] SWIG_croak causes compiler warning.
+
+11/16/2002: cheetah (William Fulton)
+ [Java] Added typemaps for pointers to class members.
+
+11/15/2002: cheetah (William Fulton)
+ [Java] Bug fix: Overloaded C++ functions which cannot be overloaded in Java
+ once again issue a warning.
+
+11/14/2002: cheetah (William Fulton)
+ [Java] Handling of NULL pointers is improved. A java null object will now
+ be translated to and from a NULL C/C++ pointer by default. Previously when
+ wrapping:
+
+ class SomeClass {...};
+ void foo(SomeClass *s);
+
+ and it was called from Java with null:
+
+ modulename.foo(null)
+
+ a Java NullPointerException was thrown. Extra typemaps had to be written in
+ order to obtain a NULL pointer to pass to functions like this one. Now the
+ default wrapping will detect 'null' and translate it into a NULL pointer.
+ Also if a function returns a NULL pointer, eg:
+
+ SomeClass *bar() { return NULL; }
+
+ Then this used to be wrapped with a SomeClass proxy class holding a NULL
+ pointer. Now null is returned instead. These changes are subtle but useful.
+ The original behaviour can be obtained by using the original typemaps:
+
+ %typemap(javaout) SWIGTYPE {
+ return new $&javaclassname($jnicall, true);
+ }
+ %typemap(javaout) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
+ return new $javaclassname($jnicall, $owner);
+ }
+ %typemap(javagetcptr) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] %{
+ protected static long getCPtr($javaclassname obj) {
+ return obj.swigCPtr;
+ }
+ %}
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+
+11/12/2002: beazley
+ Fixed problem with abstract methods and signatures. For example:
+
+ class abstract_foo {
+ public:
+ virtual int meth(int meth_param) = 0;
+ };
+
+
+ class abstract_bar : public abstract_foo {
+ public:
+ int meth(int meth_param_1, int meth_param_2) { return 0; }
+ };
+
+ In this case, abstract_bar is still abstract.
+
+ Fixes [ 628438 ] Derived abstract class not abstract.
+ Reported and patched by Scott Michel.
+
+11/11/2002: beazley
+ Fixed a matching problem with typemaps and array dimensions. For example, if you
+ had this:
+
+ typedef char blah[20];
+
+ and a typemap:
+
+ %typemap() char [ANY] {
+ ... $1_dim0 ...
+ }
+
+ then $1_dim* variables weren't be expanded properly. It should work now.
+ Problem reported by Pankaj Kumar Goel.
+
+11/07/2002: mkoeppe
+ Added an experimental new module that dumps SWIG's parse
+ tree as (Common) Lisp s-expressions. The module is
+ invoked with SWIG's -sexp command-line switch. The output
+ can be read into Common Lisp. There is (prototype)
+ example Lisp code that generates Foreign Function Interface
+ definitions for use with Kevin Rosenberg's UFFI.
+
+ *** EXPERIMENTAL NEW FEATURE ***
+
+11/07/2002: mkoeppe
+ Removed duplicate declaration of "cpp_template_decl" in
+ parser.y; bison 1.75 complained.
+
+11/06/2002: cheetah (William Fulton)
+ [Java] Default primitive array handling has changed like arrays of classes.
+ C primitive arrays are no longer wrapped by a Java array but with a pointer
+ (type wrapper class). Again the changes have been made for efficiency reasons.
+ The original typemaps have been moved into arrays_java.i, so the original
+ behaviour can be obtained merely including this file:
+
+ %include "arrays_java.i"
+
+ The array support functions are no longer generated by default. They are only
+ generated when including this file, thus this often unused code is only
+ generated when specifically requiring this type of array support.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+11/05/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added support for nested module declarations (as was
+ previously added for the Perl module). So a %module directive
+ of the form:
+
+ %module "Outer::Inner::Foo"
+
+ will nest everything as (in Ruby code):
+
+ module Outer
+ module Inner
+ module Foo
+ # stuff goes here
+ end
+ end
+ end
+
+11/05/2002: mkoeppe
+ [MzScheme] Add an argument (-declaremodule) that generates
+ code to correctly declare a primitive module extension.
+ Patch submitted by Bruce Butterfield.
+
+11/02/2002: cheetah (William Fulton)
+ [Java] Added patch submitted by Michael Cahill to remove unused parameter
+ warnings for the jenv and cls parameters. This patch also also allows one
+ to use "void" in the jni typemap for any type without code being generated
+ attempting to return a value.
+
+10/29/2002: cheetah (William Fulton)
+ [Java] Array handling is different. Arrays of classes are no longer wrapped
+ with proxy arrays, eg wrapping
+
+ class X {...};
+ X foo[10];
+
+ used to be wrapped with these Java getters and setters:
+
+ public static void setFoo(X[] value) {...}
+ public static X[] getFoo() {...}
+
+ This approach is very inefficient as the entire array is copied numerous
+ times on each invocation of the getter or setter. These arrays are now
+ wrapped with a pointer so it is only possible to access the first array element
+ using a proxy class:
+
+ public static void setFoo(X value) {...}
+ public static X getFoo() {...}
+
+ Arrays of enums have also been similarly changed. This behaviour is now like the
+ other SWIG language's implementation and the array library should be used to
+ access the other elements. The original behaviour can be achieved using the
+ macros and typemaps in arrays_java.i, for example:
+
+ %include "arrays_java.i"
+ JAVA_ARRAYSOFCLASSES(X)
+ class X {...};
+ X foo[10];
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+10/29/2002: cheetah (William Fulton)
+ [Java] Two new typemaps javain and javaout for generating the proxy class
+ and type wrapper class method calls to the JNI class. The new typemaps are
+ really used for transforming the jstype (used in proxy class and type wrapper
+ classes) to the jtype (used in the JNI class) and visa versa. A javain typemap
+ is required whenever an in typemap is written and similarly javaout for an out
+ typemap. An example is probably best to show them working:
+
+ %typemap(javain) Class "Class.getCPtr($javainput)"
+ %typemap(javain) unsigned short "$javainput"
+ %typemap(javaout) Class * {
+ return new Class($jnicall, $owner);
+ }
+
+ %inline %{
+ class Class {};
+ Class * bar(Class cls, unsigned short ush) { return new Class(); };
+ %}
+
+ The generated proxy code is then:
+
+ public static Class bar(Class cls, int ush) {
+ return new Class(exampleJNI.bar(Class.getCPtr(cls), ush), false);
+ }
+
+
+ Some new special variables have been introduced in order to use these typemaps.
+ Here $javainput has been replaced by 'cls' and 'ush'. $jnicall has been replaced by
+ the native method call, 'exampleJNI.bar(...)' and $owner has been replaced by 'false'.
+ $javainput is analogous to the $input special variable. It is replaced by the parameter name.
+ $jnicall is analogous to $action in %exception. It is replaced by the call to the native
+ method in the JNI class.
+ $owner is replaced by either true if %newobject has been used otherwise false.
+
+ The java.swg file contains default javain and javout typemaps which will produce the same code
+ as previously. This change is only of concern to those who have written their own typemaps as
+ you will then most likely have to write your own javain and javaout typemaps.
+
+ The javaout typemap also makes it possible to use a Java downcast to be used on abstract
+ proxy base classes. See the Java documentation on dynamic_cast.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+10/24/2002: ttn
+ [Methodology] Upgaded to libtool 1.4.3, presumably w/ better
+ support for newish platforms (like MacOS X).
+
+10/21/2002: ttn
+ Fixed Runtime/Makefile.in bug -- thanks to Richard Calmbach.
+
+10/18/2002: ttn
+ Fixed typo in doh.h -- thanks to Max Horn.
+
+Version 1.3.16 (October 14, 2002)
+=================================
+
+10/13/2002: beazley
+ Fixed bug with %extend directive and %feature reported
+ by William Fulton.
+
+10/13/2002: beazley
+ Added OpenVMS build directory (vms). Contributed by
+ Jean-Fran�ois Pieronne.
+
+10/09/2002: cheetah (William Fulton)
+ [Java] Added throws clause to the native functions in the JNI class.
+ The throws clause is the same as the one generated for proxy functions
+ and module class functions.
+
+09/27/2002: beazley
+ Fixed some problems with the %import directive and classes that
+ were defined but not wrapped. Problem reported by Leslie Brooks,
+ Gerry Woods, and others.
+
+09/23/2002: cheetah (William Fulton)
+ [Java] Some error checking added:
+ 1) OutOfMemoryException check in the char * typemaps.
+ 2) As SWIG treats pointers, references and passing by value all the
+ same, it is possible to pass a NULL pointer to a function that expects
+ an object passed by value or by reference. A NullPointerException is
+ now thrown under this scenario.
+
+09/20/2002: ttn
+ [Methodology] Reworked "make clean" and "make install"
+ to be more table driven.
+ [Docs] Explain how to extend "make install" w/ extra-install.list.
+
+09/15/2002: beazley
+ Deprecation of the "ignore" typemap. The "ignore" typemap has
+ been deprecated in favor of a generalization of the "in" typemap.
+ To ignore an argument, use something like this instead:
+
+ %typemap(in,numinputs=0) int *output (int temp) {
+ $1 = &temp;
+ }
+
+ This change fixes a number of subtle bugs related to the interaction
+ of the "in" and "ignore" typemaps (which were supposed to be
+ mutually exclusive).
+
+ The use of the numinputs argument is reserved for future expansion.
+ Currently, values >1 will generate an error. However, future
+ releases of SWIG may utilize that to support multi-input typemaps.
+
+ %typemap(ignore) still works, but generates a warning message and is
+ translated to %typemap(in,numinputs=0).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ *** NEW FEATURE ***
+
+09/15/2002: beazley
+ Fixed segmentation fault for unnamed structures. For example:
+
+ typedef struct {
+ } *blah;
+
+
+ Reported by Roger Gibson.
+ Note: we might be able to generate wrappers in special cases.
+
+09/13/2002: beazley
+ Minor modification to generated wrapper functions. Pointer arguments are now
+ always set to an initial value of 0. Simplifies typemap writing and cleanup
+ code (since you can rely on zero-value initialization). This also greatly
+ reduces the need to ever write an "arginit" typemap.
+
+09/12/2002: beazley
+ Minor enhancement to smart-pointer support. If operator->()
+ is part of an ignored base class like this,
+
+ %ignore Bar;
+
+ class Foo {
+ public:
+ int blah();
+ };
+
+ class Bar { /* Ignored */
+ public:
+ ...
+ Foo *operator->();
+ ...
+ };
+
+ class Spam : public Bar { };
+
+ then methods from Foo are still available. For example,
+
+ >>> s = Spam()
+ >>> s.blah()
+ 0
+ >>>
+
+ The only catch is that the operator->() itself is not available
+ (since it wasn't wrapped). Therefore, there won't be any
+ __deref__() operation unless it is explicitly added to Spam
+ (either using %extend or just placing operator->() in the
+ definition of Spam).
+
+09/11/2002: ttn
+ [Methodology] Reworked "make check" to be more table driven.
+ [Docs] Docuemented methodology in Manual/Extending.html.
+
+09/11/2002: ttn
+ [Docs] Prefixed Manual/*.html with "<!DOCTYPE html ...>" to
+ pander dotingly to (over-)sensitive editors.
+
+09/10/2002: ttn
+ [Guile] Converted Examples/guile/simple "make check"
+ behavior to actually check execution results. Reduced
+ iteration counts so that the test doesn't take too long.
+
+09/10/2002: beazley
+ SWIG-1.3.15 released.
+
+
+Version 1.3.15 (September 9, 2002)
+==================================
+
+09/09/2002: beazley
+ Fixed nasty runtime type checking bug with subtypes and inheritance
+ and templates.
+
+09/09/2002: cheetah (William Fulton)
+ [Java] Java exception classes for a method's throws clause can be generated by
+ specifying them in a comma separated list in the throws attribute in any one
+ of the following typemaps: in, out, check, freearg, argout and throws. A classic
+ example would be to convert C++ exceptions into a standard Java exception:
+
+ %typemap(throws, throws="java.io.IOException") file_exception {
+ jclass excep = jenv->FindClass("java/io/IOException");
+ if (excep)
+ jenv->ThrowNew(excep, $1.what());
+ return $null; // or use SWIG_fail
+ }
+
+ class file_exception {...};
+ void open(const char *filename) throw(file_exception);
+
+ The Java method will then be declared with a throws clause:
+
+ public static void open(String filename) throws java.io.IOException {...}
+
+09/08/2002: mkoeppe
+ * [Guile] Improved the documentation system. The arglist no
+ longer gets cluttered with type specification, making it
+ more readable. (Also the ILISP function C-u M-x
+ `arglist-lisp' RET works better this way.) The types of
+ arguments are explained in an extra sentence after the
+ arglist.
+
+ There are now two documentation-related typemap arguments:
+
+ %typemap(in, doc="$NAME is a vector of integers",
+ arglist="$name") int *VECTOR { ... }
+
+ The "arglist" texts of all arguments of a function make up
+ its arglist in the documentation. The "doc" texts of all
+ arguments are collected to make a sentence that describes
+ the types of the arguments. Reasonable defaults are
+ provided.
+
+ As usual, $name is substituted by the name of the
+ argument. The new typemap variable $NAME is like $name,
+ but marked-up as a variable. This means that it is
+ upper-cased; in TeXinfo mode ("-procdocformat texinfo") it
+ comes out as @var{name}.
+
+ The directives %values_as_list, %values_as_vector,
+ %multiple_values now also have an effect on the
+ documentation. (This is achieved via the new pragmas
+ return_nothing_doc, return_one_doc, return_multi_doc.)
+
+ Documentation has also improved for variables that are
+ wrapped as procedures-with-setters (command-line switch
+ "-emit-setters").
+
+ * [Guile] Emit constants as _immutable_ variables. (This
+ was broken recently.)
+
+09/07/2002: mkoeppe
+ [Guile] Updated the typemaps in list-vector.i.
+
+09/07/2002: mkoeppe
+ Short-circuit the typechecks for overloaded functions.
+ (The changes in code generation are visible in the new
+ testcase "overload_complicated".)
+
+09/06/2002: cheetah (William Fulton)
+ [Java] Solution for [ 596413 ]
+ New typemap so that the Java proxy classes and type wrapper classes
+ wrapper constructor modifier can be tailored by users. The default value is
+ protected. Normally SWIG generates a constructor like this which can only
+ be accessed within one package:
+
+ protected Bar(long cPtr, boolean cMemoryOwn) {
+ ...
+ }
+
+ If you are using SWIG across multiple packages or want to use this constructor
+ anyway, it can now be accessed outside the package. To modify use for example:
+
+ %typemap(javaptrconstructormodifiers) SWIGTYPE "public"
+
+ to change to public for all proxy classes and similarly for all type wrapper classes:
+
+ %typemap(javaptrconstructormodifiers) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "public"
+
+09/06/2002: cheetah (William Fulton)
+ [Java] Added throws typemaps for the Java module. C++ exceptions get converted into
+ java.lang.RuntimeException Java exceptions.
+
+ Warning: This may change from java.lang.Runtime exception in the future.
+
+09/05/2002: cheetah (William Fulton)
+ [Java] Fix for variables declared as references.
+
+09/05/2002: beazley
+ Fixed [ 605162 ] Typemap local variables. Reported by Lyle Johnson.
+
+09/05/2002: ljohnson (Lyle Johnson)
+ [Ruby] More updates to the Ruby module documentation, including
+ a new typemap example that demonstrates how to collect key-value
+ pairs from an argument list into a Hash.
+
+09/05/2002: beazley
+ Fixed bug with template expansion and constructors.
+
+ template<class T> class Foo {
+ public:
+ Foo<T>() { }
+ };
+
+ The extra <T> in the constructor was carried through in the
+ name--causing runtime problems in generated modules.
+ Reported by Jordi Arnabat Benedicto.
+
+09/05/2002: mkoeppe
+ [Guile] Support overloading.
+
+09/04/2002: ljohnson (Lyle Johnson)
+ [Ruby] Updated typemaps for long long and unsigned long long types
+ to use Ruby 1.7 support for these types when available.
+
+09/04/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added output typemaps for const reference to primitive
+ types.
+
+09/04/2002: mkoeppe
+ [Guile] Fix pass-by-value typemaps. Reported by Arno
+ Peters via Debian bugtracking (#156902), patch by Torsten
+ Landschoff <[email protected]>.
+
+09/03/2002: samjam (Sam Liddicott)
+ Better reference support.
+ Functions that want a void** can take a NULL by reference and
+ the void* will be made for you and then passed-by-reference
+
+ Also all integer-class native types can be passed by reference
+ where an int* or int& etc is needed
+
+09/03/2002: beazley
+ Changed the evaluation order of preprocessor macro arguments.
+ Arguments are now expanded by the preprocessor *before* they
+ are passed to macro expansion. This fixes a subtle expansion
+ bug reported by Anthony Heading.
+
+09/03/2002: beazley
+ Fixed the file include order (again, apparently). See 2/27/99.
+
+09/02/2002: beazley
+ [Perl] Better exception handling support. Since Perl error handling
+ relies on setjmp/longjmp, wrapper functions have been modified slightly
+ to provide an extra block scope:
+
+ XS(foo) {
+ char _swigmsg[SWIG_MAX_ERRMSG] = "";
+ const char *_swigerr = _swigmsg;
+ {
+ /* Normal wrapper function here */
+ ...
+ SWIG_croak("An error occurred\n");
+ ...
+ XSRETURN(argvi); /* Successful return */
+ fail:
+ /* cleanup code */
+ }
+ croak(_swig_err);
+ }
+
+ The macro SWIG_croak(x) sets the value of _swigerr to x and
+ executes a "goto fail". The whole wrapper function is enclosed
+ block scope to provide proper cleanup of C++ objects. Since
+ croak executes a longjmp(), there is no way to properly reclaim
+ resources if this executes in the same scope as the wrapper
+ function.
+
+ The _swigmsg[] variable is normally unused, but can be used
+ to store small error messages using sprintf or snprintf. It
+ has a capacity of at least 256 bytes (SWIG_MAX_ERRMSG).
+
+09/02/2002: beazley
+ [Tcl] Added better support for exceptions. Instead of returning TCL_ERROR,
+ use the macro SWIG_fail to return with an error. This ensures that
+ arguments are properly cleaned up. Exception specifiers are now
+ handled by default.
+
+09/02/2002: ljohnson (Lyle Johnson)
+ [Ruby] The type-checking system for the Ruby module has had a flaw
+ in that some types which should be considered equivalent
+ weren't. This bug was best demonstrated by the inherit_missing.i
+ test suite case, which defines a base class "Foo" that is
+ subclassed by "Bar". The "Foo" class isn't actually wrapped (i.e.
+ it's not directly accessible from Ruby) but we'd still like to be
+ able to pass "Bar" instances to functions expecting Foos and have
+ that work; it wasn't. The revised implementation (similar to that
+ used for some other language modules) adds a new instance variable
+ (__swigtype__) to each object that indicates its SWIG type;
+ that is, each "Bar" instance will now have a string instance
+ variable called "__swigtype__" whose value is "_p_Bar".
+
+ Unless developers were taking advantage of this low-level
+ implementation detail, they shouldn't notice any compatibility
+ problems; nevertheless, I'm marking it as a "potential
+ incompatibility".
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+09/01/2002: ljohnson (Lyle Johnson)
+ [Ruby] Fixed SF Bug #603199.
+
+08/08/2002: cheetah (William Fulton)
+ [Java] Added OUTPUT, INPUT and INOUT typemaps in typemaps.i for C++
+ references.
+
+08/27/2002: mkoeppe
+ [Guile] Fixed error in "lib_std_vector" testcase and
+ compiler warning in "lib_cdata" testcase.
+
+08/27/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added the "%mixin" directive, which allows the user to
+ specify a comma-separated list of module names to mix-in to a
+ class. So, for example, if you'd like to specify that Ruby's
+ Enumerable module should be mixed-in to your class Foo, you'd
+ write:
+
+ %mixin Foo "Enumerable";
+
+ or to specify that the modules Fee, Fie and Fo should be mixed
+ in to Foo:
+
+ %mixin Foo "Fee,Fie,Fo";
+
+ *** NEW FEATURE ***
+
+08/27/2002: ljohnson (Lyle Johnson)
+ [Ruby] Modified the %alias directive so that multiple aliases
+ can be specified for an instance method by using a comma-separated
+ list of aliases.
+
+08/27/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added "throw" typemaps for the Ruby module.
+
+08/26/2002: beazley
+ Two new command line options for printing dependencies.
+ 'swig -M' lists all file dependencies. 'swig -MM' lists
+ dependencies, but excludes files in the SWIG library.
+ Example:
+
+ % swig -M -python example.i
+ example_wrap.cxx: \
+ /u0/beazley/Projects/lib/swig1.3/swig.swg \
+ /u0/beazley/Projects/lib/swig1.3/python/python.swg \
+ example.i \
+ example.h
+
+ % swig -MM -python example.i
+ example_wrap.cxx: \
+ example.i \
+ example.h
+
+ *** NEW FEATURE ***
+
+08/26/2002: beazley
+ Fixed [ 597599 ] union in class: incorrect scope.
+ Reported by Art Yerkes.
+
+08/26/2002: beazley
+ Fixed [ 600132 ] Default argument with namespace.
+ Reported by Shibukawa Yoshiki.
+
+08/24/2002: beazley
+ Automatic C++ exception handling enabled for all language modules. This is
+ pretty simple. If you have a class like this:
+
+ class Foo {
+ };
+ class Bar {
+ public:
+ void blah() throw(Foo);
+ }
+
+ then the generated wrapper code looks like this:
+
+ wrap_Bar_blah() {
+ ...
+ try {
+ arg1->blah();
+ }
+ catch (Foo &_e) {
+ /* "throw" typemap code inserted. $1 = _e */
+ }
+ catch (...) {
+ throw;
+ }
+ }
+ The "throw" typemap can be used to raise an error in the target
+ language. It can do anything. Here is a very simple example:
+
+ %typemap("throw") Foo {
+ PyErr_SetString(PyExc_RuntimeError, "Foo exception");
+ return NULL;
+ }
+
+ To make this work in each language module, simply define a few default
+ "throw" typemaps for SWIGTYPE, SWIGTYPE *, int, const char *, and a
+ few common exception types. That's all there is to it.
+
+ Automatic exception handling can be disabled using -noexcept or
+ setting the NoExcept global variable to 1.
+ *** NEW FEATURE ***
+
+08/23/2002: beazley
+ [ Python ]
+ Automatic translation of C++ exception specifications into error handling code.
+ For example:
+
+ class Foo {
+ };
+ class Bar {
+ public:
+ void blah() throw(Foo);
+ }
+
+ In this case, Foo is wrapped as a classic-style class (compatible
+ with exception handling). Furthermore, you can write Python code
+ like this:
+
+ b = Bar()
+ try:
+ b.blah();
+ except Foo,e: # Note use of exception class here!
+ # Handle Foo error
+ ...
+
+ The object "e" in the exception handler is just a wrapped Foo
+ object. Access it like a normal object.
+
+ If an exception is not wrapped as a class, a RuntimeError
+ exception is raised. The argument to this exception is
+ the exception object. For example:
+
+ class Bar {
+ public:
+ void blah() throw(int);
+ }
+
+ b = Bar()
+ try:
+ b.blah();
+ except RuntimeError,e:
+ print e.args[0] # Integer exception value
+
+ Comments:
+
+ - If a class is used as an exception, it *must* be wrapped
+ as a Python classic-style class (new classes don't work).
+
+ - Automatic exception handling is compatible with %exception.
+
+ - Use -noexcept to turn off this feature.
+
+ - The newly introduced "throw" typemap is used to raise
+ Python errors (naturally).
+
+ *** EXPERIMENTAL NEW FEATURE ***
+
+08/23/2002: beazley
+ Information from throw() specifiers is now stored in the parse
+ tree. For example:
+
+ class Foo {
+ public:
+ int blah() throw(spam,bar);
+ }
+
+ The stored information is fully corrected for namespaces and works
+ with templates. Uses will follow.
+
+08/22/2002: beazley
+ Exception handling code is no longer applied to member access
+ function. For example, in this code
+
+ %exception {
+ try {
+ $action
+ } catch(whatever) {
+ ...
+ }
+ }
+
+ class Foo {
+ public:
+ int x;
+ ...
+ }
+
+ The exception handling code is not applied to accessor functions
+ for Foo::x. This should reduce the amount of extra code
+ generated.
+
+ Caveat: Exception handling code *is* used when attributes are
+ accessed through a smart-pointer or a synthesized attributed
+ added with %extend is used.
+
+08/22/2002: beazley
+ Made more patches to hopefully eliminate problems when compiling SWIG
+ as a 64-bit executable.
+
+08/22/2002: beazley
+ Fixed a bug with const reference members, variables, and static members.
+ For example:
+
+ class Foo {
+ public:
+ static const int &ref;
+ };
+
+ SWIG was trying to generate "set" functions which wouldn't compile.
+
+08/21/2002: beazley
+ Made the warning message for "Class X might abstract" off by default.
+ Enable with -Wall.
+
+08/21/2002: beazley
+ Refined handling of const and non-const overloaded methods. If
+ a class defines a method like this:
+
+ class Foo {
+ public:
+ int bar(int);
+ int bar(int) const;
+ }
+
+ Then the non-const method is *always* selected in overloading and
+ the const method silently discarded. If running with -Wall, a warning
+ message will be generated.
+
+08/19/2002: beazley
+ Better support for using declarations and inheritance. Consider this:
+
+ class Foo {
+ public:
+ int blah(int x);
+ };
+
+ class Bar {
+ public:
+ double blah(double x);
+ };
+
+ class FooBar : public Foo, public Bar {
+ public:
+ char *blah(char *x);
+ using Foo::blah;
+ using Bar::blah;
+ };
+
+ Now SWIG wraps FooBar::blah as an overloaded method that uses all
+ accessible versions of blah(). See section 15.2.2 in Stroustrup, 3rd Ed.
+
+ SWIG also supports access change through using declarations. For example:
+
+ class Foo {
+ protected:
+ int x;
+ int blah(int x);
+ };
+
+ class Bar : public Foo {
+ public:
+ using Foo::x;
+ using Foo::blah;
+ };
+
+
+ Caveat: SWIG does not actually check to see if declarations imported
+ via 'using' are in the inheritance hierarchy. If this occurs, the
+ wrapper code won't compile anyways---not sure it's worth worrying about.
+
+08/18/2002: beazley
+ Modified overloading dispatch to not include nodes with an "error" attribute.
+ A language module can set this if a node couldn't be wrapped and you don't want
+ it included in the dispatch function.
+
+08/18/2002: beazley
+ Enhancement to overloaded function dispatch. The dispatcher is now aware of
+ inheritance relationships. For example:
+
+ class Foo { };
+ class Bar : public Foo { };
+
+ void spam(Foo *f);
+ void spam(Bar *b);
+
+ In this case, the dispatcher re-orders the functions so that spam(Bar *b) is
+ checked first---it is more specific than spam(Foo *f).
+
+08/17/2002: beazley
+ Added -Werror command line option. If supplied, warning messages are treated
+ as errors and SWIG will return a non-zero exit code.
+
+08/17/2002: beazley
+ Fixed [ 596135 ] Typedef of reference can't compile. For example:
+
+ typedef int &IntRef;
+ void foo(IntRef i);
+
+ SWIG-1.3.14 generated code that wouldn't compile.
+
+Version 1.3.14 (August 12, 2002)
+================================
+
+08/11/2002: mmatus
+ Static const members initialized during declaration, and
+ only them, ie:
+
+ struct A
+ {
+ static const int a = 1 ; // this one
+ static const int b; // not this one
+ };
+
+ are emitted like constants (equivalent to enums or
+ explicit %constant).
+
+ This is because they cannot be added directly to 'cvar'
+ since they lack the needed reference (well, you can force
+ them to have a real reference, but in an ugly way which
+ goes completely again the original purpose of initialize
+ them during declaration, you also have to deal with extra
+ linking matters, and it take a while to figure out what is
+ the problem and how to solve it).
+
+ Please test it with your preferred target language, and
+ not only the code generation, but really run the example
+ in the test-suite (static-const-member-2.i) because the
+ problem and the solution cannot be "fully" appreciated
+ until you try to load the module and run it.
+
+ In some target languages (python specially), this can
+ produces a difference in the way that the static constant
+ members 'a' and 'b' are internally wrapped. Hopefully,
+ they still can be accessed in the same way.
+
+
+08/11/2002: mmatus
+ [python] Now static const members can be accessed in a more
+ natural way, ie, if you have
+
+ struct A
+ {
+ typedef unsigned int viewflags;
+ static const viewflags forward_field = 0;
+ static const viewflags backward_field;
+ };
+
+ now you can do:
+
+ print A.backward_field
+
+ and also
+
+ a = A()
+ print a.forward_field
+
+ Note that if the static const members don't have an
+ initializer (like backward_field), still you can access
+ them in the same way in the python side, but the
+ implementation is a quite different: backward_field will
+ still appear in the cvar entity, and also, you are
+ responsible to initialize it in some code unit, and link it
+ properly. forward_field, by the other hand, will not
+ appear in the cvar entity but only as a A member, similar
+ to what happen with enum or %constant members.
+
+08/11/2002: mmatus
+ [python] Common code in the __setattr__/__getattr__ now
+ goes to two "free" methods at the beginning of the proxy
+ file, from where each class use it. This change reduces
+ the size of the proxy file, specially if you wrap a lot of
+ small classes in one module (up to 33% in some cases),
+ making it faster to load too.
+
+08/09/2002: beazley
+ [Perl5] If a function that returns char * returns NULL,
+ undef is returned to the Perl interpreter.
+
+08/09/2002: beazley
+ Fix to conversion operators and namespaces. For example:
+
+ namespace ns {
+ struct Foo { };
+ struct Bar {
+ operator Foo*();
+ };
+ }
+
+ In the wrapper code, SWIG was using ->operator Foo*()
+ when it should have been using ->operator ns::Foo*().
+
+ Note: if using %rename with a conversion operator, you
+ might have to do this:
+
+ %rename(toFooPtr) ns::operator ns::Foo*();
+ // ^^^^ note extra qualifier
+ namespace ns {
+ ...
+
+
+08/09/2002: beazley
+ [Python] Minor enhancement to 'const' variable declarations.
+ Normally const declarations are wrapped as read-only variables
+ accessible only through the cvar attribute (see SWIG.html for
+ a discussion of why). However, in many programs, "const"
+ declarations may just be constants---making the cvar. access
+ awkward. To fix this, "const" declarations are now available
+ both through cvar. and as a simple name. For example:
+
+ const int FOO = 42;
+
+ In Python:
+
+ >>> print example.cvar.FOO
+ 42
+ >>> print example.FOO
+ 42
+
+ Note: There are cases where the value of a "const" variable
+ might change. For example:
+
+ char *const BAR = "Hello World";
+
+ In this case, the pointer itself can not change, but the
+ data being pointed to could be modified. In these situations,
+ cvar.BAR should be accessed to obtained the current value.
+
+08/08/2002: beazley
+ [Python] Fixed generation of the proxy code (.py files) to more
+ closely follow the order of declarations as they appear in
+ the .i file. In the past, all of the class wrappers appeared
+ first, followed by function stubs, inserted Python code, and
+ other details.
+
+08/08/2002: cheetah (William Fulton)
+ [Java] Proxy method _delete() changed to delete(). There shouldn't ever
+ be a wrapped function called delete() as it is a C++ keyword and there
+ is no such thing as a member function in C.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+ Backwards compatibility can be achieved by adding the function back in
+ for all proxy classes:
+ %typemap(javacode) SWIGTYPE %{
+ public void _delete() {
+ delete();
+ }
+ %}
+
+ Java backwards compatibility summary
+ ------------------------------------
+
+ There are a number of changes that have been made in improving the Java module
+ for ver 1.3.14. If at all possible change your code to take advantages of the
+ improvements. If you were using proxy classes you may not notice any backwards
+ compatibility issues. Here is an example which will help with most backwards
+ compatibility problems where it is not possible to modify the code that uses
+ the generated output:
+
+ Replace:
+ %module modulename
+
+ With:
+ %module (jniclassname="modulename") modulename;
+ %typemap(javacode) SWIGTYPE %{
+ public long getCPtr$javaclassname() {
+ return swigCPtr;
+ }
+ public void _delete() {
+ delete();
+ }
+ %}
+ %pragma(java) jniclassclassmodifiers="public";
+
+ The proxy constructors that took parameters (long cPtr, boolean cMemoryOwn)
+ were public and are now protected. If you were making use of these then you'll
+ have to modify your code and the best solution would be to use the new type
+ wrapper classes.
+
+ The other main areas are the pragmas and global variable wrapping. Replace
+ the pragmas with one of the new directives or typemaps mentioned below and use
+ %rename on the variables.
+
+ If you were not using proxy classes, you will have to define a jstype typemap
+ as well as a jtype typemap.
+
+08/08/2002: cheetah (William Fulton)
+ [Java] Fix for wrapping two dimension array variables.
+
+08/07/2002: beazley
+ [Python,Tcl]
+ Object management now has a much better sense of ownership.
+ Ownership bits is changed whenever an object is stored in a
+ global variable or structure member. For example:
+
+ struct Foo {
+ int val;
+ Foo *next;
+ };
+
+ Now in Python
+
+ >>> f = Foo()
+ >>> f.thisown
+ 1
+ >>> g = Foo()
+ >>> g.next = f # Assign a pointer
+ >>> f.thisown # Notice ownership change
+ 0
+ >>>
+
+ This scheme is mostly a conservative heuristic designed to
+ provide segmentation faults. It could cause a memory leak
+ if ownership is changed unnecessarily. In this case, you can
+ either write a typemap (that doesn't change ownership), or
+ manually set the thisown attribute back to 1.
+
+08/07/2002: beazley
+ [Tcl] Major usability improvements to the object interface.
+ Suppose you had code like this:
+
+ struct Foo {
+ int x;
+ int spam();
+ };
+
+ void blah(Foo *f);
+
+ In past versions of SWIG, you could create objects and use
+ them like this:
+
+ % Foo f
+ % f configure -x 3
+ % f spam
+ 37
+
+ The only problem is that if you tried to call blah(), it didn't
+ work:
+
+ % blah f
+ Type Error. Expected _p_Foo
+ %
+
+ Instead, you had to do this:
+
+ % blah [f cget -this]
+
+ SWIG now automatically extracts the -this pointer, avoiding this
+ problem. This means that saying "blah f" is perfectly legal and
+ everything will still work normally.
+
+ Caveat: Since pointer strings start with a leading underscore (_),
+ don't use this in object names. For example:
+
+ % Foo _f
+ % blah _f # Potential crash
+
+ Objects now have a -thisown attribute that shows the ownership.
+ This builds upon the CHANGES 11/24/2001 entry.
+
+08/07/2002: samjam, Sam Liddicott
+ Properly implemented pointer system using php resources.
+ Still need to work out whether or not to let script-users call
+ destructors directly
+
+08/06/2002: beazley
+ Upgraded mzscheme module to support version 201 and added
+ overloading support.
+
+08/05/2002: beazley
+ Added parsing support for extra grouping (in very limited cases).
+ For example:
+
+ typedef int (FuncPtr)(int, double);
+
+ *** EXPERIMENTAL ***
+
+08/03/2002: ljohnson (Lyle Johnson)
+ [Ruby] Updates to typemaps.i as those done previously for Perl,
+ Python and Tcl modules. Now supports reference types with INPUT,
+ OUTPUT and INOUT typemaps.
+
+08/02/2002: beazley
+ New library file cstring.i added. Provides macros for
+ manipulating char * data.
+
+08/02/2002: beazley
+ Deprecated the %new directive. Use %newobject instead. For
+ example:
+
+ %newobject foo;
+ ...
+ char *foo();
+
+ %newobject follows the same rules as %rename, %ignore, %feature,
+ etc.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+08/01/2002: cheetah (William Fulton)
+ [Java] New attribute 'jniclassname' for the module directive allows a way of
+ changing the JNI class name from the default which uses the modulename with JNI
+ appended after it.
+
+ %module (jniclassname="name") modulename
+
+ If 'name' is the same as 'modulename' then the module class name gets changed
+ from 'modulename' to modulenameModule.
+
+08/01/2002: beazley
+ Fixed problem with file include order. Language specific
+ directories should take precedence over generic directories.
+ For example: "swig_lib/python/foo.i" should be loaded before
+ "swig_lib/foo.i". I thought this was the case already, but
+ apparently it has been broken for quite some time.
+
+08/01/2002: beazley
+ Added std_deque.i library file. Work in progress.
+
+08/01/2002: beazley
+ [Python,Tcl,Perl]
+ Improvements to typemaps.i. INPUT/INOUT typemaps perform better
+ error checking. Typemaps are now supplied for references like
+ int &OUTPUT, double &INOUT, etc.
+
+08/01/2002: beazley
+ [Python] Deprecated the T_* and L_* typemaps in typemaps.i.
+ Multiple return values are always placed in a tuple. Deprecated
+ the BOTH typemaps. This is now INOUT (e.g., int *INOUT).
+
+ *** POTENTIAL INCOMPATIBILITY FOR PYTHON MODULE ***
+
+08/01/2002: beazley
+ Deprecated the array.i, carray.i, and timer.i library files.
+
+08/01/2002: beazley
+ Deprecated the pointer.i library file. Use cpointer.i instead.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+08/01/2002: cheetah (William Fulton)
+ [Java] For consistency the global variable getters and setters use the JavaBean
+ property design pattern like member variables always have. This means if you are
+ wrapping a variable called foo, the getter is called getFoo() and the setter is
+ called setFoo(). Before the recent changes to the Java module the getters and
+ setters were called get_foo() and set_foo(). If you really want the original
+ function names use the %rename directive like this: %rename(_foo) Foo;
+
+07/31/2002: beazley
+ Fixed casting problem with multiple inheritance. If you had this,
+
+ class foo {};
+ class bar : public foo {};
+ class baz : public foo {};
+ class spam : public bar, public baz {};
+
+ then the wrappers wouldn't compile due to an ambiguous cast.
+ Reported by Art Yerkes.
+
+07/30/2002: cheetah (William Fulton)
+ [Java] Due to new static typechecking all pointers held in a Java long are part of
+ the internal workings and this pointer value in the Java long has become abstracted
+ data. The type wrapper constructor and getCPtr() methods are as such protected.
+ If you need to mess around with pointers from Java or for example create a proxy
+ class or type wrapper class around a null pointer, add a function/constructor
+ to do so with the %javacode typemap. You can also make getCPtr() public again with
+ the %javagetcptr typemap.
+
+07/30/2002: cheetah (William Fulton)
+ [Java] Fixes for %typemap(ignore). In particular when ignoring the last parameter
+ in a function. Also for all parameters in constructors. These mods have also fixed
+ multi-argument typemaps for proxy classes - SF 581791.
+
+07/30/2002: cheetah (William Fulton)
+ [Java] %newobject (replacement for %new) now implemented for Java.
+
+07/29/2002: beazley
+ Fixed problem with typemap copies, %apply, and %clear inside
+ C++ namespaces.
+
+07/28/2002: cheetah (William Fulton)
+ [Java] The JNI class now has package access as the class modifier
+ has been changed from "public" to nothing. This has been done
+ as this class is now more for the internal workings of SWIG since the module
+ class has static type checking for all types.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+ Backwards compatibility can be achieved by using the %jniclassclassmodifier
+ pragma to change it back to "public".
+
+07/28/2002: cheetah (William Fulton)
+ [Java] Proxy/Shadow classes are generated by default. The -proxy and
+ -shadow command line options are deprecated. If you want to use the
+ low-level functional interface then use the new -noproxy commandline option.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+07/28/2002: cheetah (William Fulton)
+ [Java] Remaining pragmas shakeup. These were the remaining pragmas and their
+ new names where changed:
+
+ modulebase
+ modulecode
+ moduleclassmodifiers
+ moduleimport => moduleimports
+ moduleinterface => moduleinterfaces
+
+ The moduleimports works slightly differently to how the moduleimport pragma worked.
+ Now it actually takes code which gets placed before the class definition so the
+ whole import statement has to be given, for example:
+
+ %pragma(java) moduleimports=%{
+ import java.io.*;
+ import java.math.*;
+ %}
+
+ The moduleinterfaces is slightly different to the old moduleinterface in that if
+ more than one interface is required they must be comma separated in one use of
+ the pragma, for example:
+
+ %pragma(java) moduleinterfaces="Serializable, MyInterface"
+
+ These last two pragmas are consistent with the javainterfaces and javaimports
+ typemap.
+
+ A similar set of pragmas has been introduced, namely:
+
+ jniclassbase
+ jniclasscode
+ jniclassclassmodifiers
+ jniclassimport
+ jniclassinterface
+
+ These work in the same way as their module counterparts. Note that previously
+ the moduleXXX pragmas worked on the old module class which is now called the
+ JNI class (the class with the native functions). The jniclassXXX pragmas now
+ work on the new module class (the class that has all the global functions and
+ global variable getters and setters when using proxy classes, plus all other
+ remaining functions when using the low-level procedural interface).
+
+ In summary the contents of the pragmas make up a class like this:
+
+ <jniclassimports>
+ <jniclassmodifiers> class modulename extends <jniclassbase> implements <jniclassinterfaces> {
+ <jniclasscode>
+ ... SWIG generated functions ...
+ }
+}
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+07/28/2002: cheetah (William Fulton)
+ [Java] Deprecated modulemethodmodifiers pragma and replaced with
+ a better %feature based directive called %javamethodmodifiers.
+ A useful example would be for synchronisation in multi-threaded apps:
+
+ %javamethodmodifiers foo(int a) "public synchronized";
+
+ Changes this function from the default ("public") to "public synchronized".
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+07/26/2002: beazley
+ Several directives now allow optional configuration parameters.
+ These include:
+
+ %module(name="value", name="value", ...) modulename
+ %import(name="value", ...) "filename.i"
+ %extend(name="value", ...) classname {
+ ...
+ }
+
+ These currently have no effect and are reserved for
+ future expansion.
+
+07/26/2002: beazley
+ Enhancements to smart-pointer handling. SWIG only provides
+ extra support for a smart-pointer if operator->() returns
+ a proper pointer. For example:
+
+ Foo *operator->();
+
+ If operator->() returns an object by value or reference,
+ then SWIG examines the returned object to see if it also
+ implements operator->(). If so, SWIG chases operator->()
+ until it can find one that returns a pointer. This allows
+ cases like this to work:
+
+ class Foo {
+ public:
+ void blah();
+ };
+
+ class Bar {
+ ...
+ Foo *operator->();
+ ...
+ };
+
+ class Spam {
+ ...
+ Bar operator->();
+ ...
+ };
+
+ For example:
+
+ >>> s = Spam()
+ >>> s.blah() # Invokes Foo::blah()
+
+ The s.blah() call actually invokes:
+
+ ((s.operator->()).operator->())->blah();
+
+07/26/2002: beazley
+ Fixed a bug with typedef and references. For example:
+
+ typedef Foo & FooRef;
+ FooRef blah();
+
+ Previous versions of SWIG generated code that wouldn't
+ compile.
+
+07/25/2002: beazley
+ Wrapping of static methods has been improved in proxy classes. In older
+ versions of SWIG, if you had this:
+
+ class Foo {
+ public:
+ static void bar();
+ };
+
+ The static method was only available as a function Foo_bar(). For example:
+
+ >>> Foo_bar()
+
+ Now, the static method can also be invoked through an instance like this:
+
+ >>> f = Foo()
+ >>> f.bar() # Invokes static method
+
+ This works with all versions of Python. Additionally, for Python-2.2,
+ the static method can be invoked as:
+
+ >>> Foo.bar()
+
+ The old-style function is still support for backwards compatibility. If
+ you care about making your code across different versions of Python,
+ either use Foo_bar() or access the method through an instance.
+
+07/25/2002: beazley
+ Changes to the Python module. Proxy classes now utilize new Python-2.2
+ features including properties and static methods. However, these features
+ are supported in a way that provides backwards compatibility with older
+ Python versions. In other words, proxy classes work with all versions
+ of Python and only use new features when running on Python-2.2.
+
+
+07/25/2002: beazley
+ Modified %extend so that overloaded methods can be added. For example:
+
+ %extend Foo {
+ void bar(int x) { };
+ void bar(char *s) { };
+ ...
+ }
+
+ This works with both C++ *and* C.
+
+07/24/2002: cheetah (William Fulton)
+ [Java] More new typemaps so that the Java proxy classes and type wrapper classes
+ can be further tailored by users. These are the default code for generating the
+ finalize() methods (proxy classes only) and the getCPtr() methods for proxy
+ classes and type wrapper classes:
+
+ %typemap(javafinalize) SWIGTYPE %{
+ protected void finalize() {
+ _delete();
+ }
+ %}
+
+ %typemap(javagetcptr) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] %{
+ public static long getCPtr($javaclassname obj) {
+ return obj.swigCPtr;
+ }
+ %}
+
+ The javagetcptr typemap will enable users to handle Java null by overriding
+ this typemap - a requested feature.
+
+ The -nofinalize commandline option has been deprecated. The javafinalize
+ typemap is more powerful as it will allow the removal of the finalize methods
+ for all or any one or more particular proxy class.
+
+07/23/2002: cheetah (William Fulton)
+ [Java] The getCPtrXXX() function has been changed to a static function and
+ is now of the form:
+
+ protected static long getCPtr(XXX obj) {...}
+
+ This is a requested change which will allow Java null pointers to be used as null
+ can be passed in for obj. However, to achieve this the appropriate code must be
+ written using the new javagetcptr typemap directive.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+ Backwards compatibility can be achieved by adding this function back in using the
+ new javacode typemap:
+
+ %typemap(javacode) SWIGTYPE %{
+
+ // SWIG-1.3.12 and SWIG-1.3.13
+ public long getCPtr$javaclassname() {
+ return swigCPtr;
+ }
+ // SWIG-1.3.11 and earlier
+ public long getCPtr() {
+ return swigCPtr;
+ }
+
+ %}
+
+
+07/23/2002: cheetah (William Fulton)
+ [Java] New directive to control constant code generation - %javaconst.
+ The default handling for handling constants is to get the value through
+ a JNI call, eg
+
+ #define YELLOW 5
+ #define BIG 1234LL
+
+ results in:
+
+ public final static int YELLOW = modulename.get_YELLOW();
+ public final static long BIG = modulename.get_BIG();
+
+ Earlier versions of the Java module initialised the value using the C value:
+
+ public final static int YELLOW = 5;
+ public final static long BIG = 1234LL;
+
+ This works in most cases, but the value for BIG won't compile as 1234LL is not
+ valid Java code and this is one of the reasons why the default is now to get the
+ values through a JNI call. The side effect is that these 'constants' cannot be used
+ in switch statements. The %javaconst directive allows one to specify the
+ way the constant value is initialised and works like other %feature
+ directives, eg
+
+ %javaconst(0); // all constants from this point on are initialised using the C value
+ %javaconst(1) BIG; // just BIG initialised using JNI call (must be parsed before BIG is defined)
+
+07/23/2002: beazley
+ *** IMPORTANT CHANGES TO THE PYTHON MODULE ***
+
+ (1) The Python module now enables shadow/proxy classes by default.
+ This means that two files are always created by SWIG. For
+ instance, if you have this:
+
+ // file: foo.i
+ %module foo
+ ...
+
+ Then swig generates two files "foo_wrap.c" and "foo.py".
+
+ (2) The name of the low-level C extension module has been changed
+ to start with a leading underscore. This means that you have
+ to compile the module as follows:
+
+ $ cc -c -I/usr/local/include/python2.2 foo_wrap.c
+ $ cc -shared foo_wrap.o $(OBJS) -o _foo.so
+ ^^^^
+ note extra underscore
+
+ This naming scheme is consistent with other Python modules that
+ utilize extension code. For instance, the socket module consists
+ of "_socket.so" and "socket.py". In previous versions of SWIG,
+ the shared object file was named "foocmodule.so".
+
+ (3) A new directive can be used to insert Python code into
+ the corresponding .py file. For example:
+
+ %pythoncode %{
+ def foo():
+ print "Hello World"
+ %}
+
+ This directive allows you to create modules as a mix of C and Python.
+ Python code is seamlessly added to the module.
+
+ (4) The -shadow command line option is deprecated. This is turned on
+ by default.
+
+ (5) To disable the generation of the extra python file, use the "-noproxy"
+ command line option.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ This change will likely break the build environment of projects that
+ utilize shadow classes. To fix this, you probably only need to
+ change the name of the target .so file. For example, if you have
+ Makefile information like this:
+
+ TARGET = examplecmodule.so
+
+ Just change it to:
+
+ TARGET = _example.so
+
+ *** DOCUMENTATION UPDATE ***
+ The file Doc/Manual/Python.html has been updated to describe these changes.
+
+
+07/23/2002: beazley
+ Added -noextern option. If supplied, SWIG will not generate
+ extra extern declarations. This is sometimes an issue on
+ non-unix platforms.
+
+07/23/2002: beazley
+ Added a warning for ignored friend functions.
+
+07/23/2002: beazley
+ Fixed [ 574498 ] -proxy and %include "pointer.i" clash.
+ Reported by David Creasy.
+
+07/23/2002: beazley
+ Fixed [ 576103 ] global destruction warning with shadow.
+ Perl extensions should no longer report the warning
+
+ "Use of uninitialized value during global destruction."
+
+ when running with "perl -w". Reported by
+ Brett Williams.
+
+07/23/2002: beazley
+ In C++ mode, SWIG now always defines namespace std. By default,
+ it's empty. However, this will silence errors from programs
+ that include statements such as "using namespace std;".
+ This fixes Bug [ 584017 ] using namespace std generates error.
+ Reported by Joseph Winston.
+
+07/22/2002: beazley
+ Added a new warning message for %apply. If you use %apply but no typemaps
+ are defined, you will get a warning message. This should help with
+ problems like this:
+
+ %apply char *OUTPUT { ... };
+
+ In old versions of SWIG, this silently did nothing. Now you get an error like this:
+
+ file:line. Warning. Can't apply (char *OUTPUT). No typemaps are defined.
+
+07/22/2002: cheetah (William Fulton)
+ [Java] Started Java pragma deprecation. Replacements use %typemap based
+ directives and enable proxy classes and the new type wrapper classes to be
+ tailored in various ways. These are the new typemaps:
+
+ %typemap(javabase) - base (extends) for Java class
+ %typemap(javaclassmodifiers) - class modifiers for the Java class: default is "public"
+ %typemap(javacode) - java code is copied verbatim to the Java class
+ %typemap(javaimports) - import statements for Java class
+ %typemap(javainterfaces) - interfaces (extends) for Java class
+
+ And these are the %pragma directives being deprecated:
+ allshadowbase
+ allshadowclassmodifiers
+ allshadowcode
+ allshadowimport
+ allshadowinterface
+ shadowbase
+ shadowclassmodifiers
+ shadowcode
+ shadowimport
+ shadowinterface
+
+ Note that it is possible to target a particular proxy class:
+ %typemap(javaimports) Foo "import java.util.*"
+ or a particular type wrapper class:
+ %typemap(javaimports) double* "import java.math.*"
+ Note that $javaclassname in these typemaps are substituted with either the proxy
+ classname when using proxy classes or the SWIGTYPE class name.
+
+07/18/2002: cheetah (William Fulton)
+ [Java] Java module overhaul to implement static type checking of all
+ types.
+
+ 1) Changes when using Java Proxy classes
+ ----------------------------------------
+
+ Previously when wrapping global functions:
+
+ class SomeClass{};
+ void foo(SomeClass* s);
+ SomeClass* bar();
+
+ The native method prototypes used a long for pointers and looked like this:
+
+ public class modulename {
+ ...
+ public final static native void foo(long jarg1);
+ public final static native long bar();
+ }
+
+ and unlike member functions of a C++ class there was no wrapper around the native calls
+ to make the use of them more user friendly. They would be used from Java like this:
+
+ SomeClass s = new SomeClass(modulename.bar(), false);
+ modulename.foo(s.getCPtrSomeClass());
+
+ Note that the following will have the same effect, but then it would not have
+ been possible to call any proxy member functions in SomeClass:
+
+ long s = modulename.bar();
+ modulename.foo(s);
+
+ Now wrapper functions are generated:
+
+ public class modulename {
+ public static void foo(SomeClass s) {
+ // calls the native function
+ }
+
+ public static SomeClass bar() {
+ // calls the native function
+ }
+ }
+
+ Which means these functions can now be used more naturally with proxy classes:
+
+ SomeClass s = modulename.bar();
+ modulename.foo(s);
+
+ 2) Changes when not using Java Proxy classes
+ --------------------------------------------
+
+ The so called low-level interface was rather low-level indeed. The
+ new static type checking implementation makes it less so but it remains a
+ functional interface to the C/C++ world. Proxy classes are the obvious way to use
+ SWIG generated code, but for those who want a functional interface all non-primitive
+ types now have a simple Java class wrapper around the C/C++ type. Pointers and
+ references to primitive types are also wrapped by type wrapper classes. The type
+ wrapper classnames are based on the SWIG descriptors used by the other language
+ modules. For example:
+
+ C/C++ type Java type wrapper class name
+ ---------- ----------------------------
+ int* SWIGTYPE_p_int
+ double** SWIGTYPE_p_p_double
+ SomeClass* SWIGTYPE_p_SomeClass
+ SomeClass& SWIGTYPE_p_SomeClass
+ SomeClass SWIGTYPE_p_SomeClass
+
+ Note that everything wrapped by SWIG is accessed via a pointer even when wrapping
+ functions that pass by value or reference. So the previous example would now be
+ used like this:
+
+ SWIGTYPE_p_SomeClass s = example.bar();
+ example.foo(s);
+
+ Note that typedefs that SWIG knows about are resolved, so that if one has
+
+ class Foo{};
+ typedef Foo Bar;
+
+ then any use of Bar will require one to use SWIGTYPE_p_Foo;
+
+ Some considerations:
+ Make sure you make a firm decision to use either proxy classes or the functional
+ interface early on as the classnames are different.
+
+ 3) Pointers and non-parsed types
+ --------------------------------
+ Sometimes SWIG cannot generate a proxy class. This occurs when the definition of
+ a type is not parsed by SWIG, but is then used as a variable or a parameter.
+ For example,
+
+ void foo(Snazzy sds);
+
+ If SWIG has not parsed Snazzy it handles it simply as a pointer to a Snazzy.
+ The Java module gives it a type wrapper class around the pointer and calls it
+ SWIGTYPE_p_Snazzy. In other words it handles it in the same manner as types are
+ handled in the low-level functional interface. This approach is used for all
+ non-proxy classes, eg all pointer to pointers and pointers to primitive types.
+
+ 4) Backwards compatibility
+ -----------------------
+ Backwards compatibility is not an issue if you have been using proxy classes and
+ no global variables/functions. Otherwise some changes will have to be made.
+ The native methods still exist but they are now in a JNI class, which is called
+ modulenameJNI. As this class is really part of the internal workings,
+ it should not be required so the class has become protected. Some pragmas/directives
+ will hopefully be added to help with backwards compatibility.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+07/18/2002: beazley
+ Modified wrapping of uninstantiated templates returned by
+ value. Just to be safe, they are now wrapped by SwigValueWrapper<>
+ just in case they don't define a default constructor. This
+ would be used if you had code like this
+
+ Foo<int> blah();
+ void moreblah(Foo<int> x);
+
+ but you didn't instantiate Foo<int> using %template.
+ We should probably add a warning for this.
+
+07/17/2002: beazley
+ Added an error check to detect shadowed template paramaters.
+ For example:
+
+ template<class T> class Foo {
+ public:
+ int T;
+ };
+
+ This results in an error, not a warning. This warning is
+ also needed to fix some rather insidious problems like
+ this:
+
+ struct T {
+ int blah;
+ };
+
+ template<class T> class Foo {
+ public:
+ typedef T Traits; // Which T is this????
+ };
+
+ In this case, the template parameter T shadows the outer
+ structure (which is what you want).
+
+07/16/2002: beazley
+ Improved support for templates with integer arguments. SWIG is
+ much more aware of situations such as this:
+
+ const int Size = 100;
+
+ %template(Foo100) Foo<100>;
+ void bar(Foo<Size> *x); // Knows that Foo<Size> is the same as Foo<100>;
+
+07/15/2002: beazley
+ Fixed bug with %feature/%ignore/%rename and namespaces.
+ For example:
+
+ %ignore Foo::Bar
+ namespace Foo {
+ class Bar {
+ ...
+ };
+ }
+
+ Reported by Marcelo Matus.
+
+07/09/2002: beazley
+ Added parsing support for constructors that try to catch
+ exceptions in initializers. For example:
+
+ class Foo {
+ Bar b;
+ public:
+ Foo(int x) try
+ : b(x) { ... }
+ catch(int) {
+ ...
+ }
+ }
+
+ This has no effect on the generated wrappers. However, the try and catch
+ parts of the declaration are ignored. See Stroustrup, 3rd Ed, section
+ 14.4.6.1 for details.
+
+07/06/2002: beazley
+ Fixed bug in template symbol table management. This fixes
+ two bugs. First, mixing abstract methods, templates, and
+ inheritance no longer generates a failed assertion.
+
+ template <class T>
+ class A {
+ public:
+ virtual void foo() = 0;
+ };
+
+ template <class T>
+ class B : public A<T>
+ {
+ };
+ %template(A_int) A<int>;
+ %template(B_int) B<int>;
+
+ This fix also fixes a subtle problem with default values and
+ templates. For example:
+
+ template <class C>
+ struct B {
+ typedef unsigned int size_type;
+ static const size_type nindex = static_cast<size_type>(-1);
+ void foo(size_type index = nindex);
+ };
+
+ Bugs reported by Marcelo Matus.
+
+
+07/05/2002: ljohnson (Lyle Johnson)
+ [Ruby] Changed the definition of the SWIG_ConvertPtr() function
+ for the SWIG/Ruby runtime support so that it looks like the
+ Python version. If the last argument (flags) is non-zero,
+ SWIG_ConvertPtr() will raise an exception for type mismatches
+ as before. If flags is zero, this function will return -1 for
+ type mismatches without raising an exception.
+
+ *** POTENTIAL INCOMPATIBILITY FOR RUBY MODULE ***
+
+07/04/2002: beazley
+ Overloaded functions/methods/constructors now work in many language
+ modules. The support is completely transparent--just call the
+ function normally and SWIG will dispatch to the correct implementation.
+ There are a variety of issues associated with this. Please refer
+ to the overloading section of Doc/Manual/SWIGPlus.html for details.
+ *** NEW FEATURE ***
+
+07/04/2002: beazley
+ Fixed a bug with namespaces, enums, and templates. For example:
+
+ namespace hello {
+ enum Hello { Hi, Hola };
+
+ template <Hello H>
+ struct traits
+ {
+ typedef double value_type;
+ };
+
+ traits<Hi>::value_type say_hi()
+ {
+ return traits<Hi>::value_type(1);
+ }
+ }
+ SWIG wasn't generating wrappers that properly qualified
+ traits<Hi>. Reported by Marcelo Matus.
+
+06/30/2002: beazley
+ Supplied array variable typemaps for Tcl module. If you have a
+ variable like this:
+
+ int foo[10];
+
+ then a set function like this is generated:
+
+ void foo_set(int *x) {
+ memmove(foo,x,10*sizeof(int));
+ }
+
+06/30/2002: beazley
+ New %fragment directive. When writing typemaps, it can be easy to
+ get carried away and write a lot of code. However, doing so causes
+ tremendous code bloat. A common way to solve this is to write
+ helper functions. For example:
+
+ %{
+ void some_helper_function() {
+ ...
+ }
+ %}
+
+ %typemap(in) type {
+ some_helper_function(...);
+ }
+
+ The only problem with this is that the wrapper file gets polluted
+ with helper functions even if they aren't used. To fix this,
+ a new fragment directive is available. For example:
+
+ (corrected typo in line below - 06/26/2008)
+ %fragment("type_header","header") %{
+ void some_helper_function() {
+ ...
+ }
+ %}
+
+ %typemap(in, fragment="type_header") type {
+ some_helper_function(...);
+ }
+
+ In this case, the code fragment is only emitted if the typemap is
+ actually used. A similar capability is provided for declaration
+ annotation and the %feature directive. For example:
+
+ %feature("fragment","type_header") SomeDeclaration;
+
+ The first argument to %fragment is the fragment name. The second argument
+ is the file section where the fragment should be emitted.
+
+ The primary use of this directive is for writers of language modules
+ and advanced users wanting to streamline typemap code.
+
+ *** EXPERIMENTAL NEW FEATURE ***
+
+06/30/2002: beazley
+ Supplied memberin typemaps for all arrays in an attempt to eliminate
+ confusion about their use.
+
+06/29/2002: beazley
+ Experimental support for smart-pointers. When a class defines
+ operator->() like this
+
+ class Foo {
+ ...
+ Bar *operator->();
+ ...
+ };
+
+ SWIG locates class Bar and tries to wrap its member variables and
+ methods as part of Foo. For example, if Bar was defined like this:
+
+ class Bar {
+ public:
+ int x;
+ int spam();
+ };
+
+ You could do this (in the target language):
+
+ f = Foo()
+ f.x = 4 # Accesses Bar::x
+ f.spam() # Accesses Bar::spam
+
+ The primary use of this feature is to emulate the behavior of C++
+ smart-pointers---which allow attributes to accessed transparently
+ through operator->.
+
+ This feature is supported automatically in SWIG---no special directives
+ are needed. To disable this behavior. Use %ignore to ignore
+ operator->.
+ *** NEW FEATURE ***
+
+06/26/2002: beazley
+ Deprecated the %except directive. %exception should be used instead.
+
+06/25/2002: beazley
+ Major cleanup of the modules directory. Eliminated most
+ header files, consolidated module code into single files.
+
+06/24/2002: beazley
+ Reworked the instantiation of language modules. All language
+ modules must now define a factory function similar to this:
+
+ extern "C" Language *
+ swig_python(void) {
+ return new PYTHON();
+ }
+
+ This function is then placed in a table and associated with
+ a command line option in swigmain.cxx.
+
+ This approach has a number of benefits. It decouples the
+ SWIG main program from having to know about the class
+ definitions for each module. Also, by using a factory
+ function, it will be easier to implement dynamic loading
+ of modules (simply load the file and invoke the factory
+ function).
+
+06/24/2002: beazley
+ Fixed syntax error for reference conversions. For example:
+
+ operator Foo &();
+
+06/24/2002: beazley
+ Fixed syntax error for operator new[] and operator delete[].
+
+06/24/2002: beazley
+ Fixed code generation problem for constants and default arguments
+ involving templates.
+
+06/19/2002: ljohnson (Lyle Johnson)
+ [Ruby] Fixed a bug for the '-feature' command line argument;
+ that setting was effectively being ignored and so the feature
+ name was always set equal to the module name.
+
+06/17/2002: beazley
+ Fixed problems with static members and enums in templates.
+
+Version 1.3.13 (June 17, 2002)
+==============================
+
+06/16/2002: beazley
+ Fixed a bug with __FILE__ expansion in the preprocessor. On Windows,
+ the backslash (\) is now converted to (\\) in the string literal
+ used for __FILE__. Reported by Steve Glaser.
+
+06/14/2002: beazley
+ Fixed warning message about 'name private in this context'. The
+ warning is only generated for public methods. Reported by
+ Scott Michel.
+
+06/14/2002: beazley
+ Fixed some problems related to template instantiation
+ and namespaces. When SWIG expands a template, it does
+ so with fully resolved types. For example, if you have this:
+
+ template<class T> class foo { };
+ typedef double Double;
+ %template(foo_d) foo<Double>;
+
+ then, it is handled as foo<double> in the typesystem.
+ This fixes a number of subtle problems with inheritance
+ and templates.
+
+06/14/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added missing bool typemaps for INPUT, OUTPUT and
+ INOUT in Lib/ruby/typemaps.i.
+
+05/29/2002: cheetah (William Fulton)
+ [Java] Fix for a couple of broken pragmas.
+
+05/29/2002: cheetah (William Fulton)
+ Fix for unnecessary cast when wrapping global variable where
+ the type is not parsed by SWIG - Java variables example
+ failure as reported by Larry Virden.
+
+06/10/2002: beazley
+ Modified %template to allow for empty instantiations.
+
+ %template() foo<int,int>;
+
+ This registers foo<int,int> with the type system, but
+ doesn't wrap it (same as %ignore). This may only be a
+ temporary measure. SWIG might be able to automatically
+ instantiate templates in certain cases.
+
+06/10/2002: beazley
+ Fixed function prototype problems with Tcl 8.4
+
+06/09/2002: beazley
+ Fixed problem with templates and location of base classes.
+ This one is a little mind-bending, but here is an example
+ that illustrates:
+
+ template <class ArgType, class ResType>
+ struct traits
+ {
+ typedef ArgType arg_type;
+ typedef ResType res_type;
+ };
+
+ template <class ArgType, class ResType>
+ struct Function
+ {
+ };
+
+ template <class AF, class AG>
+ struct Class : Function<typename traits<AF, AG>::arg_type,
+ typename traits<AF, AG>::res_type>
+ {
+ };
+
+ %template(traits_dd) traits <double, double>;
+ %template(Function_dd) Function <double, double>;
+ %template(Class_dd) Class <double, double>;
+
+
+ In this example, the base class of 'Class' is determined from
+ the Function template, but the types are obtained through typedefs.
+ Because of this, SWIG could not locate the wrapped base class
+ (Function<double,double>). Should be fixed in 1.3.13 even
+ though I can think of a million other things that might
+ also be broken.
+
+06/07/2002: beazley
+ Fixed a problem with conversion operators. If you had an
+ operator like this,
+
+ operator double() const;
+
+ SWIG was ommitting the "const" qualifier. This affected
+ %rename and other directives. Reported by Zhong Ren.
+
+06/07/2002: beazley
+ Lessened the strictness of abstract class checking. If
+ you have code like this:
+
+ class Foo {
+ public:
+ virtual int method() = 0;
+ };
+
+ class Bar : public Foo {
+ public:
+ Bar();
+ ~Bar();
+ };
+
+ SWIG will go ahead and generate constructor/destructors
+ for Bar. However, it will also generate a warning message
+ that "Bar" might be abstract (since method() isn't defined).
+ In SWIG-1.3.12, SWIG refused to generate a constructor at all.
+
+06/07/2002: beazley
+ Change to %template directive. If you specify something like this:
+
+ %template(vi) std::vector<int>;
+
+ It is *exactly* the same as this:
+
+ namespace std {
+ %template(vi) vector<int>;
+ }
+
+ SWIG-1.3.12 tried to instantiate the template outside of the namespace
+ using some trick. However, this was extremely problematic and full
+ holes. This version is safer.
+
+06/07/2002: beazley
+ Fixed bug with scope qualification and templates. For example:
+
+ A<B::C>::DD
+
+ Before, this was separated as scopes A<B, C>, and DD. Fixed now.
+
+06/06/2002: beazley
+ Allow the following syntax:
+
+ class A { };
+ struct B : A { ... };
+
+ A base class without a specifier is assumed to be public for a struct.
+
+06/06/2002: beazley
+ Fixed syntax error with template constructor initializers.
+ Reported by Marcelo Matus.
+
+06/06/2002: beazley
+ Fixed bug with default template arguments.
+ Reported by Marcelo Matus.
+
+06/05/2002: beazley
+ Fixed subtle problems with %rename directive and template
+ expansion.
+
+ Code like this should now work:
+
+ %rename(blah) foo<double>::method;
+ ...
+ template<class T> class foo {
+ public:
+ void method();
+ };
+
+ %template(whatever) foo<double>;
+
+06/05/2002: beazley
+ Resolved some tricky issues of multi-pass compilation and
+ and inheritance. The following situation now generates
+ an error:
+
+ class Foo : public Bar {
+ ...
+ };
+
+ class Bar {
+ ...
+ };
+
+ The following code generates a warning about incomplete classes.
+
+ class Bar;
+ class Foo : public Bar { };
+
+ The following code generates a warning about an undefined class.
+
+ class Foo : public Bar { }; // Bar undefined
+
+ This fixes a failed assertion bug reported by Jason Stewart.
+
+06/05/2002: ljohnson
+ [Ruby] Added a warning message for the Ruby module about the lack
+ of support for multiple inheritance. Only the first base class
+ listed is used and the others are ignored. (Reported by Craig
+ Files).
+
+06/03/2002: beazley
+ Fixed a bug with struct declarations and typedef. For example:
+
+ typedef struct Foo Foo;
+ struct Foo {
+ ...
+ };
+
+ A few other subtle struct related typing problems were
+ also resolved.
+
+Version 1.3.12 (June 2, 2002)
+=============================
+
+05/30/2002: beazley
+ Fixed problem related to forward template class declarations and
+ namespaces. Bug reported by Marcelo Matus.
+
+05/30/2002: beazley
+ Added 'make uninstall' target. Contributed by Joel Reed.
+
+05/29/2002: beazley
+ Fixed rather insidious bug with %rename, %feature and template specialization.
+ For example:
+
+ %exception vector::__getitem__ {
+ ... some exception ...
+ }
+
+ template<class T> class vector {
+ ...
+ T __getitem__(int index); // Fine
+ ...
+ };
+
+ template<> class vector<int> {
+ ...
+ T __getitem__(int index); // Oops.
+ ...
+ };
+
+ Now, the %exception directive (and other features) should correctly apply to
+ both vector and specializations.
+
+05/29/2002: beazley
+ Subtle changes to %template() directive. Template arguments are now
+ reduced to primitive types in template matching. For example:
+
+ template<class T> class vector<T *> {
+ ... partial specialization ...
+ }
+
+ typedef int *IntPtr; // Gross typedef
+
+ // Gets the above partial specialization
+ %template(vectorIntPtr) vector<IntPtr>;
+
+ This change is extremely subtle, but it fixes a number of potential
+ holes in Luigi's STL library modules. For example:
+
+ typedef int Integer;
+ %template(vectori) vector<int>;
+
+05/29/2002: beazley
+ Fixed rather insidious typemap bug related to const. const
+ was being discarded through typedefs.
+
+05/29/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added input typemaps for const references to primitive
+ types (in Lib/ruby/ruby.swg).
+
+05/29/2002: cheetah (William Fulton)
+ [Java] The java arrray support functions are enclosed by
+ a SWIG_NOARRAYS #define. Useful if not using arrays and
+ it is desirable to minimise the amount of compiled code.
+
+05/29/2002: cheetah (William Fulton)
+ [Java] Enums were not renamed when using %name or %rename
+ fix.
+
+05/28/2002: ljohnson
+ [Ruby] Modified the name of the wrapper functions for the
+ "new" singleton method and "initialize" instance method for
+ consistency with the other language modules. The wrapper name
+ for the function that implements "new" is alloc_classname and
+ the wrapper name for the function that implements "initialize"
+ is new_classname.
+
+
+05/27/2002: beazley
+ Changes to runtime. Pointer conversion/creation functions
+ now almost always have an extra "flags" argument. For
+ example:
+
+ SWIG_ConvertPtr(obj, void **, swig_type_info *ty, int flags);
+ ^^^^^^^^^^
+ This extra parameter is reserved for future expansion and will
+ be used for more control over pointers in future versions.
+
+05/27/2002: beazley
+ Fix for C++ classes with private assignment operators. It
+ is now possible to safely return objects like this by value.
+ Caveat: the class must provide a copy constructor.
+
+05/26/2002: beazley
+ -proxy option added to many language modules. This is the
+ same as -shadow. We are merely changing terminology.
+
+05/26/2002: beazley
+ [perl] Fixed some inconsistencies in the -package option.
+ -package merely sets the package name to be used on the
+ wrappers. It does not change the name of the shared library
+ file or the name of the generated .pm file. This was
+ broken at some point, but works again now.
+
+05/25/2002: beazley
+ [perl] Fixed [ 475452 ] memory leak in return-by-value.
+ Problem related to static member variables returning newly
+ allocated objects. Reported by Roy Lecates.
+
+05/25/2002: beazley
+ [perl] Fixed [ 513134 ] %BLESSEDMEMBERS isn't always right.
+ Reported by Fleur Diana Dragan.
+
+05/25/2002: beazley
+ Fixed [ 540735 ] -importall and the -I option.
+
+05/25/2002: beazley
+ [guile] Fixed [ 532723 ] Default arg for char* can SegV.
+ Error in guile module. Reported by Brett Williams.
+
+05/25/2002: beazley
+ Subtle change to typemap application code. The "freearg"
+ typemap must exactly match up with the "in" or "ignore"
+ typemap. For example:
+
+ %typemap(in) (char *data, int len) { ... }
+ %typemap(freearg) char *data { ... }
+
+ void foo(char *data, int len);
+
+ In this case, the "in" typemap is applied, but the
+ freearg typemap is not. This is because the freearg
+ typemap doesn't match up with the input argument sequence.
+
+05/25/2002: beazley
+ Fixed [ 548272 ] Default argument code missing braces.
+ Reported by Brett Williams.
+
+05/25/2002: beazley
+ Fixed [ 547730 ] SwigValueWrapper needed for constructors.
+ Reported by William Fulton.
+
+05/25/2002: beazley
+ Undefined identifiers now evaluate to 0 when evaluating
+ preprocessor expressions. For example:
+
+ #if !FOO
+ ...
+ #endif
+
+ where FOO is undefined or set to some non-numeric value.
+
+ Fixes [ 540868 ] #if defined whatever - not parsed.
+ Reported by Adam Hupp.
+
+
+05/24/2002: beazley
+ SWIG now ignores the C++ 'export' keyword.
+
+05/23/2002: beazley
+ Some refinement of type-name mangling to account for pointers, arrays,
+ references, and other embedded type constructs.
+
+05/23/2002: beazley
+ Initial attempt at supporting template partial specialization. At
+ the very least, it is parsed and the classes are stored. Matching
+ of instantiations to specialized version is more limited and based on
+ the SWIG default typemap rules:
+
+ SWIGTYPE *
+ SWIGTYPE []
+ SWIGTYPE &
+
+ Now, why in the world would you want to use this feature? Other
+ than allowing for slightly modified class APIs, this capability is
+ primarily used to provide advanced wrapping support for STL-like
+ objects. It can also be mixed with typemaps. Here is an example:
+
+
+ /* Generic version */
+ template<class T> class vector {
+ %typemap(in) vector<T> * {
+ // A container of objects
+ }
+ };
+ /* Partial specialization (pointers) */
+ template<class T> class vector<T *> {
+ %typemap(in) vector<T> * {
+ // A container of pointers to objects.
+ }
+ };
+ /* Specialization (integers). */
+ template<> class vector<int> {
+ %typemap(in) vector<int> * {
+ // A container of integers.
+ }
+ };
+
+ *** EXPERIMENTAL FEATURE ***
+
+05/23/2002: beazley
+ Enhancement to typemaps. Normally, typemap variables are
+ renamed to avoid conflicts. For example:
+
+ %typemap(in) int * (int temp) {
+ $1 = &temp;
+ }
+
+ This results in code that creates and uses variables "temp1","temp2",
+ "temp3" and so forth depending on how many times the typemap is used.
+ Sometimes you want a single variable instead. To do that, using
+ the following naming scheme:
+
+ %typemap(in) int *(int _global_temp) {
+ }
+
+ Is this case, a single variable _global_temp is emitted in the
+ wrapper functions. It is shared across all typemaps. Repeated
+ typemaps do not replicate the variable---they use the first one
+ emitted.
+ *** NEW FEATURE ***
+
+05/23/2002: beazley
+ Minor enhancement to typemaps. If you have this code,
+
+ %typemap(in) Foo (int somevar = 3) {
+ ...
+ }
+
+ the default value for somevar is now emitted into the wrapper code.
+
+05/22/2002: beazley
+ Fixed %extend to be better behaved in namespaces. If you have code
+ like this:
+
+ namespace foo {
+ struct bar {
+ %extend {
+ void blah();
+ };
+ };
+ }
+
+ SWIG matches the blah() method to a C function named
+ void foo_bar_blah(foo::bar *self).
+
+ This is consistent with the non-namespace version.
+ Bug reported by Marcelo Matus.
+
+05/22/2002: beazley
+ New library files: cpointer.i, carrays.i, cmalloc.i. These
+ provide access to C pointers and memory allocation functions.
+ See Doc/Manual/Library.html for details.
+
+05/22/2002: cheetah (William Fulton)
+ [Java] C type char no longer maps to Java type byte, but to Java type char.
+ It is now treated as a character rather than a signed number. This fits in
+ with the other language modules and is a more natural mapping as char* is
+ mapped as a string of characters. Note that the C signed char type is still
+ mapped to a Java byte.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+05/22/2002: cheetah (William Fulton)
+ [Java] Improved constants wrapping. Constants (#define and %constant) values
+ are now obtained through a JNI call. Previously the value was compiled as
+ Java code, but this didn't work for all cases, eg #define 123ULL.
+
+05/22/2002: beazley
+ Fixed bogus error message with %extend directive and C++
+ access specifiers. Reported by Marcelo Matus.
+
+05/22/2002: beazley
+ Namespaces and enums now work correctly. For example:
+
+ namespace Foo {
+ enum Bar { A, B };
+ }
+
+ Bug reported by Marcelo Matus.
+
+05/21/2002: beazley
+ The %types directive can now be used to specify inheritance relationships
+ in the runtime type system. For example,
+
+ %types(Foo = Bar);
+
+ specifies that Foo isa Bar. Using this is potentially quite dangerous.
+ However, this is useful in certain cases (and in the SWIG library).
+
+05/20/2002: beazley
+ %nodefault and %makedefault directives now require a trailing semicolon.
+ For example:
+
+ %nodefault;
+ ...
+ %makedefault;
+
+ In addition both directives can take a class name. For example:
+
+ %nodefault Foo;
+
+ class Foo { /* No default constructor/destructor */
+ };
+
+ class Bar { /* Default constructor/destructor generated */
+ };
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ If you don't use the trailing semicolon, things will mysteriously break.
+
+05/20/2002: beazley
+ More improvements to type system handling. SWIG now correctly handles
+ template names and parameters in a namespace. For example:
+
+ namespace foo {
+ template<class T> class bar { };
+ typedef int Integer;
+
+ void blah(bar<Integer> *x);
+ };
+
+ In the generated code, all of the typenames are properly qualified.
+
+05/17/2002: cheetah (William Fulton)
+ [Java] deprecated broken -jnic and -jnicpp commandline options. The C or C++
+ JNI calling convention is now determined from the -c++ commandline option.
+
+05/16/2002: cheetah (William Fulton)
+ [Java] The JCALL macros which exist so that the same typemaps can be used
+ for generating both the C and C++ JNI calling conventions no longer appear
+ in the generated code. This is because the output is now passed through the
+ SWIG preprocessor which does the macro expansion for either C or C++ (depending
+ on whether -c++ is passed on the SWIG commandline).
+
+ The generation of the functions used in the array typemaps have been adjusted
+ to take account of this. The side effect is that any typemaps which contained
+ JCALL macros within %{ %} brackets will have to be moved within {} brackets
+ so that the SWIG preprocessor can expand the macros.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+05/13/2002: beazley
+ Class templates may now be used as template parameters. For example:
+
+ template<class T, template<class> class C> class Foo {
+ ...
+ };
+ template<class T> class Bar {
+ ...
+ };
+
+ %template(Fooi) Foo<int, Bar>;
+
+ SWIG doesn't really do anything special with this---it's just
+ another way of specifying a template parameter.
+
+05/13/2002: beazley
+ Minor refinement of template support. Template parameter names are no longer
+ required for types. For example:
+
+ template<bool> class Foo {
+ };
+
+ Obviously, names are required for template<class T>;
+
+05/12/2002: beazley
+ New macro expansion in typemaps. The sequence:
+
+ $descriptor(type)
+
+ Will expand into the SWIG type descriptor structor for
+ the given type. Type may be any abstract datatype.
+ For example:
+
+ $descriptor(int *)
+ $descriptor(int (*)(int,double))
+ $descriptor(vector<int> *)
+
+ Caveat: It is *NOT* currently legal to use other typemap
+ substitution variables in the macro. For example
+ $descriptor($1_type).
+
+ The primary purpose of this modification is to better
+ support typemaps for container objects or to allow typemaps
+ that might be performing type conversions.
+ *** NEW FEATURE ***
+
+05/11/2002: beazley
+ The wrapping of references to primitive types has been
+ changed as follows:
+
+ Arguments of type 'const primitive &' are now passed
+ by value as opposed to pointers. Return values of
+ type 'const primitive &' are returned as values instead of
+ pointers.
+
+ 'primitive' is any one of int, short, long, long long,
+ char, float, double, bool (as well as unsigned variants).
+
+ This change is being made to better support C++ wrapping--especially
+ code that makes use of templates and the STL.
+
+05/11/2002: beazley
+ The %template directive can now be used to access templates
+ in a namespace. For example:
+
+ namespace std {
+ template<class T> class complex {
+ T re, im;
+ public:
+ complex(T _r = T(), T _i = T()) : re(_r), im(_i) { }
+ T real() { return re; }
+ T imag() { return im; }
+ };
+ }
+
+ %template(complex) std::complex<double>;
+
+ Note: There are some very subtle namespace/symbol table
+ management issues involved in the implementation of this.
+ It may not work in certain cases.
+
+05/10/2002: beazley
+ Member template constructor support added. For example:
+
+ template<typename _T1, typename _T2>
+ struct pair {
+ _T1 first;
+ _T2 second;
+ pair() : first(_T1()), second(_T2()) { }
+ template<class _U1, class _U2> pair(const pair<_U1,_U2> &x);
+ };
+
+ To instantiate the template, use %template and %extend.
+ For example, this expands the constructor into a default
+ copy constructor:
+
+ %extend pair {
+ %template(pair) pair<_T1,_T2>;
+ }
+
+ Highly experimental. Other uses may be broken.
+
+05/10/2002: beazley
+ The %extend (%addmethods) directive no longer works unless
+ it appears in the public section of a class. An error
+ message is now generated (as opposed to a segmentation fault).
+
+05/09/2002: beazley
+ New %warnfilter() directive. This directive attaches a warning
+ filter to specific declarations and has the same semantics as
+ %rename, %ignore, %feature, and so forth. For example:
+
+ %warnfilter(501) foo; // Suppress overloaded warning
+ int foo(int);
+ int foo(double);
+
+ or
+
+ %warnfilter(501) Object::foo(double);
+ class Object {
+ public:
+ int foo(int);
+ int foo(double);
+ };
+
+ This feature only suppresses warnings in later stages of code
+ generation. It does not suppress warnings related to preprocessing
+ or parsing.
+ *** NEW FEATURE ***
+
+05/09/2002: beazley
+ SWIG now supports C99 variadic preprocessor macros. For example:
+
+ #define debugf(fmt,...) fprintf(stderr,fmt,__VA_ARGS__)
+
+ The argument "..." is used to indicate variable arguments which
+ are all placed into the special argument name __VA_ARGS__ in
+ the macro expansion.
+
+ SWIG also implements the GNU (##) extension for swallowing the
+ preceding comma when __VA_ARGS__ is empty. For example:
+
+ #define debugf(fmt,...) fprintf(stderr,fmt, ##__VA_ARGS__)
+
+ Here is how this is expanded:
+
+ debugf("%d", 3) --> fprintf(stderr,"%d",3)
+ debugf("Hello") --> fprintf(stderr,"Hello" )
+
+ (notice the deleted comma).
+ *** NEW FEATURE ***
+
+05/08/2002: samjam (Sam Liddicott)
+ Many changes to php module. Shadow classes are now implemented
+ entirely in native C and no need for php-code shadow wrappers
+ Populated template config.m4 and Makefile.in as needed by
+ phpize are generated.
+
+05/08/2002: ljohnson (Lyle Johnson)
+ [Ruby] A copy constructor is now turned into a "clone"
+ instance method (see Dave's change for copy constructors
+ dated 4/7/2002). This seems like the appropriate thing
+ to do for Ruby code.
+
+05/08/2002: ljohnson (Lyle Johnson)
+ [Ruby] Fixed [ 553864 ] Inline destructor code not written.
+
+05/08/2002: beazley
+ %ignore behaves better with constructors, destructors, and the
+ type system in general. For constructors and destructors,
+ %ignore now suppresses the creation of a default constructor
+ or destructor. For example:
+
+ %ignore ~Foo;
+ class Foo {
+ public:
+ Foo();
+ ~Foo();
+ ...
+ };
+
+ In SWIG-1.3.11, ~Foo() simply "disappeared" and the code generator
+ created a wrapper for a default destructor (as if it was never
+ declared in the interface). In SWIG-1.3.12, %ignore suppresses
+ the creation of a destructor if one is actually defined.
+
+ Similarly, even though a declaration is ignored, information
+ may still be needed to properly handle types. For example, here
+ is a very subtle error that is fixed by this change:
+
+ %ignore std::string; // Prevent class wrapping
+ namespace std {
+ class string {
+ ...
+ };
+ %typemap(in) string * {
+ ...
+ }
+ }
+
+ void foo(std::string *s); // Broken.
+
+ Before this fix, %ignore would cause the class definition to disappear.
+ This, in turn, would cause the typemap to be misapplied.
+
+05/08/2002: beazley
+ Minor changes to %rename, %ignore, %feature, and related directives
+ for better support of destructors. Destructors can now be precisely
+ tagged. For example:
+
+ %ignore Foo::~Foo;
+ %feature("action") ~Bar {
+ ...
+ }
+
+ *Developer warning*
+ Operations such as renaming and feature attachment for classes used to
+ be applied to destructors as well. For instance, if you did this:
+
+ %rename(Bar) Foo;
+
+ The operation applied to the class itself, the constructor, and
+ the destructor. This is no longer the case. Now such operations
+ will only apply to the class and the constructor. Note: if you
+ were relying on this for class renaming, be aware that renamed
+ classes should really only be handled at the level of the class itself
+ and not the level of individual declarations in the class (although
+ they can be renamed individually if needed). As far as I know,
+ the Language class is already taking care of this case correctly.
+
+05/07/2002: beazley
+ New set of tests. The Examples/test-suite/errors directory contains
+ tests that try to exercise all of SWIG's error and warning messages.
+
+05/07/2002: beazley
+ Start of a warning framework. Warning messages are now assigned numeric values
+ that are shown in warning messages. These can be suppressed using the
+ -w option. For example:
+
+ swig -w302 example.i
+ swig -w302,305 example.i
+
+ Alternatively, the #pragma preprocessor directive can be used to disable this:
+
+ #pragma SWIG nowarn=302
+ #pragma SWIG nowarn=302,305
+
+ Note: Since SWIG is a multi-pass compiler, this pragma should
+ only be used to change global settings of the warning filter. It should
+ not be used to selectively enable/disable warnings in an interface file.
+ The handling of #pragma occurs in the C++ preprocoessor and affects all
+ subsequent stages of compilation.
+
+ The -Wall option turns on all warnings and overrides any filters that
+ might have been set.
+
+ Warnings can be issued from an interface using %warn. For example:
+
+ %warn "110:%section is deprecated"
+
+ The first part of a warning message is an optional warning number.
+ A complete set of warning numbers is found in Source/Include/swigwarn.h.
+ *** NEW FEATURE ***
+
+05/07/2002: beazley
+ Internal parsing change. Directives to include files now use brackets [ ... ]
+ instead of { ... }.
+
+ %includefile "foo.i" [
+ ...
+ ]
+
+ The use of { ... } was a bad choice because they were included implicitly by
+ the preprocessor and made it impossible to properly detect legitimate missing '}'
+ errors.
+
+04/16/2002-
+05/02/2002: beazley
+ SWIG European Tour: Paris-Amsterdam-Bath.
+
+04/23/2002: beazley
+ The %addmethods directive has been renamed to %extend.
+ For example:
+
+ class Foo {
+ ...
+ };
+
+ %extend Foo {
+ int blah() { ... };
+ int bar() { ... };
+ ...
+ };
+
+ Motivation: the %addmethods directive can be used for many
+ other tasks including adding synthesized attributes, constructors,
+ and typemaps. Because of this, "addmethods" is somewhat misleading.
+ %extend more precisely describes this operation---extension of a
+ class or structure.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ %addmethods still works via a macro definition. However,
+ a warning message may be generated. Errors involving %addmethods
+ will actually refer to the %extend directive.
+
+04/23/2002: beazley
+ Further refinement of the type system. Typedef now
+ propagates through functions, pointers to functions,
+ and pointers to member functions.
+ For example:
+
+ typedef int Integer;
+ void foo(int (*x)(int), Integer (*y)(Integer));
+
+ In this case, arguments 'x' and 'y' have exactly
+ the same type (and would obviously accept objects
+ of either type).
+
+ Similarly, consider this:
+
+ class Foo {
+ };
+
+ typedef Foo Bar;
+ void bar(int (Foo::*x)(int), int (Bar::*y)(int));
+
+ In this case, arguments x and y are the same
+ type (via typedef).
+
+04/22/2002: beazley
+ SWIG now generates a warning message if any part of
+ an expression involves values from a private part of a class.
+ For example:
+
+ class Foo {
+ private:
+ static int X;
+ public:
+ void blah(int a, int b = X); // Warning
+ };
+
+ In this case, the default argument is ignored. There
+ are workarounds, but they are rather clumsy. For instance,
+ you might do this:
+
+ %feature("action") blah(int,int) {
+ if ($nargs == 1) {
+ result = blah(arg1);
+ } else {
+ result = blah(arg1,arg2);
+ }
+ }
+ void blah(int a, int b = 0);
+
+
+04/21/2002: beazley
+ Use of the %inline directive inside a namespace is
+ forbidden and now generates an error message. This is
+ not allowed since the inlined code that is emitted is
+ not placed inside a namespace. This confuses other
+ stages of parsing.
+
+04/21/2002: beazley
+ Some bug fixes to casting operations and expression
+ parsing. Due to some parsing issues, it is not
+ currently possible to use casts for all possible
+ datatypes. However, the common cases work.
+
+04/20/2002: beazley (Amsterdam)
+ Member templates now work. Simply use the %template
+ directive inside a class or %addmethods to create
+ instantiations (see Doc/Manual/SWIGPlus.html). Supporting
+ this was easy---earlier changes to templates made it
+ possible using only a two-line modification to the parser
+ and a few minor modifications elsewhere. Hmmm, come to
+ think of it, the smoke was rather thick in that Internet "cafe".
+ *** NEW FEATURE ***
+
+04/19/2002: beazley (TGV)
+ Improved handling of non-type template parameters. For example:
+
+ vector<int,100>;
+
+ Simple numbers and strings can be used with the %template
+ directive as well. For example:
+
+ %template(vecint100) vector<int,100>;
+
+ Note: Arithmetic expressions are not currently allowed.
+
+ Default template arguments now work and do not have to
+ be given to %template.
+
+04/18/2002: beazley (Paris)
+ Change in internal template handling. Template
+ parameters are now fully integrated into the type
+ system and are aware of typedefs, etc. This builds
+ upon the change below.
+
+ *** DEVELOPER WARNING ***
+ Word of caution to language module writers. The "name"
+ parameter of certain parse tree nodes (classes, functions, etc.)
+ may be parameterized with types. This parameterization is
+ done using SWIG type-strings and not the underlying C version.
+ For example,
+
+ int max<int *>(int *,int *)
+
+ has a name of "max<(p.int)>". If you use the name directly,
+ you may get syntax errors in the generated code. To fix this,
+ use SwigType_namestr(name) to convert a parameterized name
+ to a C name with valid syntax. The internal version is
+ used to reduce template types to a common representation
+ and to handle issues of typedef.
+
+04/16/2002: beazley (somewhere over the Atlantic)
+ Enhancement of typedef resolution. The type system is now
+ aware of template arguments and typedef. For example:
+
+ typedef int Integer;
+
+ foo(vector<int> *x, vector<Integer> *y);
+
+ In this case, vector<int> and vector<Integer> are
+ the same type. There is some interaction between this
+ mechanism and the implementation of typemaps. For example,
+ a typemap defined for vector<int> * would apply to either type.
+ However, a typemap for vector<Integer> * would only apply to
+ that type.
+
+ Typedefs and typemaps and matched by left-most expansion.
+ For example:
+
+ vector<Integer,Integer> -->
+ vector<int, Integer> -->
+ vector<int, int>
+
+
+04/24/2002: cheetah (William Fulton)
+ [Java] Changes to Java shadow classes.
+ Overcomes a bug where the module assumed that a pointer to a derived
+ class could be used in place of a pointer to a base class. Thanks
+ to Stephen McCaul for analysing the bug and submitting patches.
+
+ A consequence is that the getCPtr() method in each shadow class has
+ disappeared and has been replaced with a getCPtrXXX(), where XXX is the
+ shadow class name. If you have code that previously used getCPtr(),
+ and the associated class is wrapping a C struct or a C++ class that
+ is not involved in an inheritance chain, just use the new method. If
+ however, the class is involved in an inheritance chain, you'll have
+ to choose which pointer you really want. Backwards compatibility
+ has been broken as not using the correct pointer can lead to weird bugs
+ through ill-defined behaviour. If you are sure you want the old methods,
+ you could add them back into all shadow classes by adding this at the
+ beginning of your interface file:
+
+ %pragma(java) allshadowcode=%{
+ public long getCPtr(){
+ return swigCPtr;
+ }
+ %}
+
+ Please see entry dated 07/23/2002 to see how to do this after the deprecation
+ of the allshadowcode pragma.
+
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+04/13/2002: beazley
+ Fixed problem with default arguments and references. Declarations such
+ as this should now work:
+
+ void foo(const string &x = "Hello");
+
+04/12/2002: beazley
+ Added typemap $* substitutions for typemaps involving arrays.
+ Requested by William Fulton.
+
+04/11/2002: beazley
+ Template specialization is now supported. For example:
+
+ template<> class vector<int> {
+ ...
+ };
+
+ When the %template directive is used, it will use a specialization
+ if one is defined. There are still some limitations. Partial
+ specialization is not supported. A template of type <void *> does
+ not match all pointers.
+ *** NEW FEATURE ***
+
+04/11/2002: beazley
+ Major change to template wrapping internals. Template declarations are
+ no longer processed as macros but now result in real parse-tree
+ nodes. The %template directive expands these nodes into a
+ specific instantiation. This change enables a number of
+ new and interesting capabilities:
+
+ Directives such as %rename, %feature, and %addmethods can
+ now be applied to uninstantiated templates. For example:
+
+ %rename(barsize) vector::bar(char *buf, int len);
+ ...
+ template<typename T> class vector {
+ public:
+ ...
+ void bar(char *buf);
+ void bar(char *buf, int len); // Renamed
+ ...
+ };
+
+ %template(intvector) vector<int>; // Renaming carries through
+
+
+ By parsing templates into an internal data structure, it will
+ be possible to support specialization (and maybe partial
+ specialization).
+
+ This is highly experimental and a work in progress.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ In SWIG-1.3.11, template declarations were simply processed
+ as weird macros. No other information was retained. This
+ made it impossible to support more advanced features and
+ complicated many other parts of the implementation.
+
+04/09/2002: beazley
+ Change to template class wrapping. There were a variety of
+ "issues" with the old approach related to parsing, the type
+ system, and namespaces. These changes are meant to rectify
+ some of these problems:
+
+ A specific instantiation of a template can now be specified
+ by including the class inline like this:
+
+ class vector<int> {
+ public:
+ vector();
+ ~vector();
+ ... whatever ...
+ };
+
+ This is template specialization, but partial specialization is
+ not yet implemented.
+
+ The %template directive has been modified to expand roughly as
+ follows:
+
+ %template(vecint) vector<int>;
+
+ becomes
+
+ %rename(vecint> vector<int>;
+ class vector<int> {
+ public:
+ vector();
+ ...
+ };
+
+ Note that this simply builds upon the code above (templates
+ included inline).
+
+ This modified approach to wrapping fixes some subtle type
+ issues. For instance, you can now define typemaps and typedefs
+ like this:
+
+ %typemap(in) vector<int> * {
+ ...
+ }
+ typedef vector<int> intvector;
+ ...
+ void blah(intvector *v); // Gets the above typemap
+
+ This did not work in SWIG-1.3.11 due to a peculiarity of
+ the template implementation.
+
+ %template(name) no longer installs the template as a class
+ with name "name". This might break %addmethods as described
+ in the manual. For example:
+
+ %template(vecint) vector<int>;
+ %addmethods vecint { // Fails. vecint not a class
+ ...
+ };
+
+ To fix this, just use the template name instead:
+
+ %addmethods vector<int> {
+ ...
+ }
+
+ Note: This technique might be a way to implement some bizarre
+ template specialization techniques. For example:
+
+ %addmethods vector<int> {
+ // Only applied if vector<int> instantiated later
+ %typemap(in) vector<int> * {
+ ...
+ }
+ ...
+ };
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+04/08/2002: beazley
+ Fixed [ 540868 ] #if defined whatever - not parsed. SWIG should
+ now correctly handle preprocessor directives like this:
+
+ #if defined __cplusplus
+ ...
+ #endif
+
+ Note: was implemented previously, but there was a minor bug.
+ Reported by Adam Hupp.
+
+04/07/2002: beazley
+ %readonly and %readwrite are deprecated due to a change in the
+ implementation. Instead of being pragmas, mutability is now
+ controlled as a "feature" using the following two directives:
+
+ %immutable;
+ int x; // read-only variable
+ int y; // read-only variable
+ %mutable;
+ int z; // Modifiable
+
+ %immutable and %mutable are much more powerful than their older
+ counterparts. They can now pinpoint a specific declaration like
+ this:
+
+ %immutable x; /* Any x */
+ %immutable Foo::x; /* x in class Foo */
+
+ In fact, the matching algorithm is the same as for %rename,
+ %ignore, and other directives. This means that the declaration
+
+ %immutable Foo::x;
+
+ would not only apply to class Foo but to all derived classes
+ as well.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ %immutable and %mutable must be terminated by a semi-colon. This
+ differs slightly from the older %readonly and %readwrite directives.
+ Since %immutable and %mutable can be applied to declarations the
+ semicolon is needed to distinguish between a global feature and
+ one targeted to a single declaration. Note: this incompatibility is the
+ primary reason for changing the name of the directive.
+
+04/07/2002: beazley
+ New handling of copy constructors. If a class defines
+ constructors like this:
+
+ class Foo {
+ public:
+ Foo();
+ Foo(const Foo &); // Copy constructor
+ ...
+ };
+
+ SWIG now generates a function copy_Foo() for the copy
+ constructor.
+
+ In previous verions, this generated a name-clash and an
+ error message. To preserve backwards compatibility, SWIG
+ does not change the behavior if %rename is used to resolve
+ the name conflict. However, if no name resolution is made,
+ this new approach is used.
+
+ Copy constructors may be handled as a special case in the
+ target language. However, this is up to the language module
+ itself.
+
+04/07/2002: beazley
+ The %template directive is now namespace aware. This allows
+ code like this:
+
+ namespace foo {
+ template<typename T> max(T a, T b) { return a > b ? a : b; }
+ }
+
+ using namespace foo;
+ %template(maxint) max<int>; // Ok
+
+ namespace bar {
+ using foo::max;
+ %template(maxdouble) max<double>; // Ok
+ }
+
+ Caveat: the template name supplied to %template must be defined in the
+ same scope in which the %template directive appears. This code is
+ illegal:
+
+ %template(maxint) foo::max<int>;
+
+04/07/2002: beazley
+ Minor enhancement to preprocessor. The preprocessor can now perform
+ string comparison. For example:
+
+ #define A "hello"
+ ...
+ #if A == "hello"
+ ...
+ #endif
+
+ The primary use of this is in SWIG macros. For example:
+
+ %define FOO(x)
+ #if #x == "int"
+ /* Special handling for int */
+ ...
+ #endif
+ %enddef
+
+ Normal users can probably safely ignore this feature. However, it may
+ be used in parts of the SWIG library.
+
+04/07/2002: beazley
+ Further refinement of default constructor/destructor wrapper generation.
+ SWIG is now much more aware of pure virtual methods. For instance:
+
+ class A { /* Abstract */
+ public:
+ virtual void method1() = 0;
+ virtual void method2() = 0;
+ };
+ class B : public A { /* Abstract */
+ public:
+ virtual void method1() { };
+ };
+
+ class C : public B { /* Ok */
+ public:
+ virtual void method2() { };
+ };
+
+ In this case, SWIG will only generate default constructors for C.
+ Even though B looks fine, it's missing a required method and is abstract.
+
+04/04/2002: beazley
+ Subtle change to structure data member access. If you
+ have a structure like this:
+
+ struct Foo {
+ Bar b;
+ };
+
+ The accessor functions for b are generated as follows:
+
+ (1) If b is *not* defined as a structure or class:
+
+ Bar Foo_b_get(Foo *self) {
+ return self->b;
+ }
+ void Foo_b_set(Foo *self, Bar value) {
+ self->b = value;
+ }
+
+ (2) If b *is* defined as a structure or class:
+
+ Bar *Foo_b_get(Foo *self) {
+ return &self->b;
+ }
+ void Foo_b_set(Foo *self, Bar *value) {
+ self->b = *value;
+ }
+ See the "Structure data members" section of Doc/Manual/SWIG.html
+ for further details.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ This may break interfaces that relied on a lot of a undeclared
+ structure and class names. To get the old behavior, simply
+ use a forward declaration such as "struct Bar;"
+
+04/04/2002: beazley
+ C++ namespace support added. SWIG supports all aspects of
+ namespaces including namespace, using, and namespace alias
+ declarations. The default behavior of SWIG is to flatten
+ namespaces in the target language. However, namespaces are
+ fully supported at the C++ level and in the type system.
+ See Doc/Manual/SWIGPlus.html for details on the implementation.
+
+04/02/2002: cheetah (William Fulton)
+ [Java] Sun has modified javac in jdk1.4 to no longer compile
+ an import of an unnamed namespace. To fix this SWIG no longer
+ generates the import for packageless classes.
+ http://developer.java.sun.com/developer/bugParade/bugs/4361575.html
+ As reported SF #538415.
+
+03/27/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added support for pointer-to-member, similar to that
+ for the Python module. Remarkably similar. Also added a new
+ example for this (Examples/ruby/mpointer), which is remarkably
+ similar to the Python example of the same name.
+
+03/26/2002: ljohnson (Lyle Johnson)
+ [Ruby] Made a few minor edits to the "Advanced Topics"
+ chapter of the SWIG manual and added a new major section
+ about how to create multi-module Ruby packages with SWIG.
+
+03/26/2002: ljohnson (Lyle Johnson)
+ [Ruby] Removed all of the old Ruby pragmas. If any of this
+ functionality is truly missed we can resurrect it, preferably
+ with some kind of feature-based directive.
+
+03/25/2002: ljohnson (Lyle Johnson)
+ [Ruby] Fixed SWIG exception library support for Ruby, which
+ has apparently been broken for some time. Luckily, no one seems
+ to have noticed.
+
+03/23/2002: beazley
+ C++-namespace support in SWIG directives.
+
+ %addmethods:
+
+ The %addmethods directive now accepts a fully qualified classname
+ and can be used inside C++ namespace declarations. For example:
+
+ // Attaches to the class Foo::Bar below
+ %addmethods Foo::Bar {
+ int somemethod() { ... }
+ };
+
+ namespace Foo {
+ class Bar {
+ public:
+ ...
+ };
+
+ // Attaches to the class Bar above
+ %addmethods Bar {
+ int othermethod() { ... };
+ }
+ }
+
+ %feature, %rename, %ignore, %exception, and related directives:
+
+ Namespaces are fully integrated into the renaming and declaration
+ matcher. For example:
+
+ %rename(display) Foo::print; // Rename in namespace Foo
+ %ignore Foo::Bar::blah; // Ignore a declaration
+
+ %rename directives can be placed inside namespace blocks as well. For
+ example:
+
+ namespace Foo {
+ %rename(display) print; // Applies to print below
+
+ void print();
+ };
+
+ Most other SWIG directives should work properly inside namespaces.
+ No other changes are needed.
+
+03/22/2002: beazley
+ Some changes to internal symbol table handling. SWIG no longer
+ manages structures and unions in a separate namespace than normal
+ declarations like ANSI C. This means you can't have a structure
+ with the same name as a function. For example:
+
+ struct Foo {
+ ...
+ }
+
+ int Foo() { ... }
+
+ This approach is more like C++. It's not clear that SWIG ever
+ really supported the ANSI C anyways---using the same name would
+ almost certainly generate a name-clash in the target language.
+
+03/22/2002: ljohnson (Lyle Johnson)
+ [Ruby] Fixed [ 517302 ] for handling of renamed overloaded
+ constructors. Now, renamed overloaded constructors are converted
+ into class singleton methods (basically acting as "factory"
+ methods).
+
+03/21/2002: beazley
+ Fixed [ 532957 ] %ignore parse error and casting operator.
+ Reported by William Fulton.
+
+03/18/2002: beazley (** ADVANCED USERS ONLY **)
+ Added support for dynamic casting in return values. A somewhat
+ common problem in certain C++ programs is functions that hide
+ the identity of underlying objects when they are returned
+ from methods and functions. For example, a program might include
+ some generic method like this:
+
+ Node *getNode();
+
+ However, Node * may just be base class to a whole hierarchy
+ of different objects. Instead of returning this generic Node *,
+ it might be nice to automatically downcast the object into the
+ appropriate type using some kind dynamic cast.
+
+ Assuming you understand the peril involved, a downcast can now
+ be performed using the following function in the run-time type
+ checker:
+
+ swig_type_info *SWIG_TypeDynamicCast(swig_type_info *, void **ptr);
+
+ This function checks to see if the type can be converted to another
+ type. If so, a different type descriptor (for the converted type)
+ is returned. This type descriptor would then be used to create
+ a pointer in the target language.
+
+ To use this, you would write a typemap similar to this:
+
+ %typemap(out) Node * {
+ swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **) &$1);
+ $result = SWIG_NewPointerObj($1, ty);
+ }
+
+ Alternatively,
+
+ %typemap(out) Node * = SWIGTYPE *DYNAMIC;
+
+ To make the typemap have any effect, you have to write a supporting
+ function that knows how to perform downcasting. For example:
+
+ %{
+ static swig_type_info *
+ Node_dynamic_cast(void **ptr) {
+ Node **nptr = (Node **) ptr;
+ Element *e = dynamic_cast<Element *>(*nptr);
+ if (e) {
+ *ptr = (void *) e;
+ return SWIGTYPE_p_Element;
+ }
+ Data *d = dynamic_cast<Data *>(*nptr);
+ if (d) {
+ *ptr = (void *) d;
+ return SWIGTYPE_p_Data;
+ }
+ return 0;
+ }
+ %}
+
+ There is no restriction on how types are determined. dynamic_cast<>
+ uses C++ RTTI. However, if you had some other mechanism for determining
+ the type, you could use that here. Note: it is important to save
+ the new pointer value back into the argument as shown. When downcasting,
+ the value of the pointer could change.
+
+ Finally, to make the casting function available, you have to register
+ it with the run-time type checker. Put this macro in your interface file.
+
+ DYNAMIC_CAST(SWIGTYPE_p_Node, Node_dynamic_cast);
+
+ Note: this feature does not introduce a performance penalty on
+ normal SWIG operation. The feature is only enabled by writing
+ a new typemap that explicitly calls SWIG_TypeDynamicCast() to
+ make a conversion.
+
+ Examples/test-suite/dynamic_cast.i contains a simple example.
+ This feature is not supported in the Java module due to differences
+ in the type-checking implementation.
+
+ *** EXPERIMENTAL FEATURE ***
+
+03/17/2002: beazley
+ Small change to type-name handling of unnamed structures and
+ typedef. If a structure of this form appears:
+
+ typedef struct {
+ ...
+ } Foo;
+
+ Then 'Foo' is used as the proper typename for the structure.
+ Furthermore, Foo can now be used as a name in C++ inheritance.
+ SWIG was already kind of doing this, but this modification refines
+ the implementation to more closely follow the C++ ARM, section
+ 7.1.3, p. 106. This fixes a couple of obscure corner cases.
+
+03/16/2002: beazley
+ Modified C++ inheritance with a few enhancements. First, type information
+ needed for casting and type-equivalence is generated even when base-classes
+ aren't defined in the interface. For example:
+
+ class Foo : public Bar { /* Bar unspecified */
+ public:
+ ...
+ };
+
+ void blah(Bar *b);
+
+ In this case, the blah() function still accepts Foo * even though nothing
+ is really known about Bar. Previous SWIG versions would just generate
+ a type error.
+
+ Inheritance has also been modified to work through typedef. For example:
+
+ class Bar {
+ };
+
+ typedef Bar OtherBar;
+ class Foo: public OtherBar {
+ }
+
+ In this case, the base class of OtherBar is correctly resolved back to
+ Bar. The use of the name OtherBar is lost in this resolution (the wrappers
+ will simply use Bar instead of the typedef name OtherBar).
+
+03/13/2002: beazley
+ %typemap, %apply, and related directives can now appear inside
+ class definitions.
+
+03/13/2002: beazley
+ Fixed a variety of problems related to compiling SWIG on 64-bit
+ platforms.
+
+03/12/2002: beazley
+ Fixed problem with "ignore" and "in" typemaps. Local variables
+ associated with "in" were being added to the wrapper function even
+ though they were never used. Mostly harmless, but it would lead
+ to a variety of compilation warnings.
+
+03/12/2002: beazley
+ Some changes to the internal type system and handling of nested C++
+ types. In previous versions of SWIG, if you had the following:
+
+ class Foo {
+ public:
+ typedef int Blah;
+ };
+ class Bar : public Foo {
+ public:
+ void somemethod(Blah x);
+ };
+
+ The argument type in somemethod() would implicitly be set to Bar::Blah.
+ Although this is technically allowed, it breaks typemaps. For example:
+
+ %typemap(in) Foo::Blah { ... }
+
+ doesn't match like you expect. This has been changed in SWIG-1.3.12.
+ Now, types are expanded using the class in which they were defined.
+ So, the argument type in somemethod() will be Foo::Blah---since the
+ type Blah was defined in Foo.
+
+03/10/2002: beazley
+ Fixed some subtle type scoping problems with typedef and C++ classes.
+ For example:
+
+ typedef int Blah;
+ class Bar {
+ public:
+ typedef double Blah;
+ void foo(Blah x, ::Blah y);
+ ...
+ }
+
+03/10/2002: beazley
+ Highly experimental change to handle variable length arguments.
+ First, there is no portable or reliable way to wrap
+ a varargs function in full generality. However, you *can* change
+ the function signature using %varargs.
+
+ %varargs(char *) fprintf;
+ ...
+ void fprintf(FILE *f, char *fmt, ...);
+
+ In this case, the variable length parameter "..." is
+ simply replaced by the parameters given in %varargs. This
+ results in a function like this:
+
+ void fprintf(FILE *f, char *fmt, char *s);
+
+ More than one argument can be used and default values
+ can be defined. For example, this code specifies a
+ maximum of four arguments.
+
+ %varargs(char *x1 = 0, char *x2 = 0, char *x3 = 0, char *x4 = 0) fprintf;
+
+ *** EXPERIMENTAL NEW FEATURE ***
+
+03/10/2002: beazley
+ Change to handling of variable length arguments. varargs
+ is now handled as a proper parameter and is passed to the
+ code generator. However, it still can't be handled correctly
+ (and will generate a typemap warning). This change has been
+ made to better incorporate variable length arguments with other
+ directives such as %ignore, %rename, %feature, and so forth.
+
+03/10/2002: beazley
+ Fixed [ 522555 ] Syntax error parsing "define" construct. SWIG
+ is a little more restrictive in determining #define statements
+ that will be wrapped as constants. Also added a better parser
+ error rule for handling bad constants.
+
+03/08/2002: cheetah (William Fulton)
+ [Java] Bug fix: Classes renamed with %rename that are derived from
+ another class generate more appropriate shadow class code.
+
+03/08/2002: cheetah (William Fulton)
+ [Java] Fixed SF [ #523632 ] and [ #513335 ] both reported by Israel
+ Tanner. Support for types that are used which are in a typedef. The
+ appropriate shadow class name is generated. Also generated correct
+ shadow classname when a templated class is used within another
+ templated class. See the cpp_typedef.i testcase.
+
+03/08/2002: cheetah (William Fulton)
+ [Java] Bug fix: No type was generated in shadow classes for types
+ that weren't wrapped by SWIG. The type is treated as a raw
+ pointer, ie no shadow class.
+
+02/22/2002: beazley
+ Refined the matching algorithm used by %rename, %ignore, and
+ %feature. If a type signature is supplied, it must exactly
+ match that used in the declaration---including any use of
+ const. For example:
+
+ %rename(foo1) foo(int);
+ %rename(bar1) bar(int) const;
+
+ class Blah {
+ public:
+ void foo(int); // Matched --> foo1
+ void foo(int) const; // Not matched
+ void bar(int); // Not matched
+ void bar(int) const; // Matched --> bar1
+ }
+
+ In previous versions, a non-const specification would match
+ both the non-const and const declarations. However, the whole
+ point of %rename and related directives is that they be able
+ to precisely pinpoint exact declarations in an interface. This
+ fixes the problem.
+
+02/21/2002: beazley
+ Reworked the handling of default constructor and destructors.
+ SWIG now makes a preliminary pass over the parse tree to discover
+ which classes support default allocation. This fixes a number
+ of very subtle issues in code generation and call/return by value.
+
+02/18/2002: cheetah (William Fulton)
+ Improved support on Cygwin: Perl, Python, Tcl, Ruby and Java should
+ work out of the box, barring the runtime library. Removed dllwrap
+ and replaced with newly working gcc -shared instead for Cygwin.
+ All this will require the new improved binutils 20010802 and later,
+ but the latest Cygwin is usually the best recommendation.
+
+02/15/2002: beazley
+ Fixed some problems related to wrapping of global variables
+ and Perl shadow classes. Reported by Chia-liang Kao.
+
+02/15/2002: ljohnson (Lyle Johnson)
+ [Ruby] Made a fix to the code generation for C++ class
+ constructors so that we get both a "new" singleton method
+ and an "initialize" instance method for each class. This
+ change enables developers to derive new Ruby classes from
+ SWIG-wrapped C++ classes and then override their initialize
+ methods to provide subclass-specific instance initialization.
+
+02/15/2002: ljohnson (Lyle Johnson)
+ [Ruby] Massive documentation update for the Ruby module,
+ contributed by Craig Files.
+
+02/14/2002: ljohnson (Lyle Johnson)
+ [Ruby] Bug fix: An error in the SWIG runtime support for Ruby
+ was causing several of the examples to fail. Reported by
+ William Fulton.
+
+02/14/2002: ljohnson (Lyle Johnson)
+ [Ruby] Bug fix: Enumerations defined within a class (such
+ as those seen in the Examples/ruby/enum example) were not
+ being exported with the correct names. Reported by William
+ Fulton.
+
+02/13/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added a warning message when we run across overloaded
+ class constructors for C++ code, that this is currently not
+ supported (even if the overloads have been %renamed). For an
+ example of where this doesn't work, see Examples/ruby/operator.
+
+02/13/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added an "ignored" warning message when the parser runs
+ across an operator!=() declaration for C++ code.
+
+02/11/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added the "import", "import_template", "operator" and
+ "template" examples.
+
+02/11/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added multi-module support.
+
+02/09/2002: ljohnson (Lyle Johnson)
+ [Ruby] Added the missing "#define SWIG_NOINCLUDE" at the top of
+ the wrapper code when the '-c' option is used.
+
+02/09/2002: ljohnson (Lyle Johnson)
+ Corrected a minor off-by-one error for the size of the
+ swig_types[] array that's generated in the wrapper code.
+
+02/08/2002: beazley
+ Fixed SF [ #515058 ] Wrong code for C++ templates.
+ Reported by Israel Taller.
+
+Version 1.3.11 (January 31, 2002)
+=================================
+
+01/30/2002: beazley
+ Fix to pass/return by value for C++ objects that define
+ no default constructor. Changes to the typemap system
+ made it impossible to wrap C++ objects with no default
+ constructor. This has been fixed, but the solution
+ involves some clever template magic contributed by
+ William Fulton. Please see the comments in the file
+ Lib/swig.swg for further details. This solution is
+ experimental and may be refined in a future release.
+
+01/30/2002: beazley
+ Global variables and member data of type "const char *"
+ can be set, but the old value is silently discarded without
+ any garbage collection. This may generate a memory leak.
+ This change is needed to more safely handle variables
+ like this:
+
+ const char *foo = "Hello World\n";
+
+ In this case, it's not safe to free the old value. However,
+ SWIG can dynamically allocate a new value and make foo point
+ to it. To fix this memory leak, you can probably do this:
+
+ %clear const char *foo;
+ %apply char * {const char *foo};
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+01/30/2002: beazley
+ Two minor typemap enhancements have been added. First,
+ typemaps can issue a warning message by including a special
+ warning attribute. For example:
+
+ %typemap(in,warning="I'm going to do something dangerous") ...
+
+ The warning message will show up whenever the typemap is
+ applied.
+
+ Second, a typemap can force a no-match by defining
+
+ %typemap(in) sometype "pass"
+
+ If this is used, the typemap system will *not* record a
+ typemap match for "sometype". This can be used to block
+ selected typemaps. For example, if you wanted to disable
+ a typemap feature for some type, you could do this.
+
+ // Do not allow global variables of type 'const char *' to be set.
+ %typemap(varin) const char * "pass"
+
+ It might also be possible to use this to do subtle and
+ strange things with typemaps. For example, if you wanted to
+ make 'blah *' an output value and 'const blah *' an input
+ parameter, you might do this:
+
+ %typemap(ignore) blah *(blah temp) {
+ $1 = &temp;
+ }
+ %typemap(argout) blah * {
+ ... return a value ...
+ }
+ /* Block unqualified typemaps defined above */
+ %typemap(ignore) const blah * "pass"
+ %typemap(argout) const blah * "pass"
+ %typemap(in) const blah * {
+ ... get input value ...
+ }
+
+ (This potential applications of typemaps suggested by Greg Stein).
+ *** NEW FEATURE ***
+
+01/29/2002: cheetah (william fulton)
+ [Java] Bug fix: No enumerations were wrapped when the -shadow
+ commandline option was not specified. Reported by Israel Taller.
+
+01/28/2002: cheetah (william fulton)
+ [Java] Global arrays are successfully wrapped. In fact they started
+ mostly working in SWIG-1.3.10.
+
+01/28/2002:richardp
+ Added first attempt at C++ and -shadow support for PHP4 module,
+ please test and mail me if any problems/ideas on improving it.
+
+ There is a known problem with uninitialized member variables,
+ please see Examples/php4/sync/README for details.
+
+ Also more PHP documentation added to Doc/Manual/Php.html
+
+01/27/2002:beazley
+ The ANSI C size_t type is now recognized as an integer by default.
+
+01/26/2002:beazley
+ long long and unsigned long long support added to many language modules.
+ This is not a portable feature and will require compiler support
+ for the long long type. In target languages that do not support
+ long long (e.g., Tcl and Perl), numbers are converted to a string
+ of digits. This prevents their use in arithmetic calculations, but
+ still allows values to be set from a string.
+
+ long long support requires the use of the strtoll() and strtoull()
+ functions as well as the 'lld' and 'llu' format specifiers
+ of sprintf().
+
+01/26/2002:beazley
+ Fixed [ #501827 ] Delete method is not called. The Tcl
+ module wasn't correctly calling destructors when they
+ were defined using %addmethods. This has been fixed.
+ Reported by Reinhard Fobbe.
+
+01/26/2002: beazley
+ Better support for long long and unsigned long long. Typemaps
+ have been included in a number of modules for handling these types.
+ In addition, the parser has been modified to accept long long
+ literals such as 1234LL and 1234ULL.
+
+01/27/2002: cheetah (william fulton)
+ [Java] A C char[] is mapped to a Java String which is the default
+ SWIG handling of char[] and char*. It used to be mapped to byte[].
+ Note that a C signed char[] array is mapped to byte[].
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+01/25/2002: beazley
+ Fixed a problem with return-by-value, C++, and
+ objects that define no default constructor.
+ Reported by Joel Reed.
+
+01/25/2002: cheetah (william fulton)
+ [Java] Overhaul of the Java module. The C code generation is now
+ done from typemaps.
+
+01/24/2002: cheetah (william fulton)
+ [Java] Support for arrays of enum pointers
+
+01/20/2002: cheetah (william fulton)
+ [Java] Error checking for null Java objects being passed to native
+ functions. Exception thrown now whereas before the JVM crashed.
+
+01/18/2002: cheetah (william fulton)
+ [Java] Corrected behaviour for functions that take arrays. For
+ example, when this c function:
+
+ void arrayfn(int array[]);
+
+ is wrapped the corresponding native function
+
+ public final static native void arrayfn(int[] array);
+
+ is produced. Previously if the C function made any changes to the
+ array elements, these were not reflected back into the Java array.
+ This has now been corrected so that the changes are propogated back
+ to Java and the calling function will see these changes. This is
+ how pure Java functions work, ie arrays are passed by reference.
+
+01/15/2002:mkoeppe
+ [Guile] New file cplusplus.i with C++ typemaps contributed
+ by Marcio Luis Teixeira <[email protected]>.
+
+01/11/2002: cheetah (william fulton)
+ [Java] Changed mapping of C long to Java type. Was mapped to Java
+ long, now mapped to Java int. If you want the previous mapping to
+ Java long use this approach in your interface file:
+
+ %clear long;
+ %typemap(jni) long "jlong"
+ %typemap(jtype) long "long"
+ %typemap(jstype) long "long"
+
+ %clear long[ANY];
+ %typemap(jni) long[ANY] "jlongArray"
+ %typemap(jtype) long[ANY] "long[]"
+ %typemap(jstype) long[ANY] "long[]"
+ %typemap(in) long[ANY] {write me for array support}
+ %typemap(out) long[ANY] {write me for array support}
+ %typemap(argout) long[ANY] {write me for array support}
+ %typemap(freearg) long[ANY] {write me for array support}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+ This new mapping is more appropriate when interfacing to 32 bit
+ applications which are used in the current 32-bit JVMs. For future
+ 64-bit JVMs you may have to change these mappings - eg on Unix LP64
+ systems, but not on Microsoft 64bit Windows which will be using a
+ P64 IL32 model. This may be automated in a future version of SWIG.
+
+01/10/2002:beazley
+ Fixed [ 501677 ] %init block in wrong place. Reported
+ by Luigi Ballabio.
+
+01/09/2002: cheetah (william fulton)
+ [Java] Default support for the long long type. signed long long is
+ mapped to a Java long. unsigned long long is mapped to BigInteger.
+
+01/09/2002:beazley
+ Experimental change to parser to better support mixing of
+ int, long, short, unsigned, float, and double. The parser
+ should now support types like this:
+
+ short unsigned int
+ int unsigned short
+ unsigned short int
+ unsigned int short
+
+ This change also enables a type of 'long double' (previously
+ unsupported) to be used.
+ *** NEW FEATURE ***
+
+01/05/2002: cheetah (william fulton)
+ [Java] Casting fix for when function return type is a pointer as
+ reported by Gary Pennington 2002-01-05. The upper 32bits of the
+ 64 bit jlong will have contained junk for 32bit pointers.
+
+01/05/2002: cheetah (william fulton)
+ [Java] Better pointer handling in Java is possible as the
+ INPUT, OUTPUT and INOUT typemaps have been added into typemaps.i.
+
+01/05/2002: cheetah (william fulton)
+ [Java] $null can be used in input typemaps to return early from JNI
+ functions that have either void or a non-void return type. Example:
+
+ %typemap(check) int * %{
+ if (error) {
+ SWIG_exception(SWIG_IndexError, "Array element error");
+ return $null;
+ }
+ %}
+
+ If the typemap gets put into a function with void as return, $null
+ will expand to nothing:
+
+ void jni_fn(...) {
+ if (error) {
+ SWIG_exception(SWIG_IndexError, "Array element error");
+ return ;
+ }
+ ...
+ }
+
+ otherwise $null expands to zero, where javareturntype is either a
+ pointer or a primitive type:
+
+ javareturntype jni_fn(...) {
+ if (error) {
+ SWIG_exception(SWIG_IndexError, "Array element error");
+ return 0;
+ }
+ ...
+ }
+
+01/02/2002: cheetah (william fulton)
+ [Java] The Java module incorrectly used argout typemaps for
+ strings. This is now corrected and the code now resides
+ in the freearg typemap. The argout array typemaps have been split into
+ argout and freearg typemaps. This correction may require some user
+ written typemaps to be modified.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+12/28/2001: cheetah (william fulton)
+ [Java] Multi typemaps now working for Java see multimap example.
+ [Java] Fix for recently introduced bug - freearg typemap code was appearing
+ before the function call.
+
+12/28/2001: cheetah (william fulton)
+ [Java] JCALL macro for JNI calls that work in both C and C++ typemaps
+ have been replaced with JCALL0, JCALL1, JCALL2, JCALL3 and JCALL4
+ macros.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+12/22/2001:beazley
+ Resolved some inconsistent behavior with %rename and class renaming.
+ If you specify the following:
+
+ %rename(Foo) Bar;
+
+ class Bar {
+ public:
+ Bar();
+ ~Bar();
+ }
+
+ Then the %rename directive applies to the class itself, the constructor,
+ and the destructor (all will be renamed to Foo).
+
+ If a class defines more than one constructor, the overloaded variants
+ can still be renamed by specifying parameters to %rename. For example:
+
+ %rename(Bar_copy) Bar(Bar &);
+ class Bar {
+ public:
+ Bar();
+ Bar(Bar &);
+ ~Bar();
+ };
+
+ There are still some odd corner cases. If you specify
+
+ %rename(Foo) ::Bar;
+
+ then only the name of the class is changed and the constructor/destructor
+ names are left unmodified. If you specify
+
+ %rename(Foo) *::Bar;
+
+ then the names of the constructor/destructor functions are modified but
+ the name of the class is not.
+
+12/21/2001: cheetah (william fulton)
+ [Java] jni, jtype and jstype typemaps no longer hardcoded but real
+ typemaps. New variable substitution, $javaclassname, can be used in
+ the jstype typemaps. It is replaced with the Java shadow class name
+ where applicable.
+ [Java] Fix for recently introduced bug to do with inheritance when
+ using %import.
+ [Java] A few more bug fixes, todo with %rename and using the kind
+ with the type, eg
+ void fn(union uni myuni, struct str mystr, class cl mycl);
+
+12/20/2001:beazley
+ Fixed [ #494524 ] Preprocessor bug - apostrophe and #subst.
+
+12/20/2001:beazley
+ Added SWIG_VERSION preprocessor symbol. This is a hexadecimal
+ integer such as 0x010311 (corresponding to SWIG-1.3.11). This can
+ be used in the interface as follows:
+
+ #if SWIG_VERSION >= 0x010311
+ /* Use some fancy new feature */
+ #endif
+
+ Note: The version symbol is not defined in the generated SWIG
+ wrapper file.
+
+ *** NEW FEATURE ***
+
+12/20/2001:mkoeppe
+ [MzScheme]: Renamed mzswig_make_boolean to
+ swig_make_boolean, as the latter is used in the typemaps.
+ Reported by Luigi Ballabio.
+
+12/17/2001:mkoeppe
+ [Guile]: Rewrote list-vector.i using multi-dispatch
+ typemaps. Updated pointer-in-out.i. Make the
+ deprecated typemap-substitution of "$source" in "argout"
+ work as before.
+
+12/16/2001:mkoeppe
+ [Guile]: Fixed macros %values_as_list, %values_as_vector,
+ %multiple_values to use the proper %pragma syntax. New
+ Guile example/test "multivalue"; new Guile run-test for
+ test-suite item "list-vector" (currently broken).
+
+12/14/2001:mkoeppe
+ [Guile]: Fixed typemap-substition bug for "varin". Relaxed
+ valid-identifier check to allow all R5RS identifiers.
+
+
+Version 1.3.10 (December 10, 2001)
+==================================
+
+12/08/2001:beazley
+ Modified %typemap so that %{ ... %} can also be used as a
+ code block (mostly for completeness). For example:
+
+ %typemap(in) blah %{
+ ...
+ %}
+
+ This form does not introduce a new block scope. Also, the
+ code enclosed in %{ ... %} is not processed by the preprocessor.
+
+12/08/2001:beazley
+ Fixed [ #459614 ] SWIG with multiple TCL interpreters.
+
+12/08/2001:beazley
+ Fixed [ #417141 ] rubydec.swg is wrong
+ Reported by Paul Brannan.
+
+12/08/2001:beazley
+ Fixed [ #410557 ] Problem with %addmethods on NT.
+ Reported by Magnus Ljung.
+
+12/08/2001:beazley
+ Fixed [ #445233 ] Enhancement: handle access change.
+ SWIG now parses (but ignores) C++ access changes for the
+ the following:
+
+ class A {
+ protected:
+ void something() { }
+ public:
+ A() {}
+ };
+
+ class B : private A {
+ public:
+ B() : A() { }
+ protected:
+ A::something; <---- Parsed, but ignored
+ };
+
+ Suggested by Krzysztof Kozminski.
+
+12/08/2001: cheetah (william fulton)
+ Fix for Ruby to work using Visual C++.
+
+12/06/2001:beazley
+ Fixed [ #465687 ] unsigned short parameters fail.
+ Reported by Gerald Williams.
+
+12/06/2001:beazley
+ Fixed SF [ #489594 ] PyString_FromString can't take NULL arg.
+ Reported by John Merritt. SWIG now converts string values
+ to Python using code like this:
+
+ resultobj = result ? PyString_FromString(result) : Py_BuildValue("");
+
+12/06/2001:beazley
+ Fixed SF [ #463561 ] Type conversions not generated.
+ Reported by Gerald Williams.
+
+12/04/2001:beazley
+ Fixed SF [ #470217 ] Tcl default argument handling.
+ Reported by Shaun Lowry.
+
+12/04/2001:beazley
+ Fixed SF [ #472088 ] defined(MACRO) expanded everywhere.
+ Embedded preprocessor directives such as
+
+ %#if defined(FOO)
+
+ are not expanded by the SWIG preprocessor.
+ Reported by Gerald Williams.
+
+12/04/2001:beazley
+ Fixed SF [ #476467 ] Problems with #define & commas.
+
+12/04/2001:beazley
+ Fixed SF [ #477547 ] wrong declaration of pointer functions.
+ Bad prototypes in Lib/tcl/ptrlang.i.
+
+12/04/2001:beazley
+ Fixed SF [ #483182 ] Constants can take args by mistake.
+ When swig -perl5 -const is used, constants are declared
+ with a void prototype. For example:
+
+ sub ICONST () { $examplec::ICONST }
+
+ Patch submitted by Rich Wales.
+
+12/03/2001:beazley
+ New %exception directive. This is intended to replace %except.
+ It works in exactly the same manner except it does not accept a
+ language specifier. For example:
+
+ %exception {
+ try {
+ $action
+ }
+ catch(SomeError) {
+ error
+ }
+ }
+
+ %exception is also name aware---allowing it to be applied to
+ specific declarations in an interface. For example:
+
+ %exception foo {
+ ...
+ exception for any function/method foo
+ ...
+ }
+
+ %exception Foo::bar {
+ ...
+ exception for method bar in class Foo
+ ...
+ }
+
+ %exception Foo::bar(double) {
+ ...
+ exception for method bar(double) in class Foo
+ ...
+ }
+
+ The semantics of this name matching is exactly the same as for %rename.
+ *** NEW FEATURE ***
+
+12/03/2001:beazley
+ Substantial cleanup of the Python shadow class code. Shadow classes
+ used to be created in this rather complicated manner involving about
+ a half-dozen strings created in bits and pieces. Shadow classes
+ are now generated in a more straightforward manner--in the same
+ order that appears in the interface file.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ The order in which declarations appear in the shadow file may differ.
+
+12/03/2001:beazley
+ The %insert directive (%{ ... %}, %runtime, %header, %wrapper, etc.)
+ can now be used inside of a class definition. This has potential
+ uses when generating shadow class code. For example:
+
+ class Foo {
+ ...
+ %insert("shadow") %{
+ # Some python code
+ def blah(self):
+ print "I'm blah!"
+ %}
+ ...
+ };
+
+ The support for class code insertion depends on the language module.
+ However, the intent of this feature is to simplify the task of extending
+ shadow class code. In the Python module, this inserts code with the
+ proper level of indendation (regardless of what was used in the SWIG
+ interface).
+ *** NEW FEATURE ***
+
+11/29/2001: cheetah (william fulton)
+ Modifications for Java and Python modules to work on cygwin.
+ Unfortunately a lot of the python module has started to produces code
+ which cannot be auto-imported using cygwin libtools so most of it is
+ still broken.
+
+11/28/2001:beazley
+ The %rename and %feature directive can now be used inside
+ of a class definition. For example:
+
+ class Foo {
+ %rename(foo_i) foo(int);
+ %rename(foo_d) foo(double);
+ public:
+ ...
+ void foo(int);
+ void foo(double);
+ ...
+ };
+
+ When used in this manner, the %rename directive only applies
+ to members of the class in which it appears as well as all
+ derived classes. In fact, this is really just the same
+ as saying:
+
+ %rename(foo_i) Foo::foo(int);
+ %rename(foo_d) Foo::foo(double);
+ class Foo {
+ ...
+ };
+
+ *** NEW FEATURE ***
+
+11/26/2001:beazley
+ Added the experimental %feature directive. %feature can be
+ used to attach arbitrary string attributes to parse tree nodes.
+ For example:
+
+ %feature("except") blah {
+ try {
+ $function
+ } catch (Error) {
+ whatever;
+ }
+ }
+
+ or
+
+ %feature("set") *::x_set "x";
+
+ or
+
+ %feature("blah") Foo::bar(int,double) const "spam";
+
+ The syntax is borrowed from the %rename directive. In fact, the
+ exact same semantics apply (inheritance, matching, etc.).
+
+ %feature is a very powerful low-level primitive that can be used to
+ customize individual language modules and to provide hints to
+ any stage of code generation. Features are attached to
+ parse tree nodes as attributes with names like "feature:*" where *
+ is replaced by the feature name (e.g., "feature:except", "feature:set",
+ etc.). Language modules can then look for the features using
+ a simple attribute lookup.
+
+ %feature is intended to be a replacement for a number of
+ older SWIG directives including %except and specialized
+ pragmas. It is more powerful (due to its parameterized
+ name matching) and it provides very precise control over
+ how customization features are attached to individual
+ declarations. There are future expansion plans that will
+ build upon this capability as well.
+
+ It's not certain that %feature will ever be used directly
+ by SWIG users. Instead, it may be a low-level primitive
+ that is used in high-level macro definitions. For instance,
+ to support properties, you might define a macro like this:
+
+ %define %property(name, setf, getf)
+ %feature("set") setf #name;
+ %feature("get") getf #name;
+ %enddef
+
+ Which allows a user to specify things like this:
+
+ %property(p, get_p, set_p);
+
+ class Blah {
+ public:
+ int get_p();
+ void set_p(int);
+ };
+
+ *** EXPERIMENTAL NEW FEATURE ***
+
+11/24/2001:beazley
+ The Tcl module has been expanded with some new features for
+ managing object ownership. For example:
+
+ set c [Circle -args 20]
+ $c area # Invoke a method
+ $c -disown # Releases ownership of the object
+ $c -acquire # Acquires ownership of the object
+
+ If Tcl owns the object, its destructor is invoked when the
+ corresponding object command is deleted in Tcl.
+
+ To simplify the destruction of objects, the following syntax
+ can be used:
+
+ $c -delete # Delete an object
+
+ This is an alternative for the more obscure variant of
+
+ rename $c {}
+
+ These features also add functionality at the C API level.
+ The following functions manage ownership from C and
+ can be used in typemaps.
+
+ SWIG_Acquire(void *ptr);
+ SWIG_Disown(void *ptr);
+
+ A new function for constructing instances is also available:
+
+ Tcl_Obj *
+ SWIG_NewInstanceObj(Tcl_Interp *interp, void *ptr,
+ swig_type_info *type, int own);
+
+ When used in a typemap, this creates a pointer object and
+ an interpreter command that can be used to issue methods and
+ access attributes as shown above.
+ *** NEW FEATURE ***
+
+11/23/2001:beazley
+ All Python-related %pragma operations have been eliminated.
+ Most of these were written for older SWIG versions in order to
+ compensate for limitations in earlier releases. In an effort
+ to reduce the amount of code-clutter and potential for errors,
+ it is easier to simply eliminate the pragmas and to start over
+ (if needed). To be honest, I'm not even sure the pragmas
+ worked in 1.3.9 and recent releases.
+
+ Note: If you need to insert code into the shadow class file
+ created by SWIG, simply use the %shadow directive like this:
+
+ %shadow %{
+ def some_python_code():
+ print "blah!"
+ %}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/22/2001:beazley
+ Sweeping changes to the way in which the Python module handles
+ shadow classes. In early implementations, shadow classes were
+ merely Python wrappers around typed pointer objects. However,
+ some users actually wanted to receive the shadow class object in C.
+ To accommodate this, the dereferencing of the "this" pointer in
+ a shadow class was moved to C as described in CHANGES [8/8/99].
+ However, the process of returning pointers to Python was still
+ somewhat problematic. Specifically, shadow classes never worked
+ in situations such as these:
+
+ - Use of any kind of output typemap ('out' or 'argout')
+ - Global variables (broken as far as I can tell).
+
+ In the past, some users have dealt with this by manually trying
+ to create shadow class objects themselves from C/C++. However,
+ this was difficult because the C wrappers don't really know how
+ to get access to the corresponding Python class.
+
+ The Python module has now been modified to automatically attach
+ shadow class objects to pointers when they are returned to
+ Python. This process occurs in the function SWIG_NewPointerObj()
+ so the process is completely transparent to users. As a result,
+ shadow classes are now more seamlessly integrated with typemaps
+ and other features of SWIG.
+
+ This change may introduce a number of incompatibilities. The
+ SWIG_NewPointerObj() now takes an extra parameter "own" to
+ indicate object ownership. This can be used to return a pointer
+ to Python that Python should destroy. In addition, older code
+ that tries to manually construct shadow class objects or which
+ expects bare pointers may break---such pointers may already be
+ encapsulated by a shadow class.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/20/2001:beazley
+ Modified the %insert directive to accept single braces { ... }.
+ For example:
+
+ %insert("header") {
+ ... some code ...
+ }
+
+ This works exactly like %{ ... %} except that the code in the
+ braces is processed using the preprocessor. This can be useful
+ in certain contexts such as low-level code generation in
+ language modules.
+ *** NEW FEATURE ***
+
+11/20/2001:beazley
+ Command line options are now translated into preprocessor
+ symbols. For example:
+
+ ./swig -python -shadow -module blah interface.i
+
+ Creates the symbols:
+
+ SWIGOPT_PYTHON 1
+ SWIGOPT_SHADOW 1
+ SWIGOPT_MODULE blah
+
+ Modules can look for these symbols to alter their code generation
+ if needed.
+ *** NEW FEATURE ***
+
+11/20/2001:beazley
+ Massive overhaul of the Perl5 module. A lot of code generation is
+ now driven by tables and typemaps. The generated wrapper code
+ also makes use of tables to install constants, variables, and
+ functions instead of inlining a bunch of procedure calls. The
+ separate variable initialization function is gone. Most
+ code generation is controlled via the perl5.swg file in the
+ library.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/13/2001:beazley
+ Added parsing support for the C++ typename keyword. Primarily this
+ is added to better support templates. For example:
+
+ template<typename T> void blah(C& v) {
+ typename C::iterator i = v.begin();
+ }
+
+ Note: typename is supported in the parser in the same way as 'struct'
+ or 'class'. You probably shouldn't use it anywhere except in templates.
+ *** NEW FEATURE ***
+
+11/11/2001:beazley
+ Massive overhaul of the language module API. Most functions now
+ use a common, very simple, API. There are also a number of
+ interesting semantic side-effects of how code is actually generated.
+ Details will be forthcoming in Doc/Manual/Extending.html.
+
+ *** POTENTIAL INCOMPATIBILITY *** Language modules written for
+ previous versions of SWIG will no longer work,
+
+11/10/2001:beazley
+ Fixed a very subtle bug due to unnamed class wrapping. For example, if
+ you did this
+
+ typedef struct {
+ int x,y;
+ } gdPoint, *gdPointPtr;
+
+ void foo(gdPointPtr x);
+
+ Then the foo function would get a type-error. The problem has
+ to do with internal typedef handling and the fact that the typedef
+ declarations after the struct appear later in the parse tree.
+ It should work now. Problem reported by Vin Jovanovic.
+
+11/09/2001:beazley
+ Subtle change to "out" typemaps (and related variations). The name
+ that is attached to the typemap is now the raw C identifier that
+ appears on a declaration. This changes the behavior of
+ member functions. For example:
+
+ %typemap(out) int foo {
+ ...
+ }
+
+ class Blah {
+ public:
+ int foo(); // typemap gets applied
+ }
+
+ Previous versions never really specified how this was supposed to
+ work. In SWIG1.1, you could probably write a typemap for the
+ wrapper name like this:
+
+ %typemap(out) int Blah_foo { ... }
+
+ However, this old behavior is now withdrawn and not supported.
+ Just use the member name without any sort of special prefix.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/06/2001:beazley
+ Changes to Tcl module initialization:
+
+ (1) SWIG now automatically includes the code needed to work with
+ Tcl stubs. Simply compile with -DUSE_TCL_STUBS.
+
+ (2) SWIG now automatically calls Tcl_PkgProvide to register
+ a package name. The package name is the same as the name
+ specified with the %module directive. The version number is
+ set to "0.0" by default. To change the version number, use
+ swig -pkgversion 1.2 interface.i.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ Modules that provided stubs and Tcl_PkgProvide on their own might
+ break. Simply remove that code.
+
+11/05/2001:beazley
+ Changed code generation of constants in the Tcl module. Constants
+ are now stored in a large table that get installed at module startup.
+ There are also no longer any static variables so it should generate
+ somewhat less code.
+
+11/04/2001:beazley
+ The "const" typemap has been renamed to "constant" in many language
+ modules. "const" is a C keyword which made the handling of the typemap
+ directive somewhat awkward in the parser.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/04/2001:beazley
+ %typemap directive can now accept nearly arbitrary keyword parameters.
+ For example:
+
+ %typemap(in,parse="i",doc="integer") int "..."
+
+ The purpose of the keyword parameters is to supply code generation
+ hints to the target language module. The intepretation of the
+ parameters is language specific.
+ *** NEW FEATURE ***
+
+11/04/2001:beazley
+ Slight semantic change to internal call/return by value handling.
+ In previous versions of SWIG, call-by-value was translated
+ into pointers. For example:
+
+ double dot_product(Vector a, Vector b);
+
+ turned into this:
+
+ double wrap_dot_product(Vector *a, Vector *b) {
+ return dot_product(*a,*b);
+ }
+
+ This translation was normally performed by the SWIG core, outside
+ of the control of language modules. However, a side effect
+ of this was a lot of bizarre typemap behavior. For example,
+ if you did something like this:
+
+ %typemap(in) int32 {
+ ...
+ }
+
+ You would find that int32 was transformed into a pointer everywhere!
+ (needless to say, such behavior is unexpected and quite awkward to
+ deal with). To make matters worse, if a typedef was also used,
+ the pointer behavior suddenly disappeared.
+
+ To fix this, the pointer transformation is now pushed to the
+ language modules. This produces wrappers that look roughly
+ like this:
+
+ double wrap_dot_product(Vector *a, Vector *b) {
+ Vector arg1 = *a;
+ Vector arg2 = *b;
+ return dot_product(arg1,arg2);
+ }
+
+ This change also makes it easy to define typemaps for
+ arbitrary undefined types. For example, you can do this (and it
+ will work regardless what int32 is):
+
+ %typemap(in) int32 {
+ $1 = (int32) PyInt_AsLong($input);
+ }
+
+ *** POTENTIAL IMCOMPATIBILITY ***
+ This change may break call/return by value code generation in
+ some language modules.
+
+11/03/2001:beazley
+ Changed the name of the default typemaps to the following:
+
+ %typemap() SWIGTYPE {
+ ... an object ...
+ }
+ %typemap() SWIGTYPE * {
+ ... a pointer ...
+ }
+ %typemap() SWIGTYPE & {
+ ... a reference ...
+ }
+ %typemap() SWIGTYPE [] {
+ ... an array ...
+ }
+ %typemap() enum SWIGTYPE {
+ ... an enum value ...
+ }
+ %typemap() SWIGTYPE (CLASS::*) {
+ ... pointer to member ...
+ }
+
+
+ These types are used as the default for all types that don't match
+ anything else. See CHANGES log entry for 8/27/2000 for the
+ old behavior. The role of these types is also described in
+ Doc/Manual/Typemaps.html
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+10/25/2001:beazley
+ Modified Guile and Mzscheme modules to support
+ multi-argument typemaps.
+
+10/25/2001: cheetah (william fulton)
+ [Java] Fix to handle pointers to arrays.
+
+10/24/2001:beazley
+ Defining a typemap rule for enum SWIGENUM can now be used
+ to define default behavior for enum variables.
+
+10/22/2001:beazley
+ Ruby module modified to support multi-argument typemaps.
+
+10/22/2001:beazley
+ The Ruby module can now handle functions with an arbitrary
+ number of arguments. Previous versions were limited to
+ to functions with only 9 or 16 arguments depending on
+ the use of default arguments. Note: from some inspection
+ of the Ruby interpreter source, the new approach might be
+ a little faster as well.
+
+10/18/2001:beazley
+ Fixed a bug with forward class declarations and
+ templates.
+
+ class Foo <S,T>;
+
+ Bug reported by Irina Kotlova.
+
+10/16/2001:beazley
+ Support for multivalued typemaps added. The typemaps
+ are specified using the syntax below. Within each
+ typemap, variable substitution is handled as follows:
+
+ %typemap(in) (int argc, char *argv[]) {
+ $arg; // The input object in the target language
+ $1; // C local variable for first argument
+ $2; // C local variable for second argument
+
+ // These variables refer to either argument
+ $1_type, $1_ltype, $1_basetype, etc... (argc)
+ $2_type, $2_ltype, $2_basetype, etc... (argv[])
+
+ // Array dimension of argv
+ $2_dim0
+ }
+
+ Basically any variable that was available in normal typemaps
+ is available for either argument by prefacing the variable
+ name by '$n_' where n is the argument position.
+
+ Notes:
+ (1) Multi-valued typemaps can only be applied to a single
+ object in the target scripting language. For example,
+ you can split a string into a (char *, int) pair or
+ split a list into a (int, char []) pair. It is not
+ possible to map multiple objects to multiple arguments.
+
+ (2) To maintain compatibility with older SWIG versions, the
+ variables such as $target and $type are preserved and
+ are mapped onto the first argument only.
+
+ (3) This should not affect compatibility with older code.
+ Multi-valued typemaps are an extension to typemap handling.
+ Single valued typemaps can be specified in the usual
+ way.
+
+ The old $source and $target variables are officially
+ deprecated. Input variables are referenced through
+ $arg$ and output values are reference through $result$.
+
+ *** NEW FEATURE ***
+
+10/16/2001:beazley
+ Added parsing support for multivalued typemaps. The syntax
+ is a little funky, but here goes:
+
+ // Define a multivalued typemap
+ %typemap(in) (int argc, char *argv[]) {
+ ... typemap code ...
+ }
+
+ // Multivalued typemap with locals
+ %typemap(in) (int argc, char *argv[])(int temp) {
+ ... typemap code ...
+ }
+
+ // Copy a multivalued typemap
+ %typemap(in) (int argcount, char **argv) = (int argc, char *argv[]);
+
+ // Apply a multivalued typemap
+ %apply (int argc, char *argv[]) { (int argcount, char **argv) };
+
+ Note: this extra parsing support is added for future extension.
+ No language modules currently support multi-valued typemaps.
+
+10/11/2001:beazley
+ Modified the typemap matching code to discard qualifiers when
+ checking for a match. For example, if you have a declaration
+ like this:
+
+ void blah(const char *x);
+
+ The typemap checker checks for a match in the following order:
+
+ const char *x
+ const char *
+ char *x
+ char *
+
+ If typedef's are involved, qualifier stripping occurs before
+ typedef resolution. So if you had this,
+
+ typedef char *string;
+ void blah(const string x);
+
+ typemap checking would be as follows:
+
+ const string x
+ const string
+ string x
+ string
+ const char *x
+ const char *
+ char *x
+ char *
+
+ The primary reason for this change is to simplify the implementation
+ of language modules. Without qualifier stripping, one has to write
+ seperate typemaps for all variations of const and volatile (which
+ is a pain).
+
+ *** POTENTIAL INCOMPATIBILITY *** Typemaps might be applied in
+ places where they weren't before.
+
+
+10/9/2001: beazley
+ SWIG now generates wrappers that properly disambiguate
+ overloaded methods that only vary in constness. For
+ example:
+
+ class Foo {
+ ...
+ void blah();
+ void blah() const;
+ ...
+ };
+
+ To handle this, the %rename directive can be used normally.
+
+ %rename(blah_const) blah() const;
+
+ In the resulting wrapper code, method calls like this
+ are now generated:
+
+ (obj)->blah() // Non-const version
+ ((Foo const *)obj)->blah() // const version
+
+ This should force the right method to be invoked.
+ Admittedly, this is probably obscure, but we might
+ as well get it right.
+
+10/8/2001: beazley
+ The preprocessor now ignores '\r' in the input.
+ This should fix the following bug:
+ [ #468416 ] SWIG thinks macro defs are declarations?
+
+10/8/2001: beazley
+ Added support for ||, &&, and ! in constants. This
+ fixes SF [ #468988 ] Logical ops break preprocessor.
+ However, at this time, constants using these operators
+ are not supported (the parser will issue a warning).
+
+10/4/2001: beazley
+ Added -show_templates command line option. This makes
+ SWIG display the code it actually parses to generate
+ template wrappers. Mostly useful for debugging.
+ *** NEW FEATURE ***
+
+10/4/2001: beazley
+ Change to semantics of %template directive. When
+ using %template, the template arguments are handled
+ as types by default. For example:
+
+ %template(vecint) vector<int>;
+ %template(vecdouble) vector<double>;
+
+ To specify a template argument that is *not* a type, you
+ need to use default-value syntax. For example:
+
+ %template(vecint) vector<int,int=50>;
+ %template(vecdouble) vector<int,size=100>;
+
+ In this case, the type name doesn't really matter--only
+ the default value (e.g., 50, 100) is used during
+ expansion. This differs from normal C++, but I couldn't
+ figure out a better way to do it in the parser. Might
+ implement an alternative later.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+10/4/2001: beazley
+ Major changes to template handling in order to provide
+ better integration with the C++ type-system. The main
+ problem is as follows:
+
+ Suppose you have a template like this:
+
+ template<class T> void blah(const T x) { stuff };
+
+ Now suppose, that you instantiate the template on a
+ type like this in SWIG:
+
+ %template(blahint) blah<int *>;
+
+ In C++, this is *supposed* to generate code like this:
+
+ void blah(int *const x) { stuff };
+
+ However, in SWIG-1.3.9, the template substitution gets it wrong
+ and produces
+
+ void blah(const int *x) { stuff };
+
+ (notice the bad placement of the 'const' qualifier).
+
+ To fix this, the SWIG parser now generates implicit typedefs
+ for template type arguments that produces code roughly
+ equivalent to doing this:
+
+ typedef int *__swigtmpl1;
+ %template(blahint) blah<__swigtmpl1>;
+
+ which generates code like this:
+
+ void blah(const __swigtmpl1 x) { stuff };
+
+ Since this is correct in both C++ and SWIG, it provides the right
+ semantics and allows everything to compile properly. However,
+ to clean up the generated code a little bit, the parser keeps
+ track of the template types and performs back-substitution to
+ the original type when building the parse tree. Thus, even
+ though the implicit typedef is used in the input and may appear
+ in the generated wrapper file (for proper compilation), the parse
+ tree will hide a lot of these details. For example:
+
+ void blah(const __swigtmpl1 x) { stuff };
+
+ will look like it was declared as follows (which is what
+ you want):
+
+ void blah(int *const x) { stuff }
+
+ The only place you are likely to notice the typedef hack
+ is in bodies of template functions. For example, if you
+ did this,
+
+ template<class T> class blah {
+ ...
+ %addmethods {
+ void spam() {
+ T tempvalue;
+ ...
+ }
+ }
+ }
+
+ you will find that 'T tempvalue' got expanded into some
+ strange typedef type. This *still* compiles correctly
+ so it's not a big deal (other than looking kind of ugly
+ in the wrapper file).
+
+10/4/2001: beazley
+ Fixed some inheritance problems in Tcl Object interface.
+
+10/1/2001: beazley
+ Tcl module has changed to use byte-backed pointer strings. This
+ implementation should be safe on 64-bit platforms. However,
+ the order in which digits appear in pointer values no longer
+ directly corresponds to the actual numerical value of a
+ pointer (on little-endian machines, pairs of digits appear
+ in reverse order).
+
+10/1/2001: beazley
+ Perl5 module is now driven by a configuration file 'perl5.swg'
+ in the SWIG library.
+
+10/1/2001: beazley
+ The perl5 module no longer tries to apply the "out" typemap
+ in code generated for magic variables. I'm surprised that
+ this ever worked at all (since all of the code that was there
+ was wrong anyways). Use the "varout" typemap to handle
+ global variables.
+
+10/1/2001: beazley
+ Fixed a bug related to character array members of structures.
+ For example:
+
+ struct Foo {
+ char name[32];
+ };
+
+ SWIG is normally supposed to return a string, but this was
+ broken in 1.3.9. The reason it was broken was actually
+ due to a subtle new feature of typemaps. When a data member
+ is set to an array like this, the return type of the related
+ accessor function is actually set to an array. This means
+ that you can now write typemaps like this:
+
+ %typemap(python,out) char [ANY] {
+ $target = PyString_FromStringAndSize($source,$dim0);
+ }
+
+ This functionality can be used to replace the defunct
+ memberout typemap in a more elegant manner.
+
+9/29/2001: beazley
+ Some further refinement of qualified C++ member functions.
+ For example:
+
+ class Foo {
+ ...
+ void foo() const;
+ ...
+ };
+
+ (i) The SWIG parser was extended slightly to allow 'volatile'
+ and combinations of 'const' and 'volatile' to be used. This
+ is probably rare, but technically legal. Only added for
+ completeness.
+
+ (ii) For the purposes of overloading, qualified and non-qualified
+ functions are different. Thus, when a class has methods like this:
+
+ void foo();
+ void foo() const;
+
+ Two distinct methods are declared. To deal with this, %rename
+ and similar directives have been extended to recognize const.
+ Thus, one can disambiguate the two functions like this:
+
+ %rename(fooconst) Foo::foo() const;
+
+ or simply ignore the const variant like this:
+
+ %ignore Foo::foo() const;
+
+ Note: SWIG currently has no way to actually invoke the const
+ member since the 'const' is discarded when generating wrappers
+ for objects.
+
+9/27/2001: beazley
+ New directive. %namewarn can be used to issue warning
+ messages for certain declaration names. The name
+ matching is the same as for the %rename directive.
+ The intent of this directive is to issue warnings for
+ possible namespace conflicts. For example:
+
+ %namewarn("print is a python keyword") print;
+
+ The name matching algorithm is performed after a name
+ has been resolved using %rename. Therefore, a
+ declaration like this will not generate a warning:
+
+ %rename("Print") print;
+ ...
+ void print(); /* No warning generated */
+
+ Since the warning mechanism follows %rename semantics, it is
+ also to issue warnings for specific classes or just for
+ certain member function names.
+
+ (Dave - I've been thinking about adding something like this
+ for quite some time. Just never got around to it)
+ *** NEW FEATURE ***
+
+
+9/27/2001: beazley
+ Enhanced the %ignore directive so that warning messages
+ can be issued to users. This is done using %ignorewarn
+ like this:
+
+ %ignorewarn("operator new ignored") operator new;
+
+ The names and semantics of %ignorewarn is exactly the
+ same as %ignore. The primary purpose of this directive
+ is for module writers who want to ignore certain types
+ of declarations, but who also want to alert users about it.
+ A user might also use this for debugging (since messages
+ will appear whenever an ignored declaration appears).
+ *** NEW FEATURE ***
+
+9/26/2001: beazley
+ Super-experimental support for overloaded operators.
+ This implementation consists of a few different parts.
+
+ (i) Operator names such as 'operator+' are now allowed
+ as valid declarator names. Thus the 'operator' syntax
+ can appear *anyplace* a normal declarator name was used
+ before. On the surface, this means that operators can
+ be parsed just like normal functions and methods.
+ However, it also means that operator names can be used
+ in many other SWIG directives like %rename. For example:
+
+ %rename(__add__) Complex::operator+(const Complex &);
+
+ (ii) Operators are wrapped *exactly* like normal functions
+ and methods. Internally, the operator name is used
+ directly meaning that the wrapper code might contain
+ statements like this:
+
+ arg0->operator*((Complex const &)*arg1);
+
+ This all seems to parse and compile correctly (at least
+ on my machine).
+
+ (iii) SWIG will no longer wrap a declaration if its symbol
+ table name contains illegal identifier characters. If
+ illegal characters are detected, you will see an error
+ like this:
+
+ Warning. Can't wrap operator* unless renamed to a valid identifier.
+
+ The only way to fix this is to use %rename or %name to bind
+ the operator to a nice name like "add" or something. Note:
+ the legal identifier characters are determined by the target
+ language.
+
+ There are certain issues with friend functions and operators.
+ Sometimes, friends are used to define mixed operators such
+ as adding a Complex and a double together. Currently, SWIG
+ ignores all friend declarations in a class. A global operator
+ declaration can probably be made to work, but you'll have to
+ rename it and it probably won't work very cleanly in the
+ target language since it's not a class member.
+
+ SWIG doesn't know how to handle operator specifications
+ sometimes used for automatic type conversion. For example:
+
+ class String {
+ ...
+ operator const char*();
+ ...
+ };
+
+ (this doesn't parse correctly and generates a syntax error).
+
+ Also: operators no longer show up as separate parse-tree
+ nodes (instead they are normal 'cdecl' nodes). I may
+ separate them as a special case later.
+
+ See Examples/python/operator for an example.
+
+ *** SUPER-EXPERIMENTAL NEW FEATURE ***
+
+Version 1.3.9 (September 25, 2001)
+==================================
+
+9/25/2001: beazley
+ Fixed parsing problem with type declarations like
+ 'char ** const'. SWIG parsed this correctly, but the
+ internal type was represented incorrectly (the pointers
+ and qualifiers were in the wrong order).
+
+9/25/2001: beazley
+ Withdrew experimental feature (noted below) that was
+ causing serious parsing problems.
+
+Version 1.3.8 (September 23, 2001)
+==================================
+
+9/23/2001: beazley
+ Included improved distutils setup.py file in the Tools
+ directory (look for the setup.py.tmpl file). Contributed by
+ Tony Seward.
+
+9/23/2001: beazley
+ Included two new RPM spec files in the Tools directory. Contributed
+ by Tony Seward and Uwe Steinmann.
+
+9/21/2001: beazley
+ Fixed SF Bug [ #463635 ] Perl5.swg does not compile in Visual C++
+
+9/21/2001: beazley
+ Two new directives control the creation of default
+ constructors and destructors:
+
+ %nodefault
+ %makedefault
+
+ These replace %pragma nodefault and %pragma makedefault.
+ (old code will still work, but documentation will only
+ describe the new directives).
+
+9/21/2001: beazley
+ Fixed SF Bug [ #462354 ] %import broken in 1.3.7.
+
+9/20/2001: beazley
+
+ Parser modified to ignore out-of-class constructor
+ and destructor declarations. For example:
+
+ inline Foo::Foo() :
+ Bar("foo")
+ {
+ }
+
+ inline Foo::~Foo() {
+ }
+
+ Suggested by Jason Stewart.
+ *** EXPERIMENTAL FEATURE ***
+
+9/20/2001: beazley
+ Modified the parser to ignore forward template class
+ declarations. For example:
+
+ template <class V, long S> class MapIter;
+
+ Suggested by an email example from Irina Kotlova.
+
+9/20/2001: beazley
+ Fixed problem with undeclared tcl_result variable in
+ the "out" typemap for Tcl. Reported by Shaun Lowry.
+
+9/20/2001: beazley
+ Incorporated changes to make SWIG work with ActivePerl.
+ Contributed by Joel Reed.
+
+9/20/2001: beazley
+ Slight change to the parsing of C++ constructor initializers.
+ For example:
+
+ class Foo : public Bar {
+ public:
+ Foo() : Bar(...) {...}
+ };
+
+ SWIG now discards the contents of the (...) regardless of
+ what might enclosed (even if syntactically wrong). SWIG
+ doesn't need this information and there is no reason to
+ needless add syntax rules to handle all of the possibilities
+ here.
+
+9/20/2001: beazley
+ Change to typemaps for structure members. If you have a
+ structure like this:
+
+ struct Vector {
+ int *bar;
+ };
+
+ The member name 'bar' is now used in any accessor functions.
+ This allows the "in" typemap to be used when setting the value.
+ For example, this typemap
+
+ %typemap(python,in) int *bar {
+ ...
+ }
+
+ now matches Vector::bar. It should be noted that this will also
+ match any function with an argument of "int *bar" (so you should
+ be careful).
+ *** NEW FEATURE. POTENTIAL INCOMPATIBILITY ***
+
+9/20/2001: beazley
+ Fixed SF bug #462642 setting string values in structures
+
+9/20/2001: beazley
+ Fixed SF bug #462398 problem with nested templates.
+
+9/20/2001: beazley
+ Fixed SF bug #461626 problem with formatting and C++ comments.
+
+9/20/2001: beazley
+ Fixed SF bug #462845 Wrong ownership of returned objects.
+
+9/19/2001: beazley
+ Fixed SF bug #459367. Default constructors for classes
+ with pure virtual methods.
+
+9/19/2001: beazley
+ Fixed problem with default arguments and class scope. For
+ example:
+
+ class Foo {
+ public:
+ enum bar { FOO, BAR };
+ void blah(bar b = FOO);
+ ...
+ }
+
+ SWIG now correctly generates a default value of "Foo::FOO" for
+ the blah() method above. This used to work in 1.1, but was
+ broken in 1.3.7. Bug reported by Mike Romberg.
+
+Version 1.3.7 (September 3, 2001)
+==================================
+
+9/02/2001: beazley
+ Added special %ignore directive to ignore declarations. This
+ feature works exactly like %rename. For example:
+
+ %ignore foo; // Ignore all declarations foo
+ %ignore ::foo; // Only ignore foo in global scope
+ %ignore Spam::foo; // Only ignore in class Spam
+ %ignore *::foo; // Ignore in all classes
+
+ %ignore can also be parameterized. For example:
+
+ %ignore foo(int);
+ %ignore ::foo(int);
+ %ignore Spam::foo(int);
+ %ignore *::foo(int);
+
+ *** NEW FEATURE ***
+
+
+9/02/2001: cheetah (william fulton)
+ [Java] shadowcode pragma modified so that the code that is output
+ in the shadow file is placed relative to where it is placed in the
+ c/c++ code. This allows support for JavaDoc function comments.
+
+9/01/2001: beazley
+ Fixed SF Patch [ #447791 ] Fix for python -interface option.
+ Submitted by Tarn Weisner Burton.
+
+9/01/2001: beazley
+ SWIG no longer generates default constructors/destructors
+ for a class if it only defines a private/protected constructor
+ or destructor or if any one of its base classes only has
+ private constructors/destructors. This was reported in
+ SF Patch [ #444281 ] nonpublic/default/inhereted ctor/dtor
+ by Marcelo Matus.
+
+9/01/2001: beazley
+ Added patch to Perl5 module that allows constants to be
+ wrapped as constants that don't require the leading $.
+ This feature is enabled using the -const option.
+ Patch contributed by Rich Wales.
+ *** NEW FEATURE ***
+
+8/31/2001: beazley
+ Added parsing support for the 'volatile' type qualifier.
+ volatile doesn't mean anything to SWIG, but it is
+ needed to properly generate prototypes for declarations
+ that use it. It's also been added to make the SWIG type
+ system more complete.
+ *** NEW FEATURE ***
+
+8/30/2001: beazley
+ Added support for parameterized %rename directive. *** This
+ new feature can be used to greatly simplify the task of
+ resolving overloaded methods and functions. ***
+
+ In prior versions of SWIG, the %rename directive was
+ used to consistently apply an identifier renaming. For
+ example, if you said this:
+
+ %rename foo bar;
+
+ Every occurrence of 'foo' would be renamed to 'bar'.
+ Although this works fine for resolving a conflict with a
+ target language reserved word, it is useless for
+ for dealing with overloaded methods. This is because
+ all methods are simply renamed to the same thing
+ (generating the same conflict as before).
+
+ Therefore, the only way to deal with overloaded methods
+ was to go through and individually rename them all using
+ %name. For example:
+
+ class Foo {
+ public:
+ virtual void bar(void);
+ %name(bar_i) virtual void bar(int);
+ ...
+ };
+
+ To make matters worse, you had to do this for all
+ derived classes too.
+
+ class Spam : public Foo {
+ public:
+ virtual void bar(void);
+ %name(bar_i) virtual void bar(int);
+ ...
+ };
+
+ Needless to say, this makes it extremely hard to resolve
+ overloading without a lot of work and makes it almost
+ impossible to use SWIG on raw C++ .h files.
+
+ To fix this, %rename now accepts parameter declarators.
+ The syntax has also been changed slightly. For example,
+ the following declaration renames all occurrences of 'bar(int)'
+ to 'bar_i', leaving any other occurrence of 'bar' alone.
+
+ %rename(bar_i) bar(int);
+
+ Using this feature, you can now selectively rename
+ certain declarations in advance. For example:
+
+ %rename(bar_i) bar(int);
+ %rename(bar_d) bar(double);
+
+ // Include raw C++ header
+ %include "header.h"
+
+ When %rename is used in this manner, all occurrence of bar(int)
+ are renamed wherever they might occur. More control is obtained
+ through explicit qualification. For example,
+
+ %rename(bar_i) ::bar(int);
+
+ only applies the renaming if bar(int) is defined in the global scope.
+ The declaration,
+
+ %rename(bar_i) Foo::bar(int);
+
+ applies the renaming if bar(int) is defined in a class Foo.
+ This latter form also supports inheritance. Therefore, if you
+ had a class like this:
+
+ class Spam : public Foo {
+ public:
+ void bar(int);
+ }
+
+ The Spam::bar(int) method would also be renamed (since Spam
+ is a subclass of Foo). This latter feature makes it easy
+ for SWIG to apply a consistent renaming across an entire
+ class hierarchy simply by specifying renaming rules for
+ the base class.
+
+ A class wildcard of * can be used if you want to renaming
+ all matching members of all classes. For example:
+
+ %rename(bar_i) *::bar(int);
+
+ will rename all members bar(int) that are defined in classes.
+ It will not renamed definitions of bar(int) in the global
+ scope.
+
+ The old use of %rename is still supported, but is somewhat
+ enhanced.
+
+ %rename(foo) bar; // Renames all occurrences of 'bar'.
+ %rename(foo) ::bar; // Rename all 'bar' in global scope only.
+ %rename(foo) *::bar; // Rename all 'bar' in classes only.
+ %rename(foo) Foo::bar; // Rename all 'bar' defined in class Foo.
+
+ *** NEW FEATURE ***
+
+8/30/2001: beazley
+ Added support for data-member to member-function
+ transformation. For example, suppose you had a
+ structure like this:
+
+ struct Vector {
+ double x,y;
+ };
+
+ Now suppose that you wanted to access x and y
+ through a member function interface instead
+ of the usual SWIG behavior. For example:
+
+ f.set_x(3.4) # instead of f.x = 3.4
+ x = f.get_x() # instead of x = f.x
+
+ To do this, simply use the new %attributefunc
+ directive. For example:
+
+ %attributefunc(get_%s,set_%s)
+ struct Vector {
+ double x,y;
+ };
+ %noattributefunc
+
+ The arguments to %attributefunc are C-style printf
+ format strings that determine the naming convention
+ to use. %s is replaced with the actual name of the
+ data member. SWIG provides a number of printf
+ extensions that might help. For example, if you
+ wanted to title case all of the attributes, you
+ could do this:
+
+ %attributefunc(get%(title)s,set%(title)s);
+
+ This will turn an attribute 'bar' to 'getBar()' and 'setBar()'.
+
+ (someone requested this long ago, but I finally figured
+ how to implement it in a straightforward manner).
+ *** EXPERIMENTAL NEW FEATURE ***
+
+8/30/2001: beazley
+ SWIG now automatically generates default constructors
+ and destructors if none are defined. This used to be
+ enabled with a command line switch -make_default, but
+ most people want these functions anyways. To turn
+ off this behavior use the -no_default option or include
+ the following pragma in the interface file:
+
+ %pragma no_default;
+
+ This may break certain interfaces that defined their
+ own constructors/destructors using the same naming
+ convention as SWIG. If so, you will get duplicate
+ symbols when compiling the SWIG wrapper file.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/29/2001: beazley
+ Changes to Perl5 shadow class code generation. Iterators
+ are no longer supported (FIRSTKEY, NEXTKEY). Also, attribute
+ access has been changed to rely on inheritance in order
+ to provide better behavior across modules.
+
+8/28/2001: beazley
+ Various obscure improvements to the type system and classes.
+ Strange declarations like this are now wrapped correctly
+ (i.e., the generated wrapper code doesn't cause the C++
+ compiler to die with a type error).
+
+ class Foo {
+ public:
+ typedef double Real;
+ Real foo(Real (*op)(Real,Real), Real x, Real y);
+ };
+
+ Inheritance of types is also handled correctly.
+
+8/28/2001: beazley
+ Changes to class wrappers. When SWIG sees two classes like this,
+
+ class X {
+ public:
+ void foo();
+ ...
+ }
+
+ class Y : public X {
+ public:
+ void bar();
+ ...
+ }
+
+ it now only generates two wrapper functions:
+
+ X_foo(X *x) { x->foo(); }
+ Y_bar(Y *y) { y->bar(); }
+
+ Unlike SWIG1.15, the foo() method does *not* propagate to a wrapper
+ function Y_foo(). Instead, the base class method X_foo() must be
+ used.
+
+ This change should not affect modules that use shadow classes, but
+ it might break modules that directly use the low-level C wrappers.
+ This change is being made for a number of reasons:
+
+ - It greatly simplifies the implementation of SWIG--especially
+ with anticipated future changes such as overloaded methods.
+
+ - It results in substantially less wrapper code--especially
+ for big C++ class hierarchies (inherited declarations
+ are no longer copied into every single derived class).
+
+ - It allows for better code generation across multiple
+ SWIG generated modules (code isn't replicated in
+ every single module).
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/22/2001: cheetah (william fulton)
+ Provided some Windows documentation in the Win directory and some
+ Visual C++ project files for running examples on Windows.
+
+8/28/2001: mkoeppe
+ [Guile] Handle renamed overloaded functions properly;
+ thanks to Marc Zonzon <[email protected]> for the
+ patch. See the new test case name_cxx.
+
+8/27/2001: mkoeppe
+ [Tcl] Removed lots of warnings issued by the Sun Forte
+ compilers, which were caused by mixing function pointers
+ of different linkages (C++/C).
+
+8/23/2001: mkoeppe
+ Improved the MzScheme module by porting Guile's pointer
+ type checking system and making type dispatch
+ typemap-driven.
+
+8/22/2001: beazley
+ Entirely new symbol table processing. SWIG should be able to
+ report much better error messages for multiple declarations.
+ Also, the new symbol table allows for overloaded functions
+ (although overloading isn't quite supported in the language
+ modules yet).
+
+8/22/2001: cheetah (william fulton)
+ * [Java] %new support added.
+ * [Java] Package JNI name refixed!
+
+8/19/2001: beazley
+ Python module modified to support pointers to C++ members. This
+ is an experimental feature.
+ *** NEW FEATURE ***
+
+8/19/2001: beazley
+ Added limited parsing and full type-system support for pointers to
+ members. None of SWIG's language modules really know how to deal with
+ this so this is really only provided for completeness and future
+ expansion. Note: SWIG does not support pointers to members which
+ are themselves pointers to members, references to pointers to members,
+ or other complicated declarations like this.
+ *** NEW FEATURE ***
+
+8/19/2001: beazley
+ SWIG is much better at parsing certain C++ declarations. Operators and
+ friends generally don't cause anymore syntax errors. However, neither
+ are really supported.
+
+8/18/2001: beazley
+ Added *highly* experimental support for wrapping of C++
+ template declarations. Since C++ templates are essentially
+ glorified macros and SWIG has a fully operational C
+ preprocessor with macro support, the parser now converts
+ template declarations to macros. For example, a function
+ template like this
+
+ template<class T> T max(T a, T b);
+
+ is internally converted into a macro like this:
+
+ %define %_template_max(__name,T)
+ %name(__name) T max(T a, T b);
+ %enddef
+
+ To instantiate a version of the template, a special %template declaration
+ is used like this:
+
+ %template(maxint) max<int>;
+ %template(maxdouble) max<double>;
+
+ The parameter to the %template directive must be proper C identifier that's
+ used to uniquely name the resulting instantiation. When used, the
+ the expanded macro looks like this:
+
+ %name(maxint) int max(int a, int b);
+ %name(maxdouble) double max(double a, double b);
+
+ A similar technique is used for template classes. For instance:
+
+ template<class T> class vector {
+ T *data;
+ int sz;
+ public:
+ vector(int nitems);
+ T *get(int n);
+ ...
+ };
+
+ Gets converted into a macro like this:
+
+ %define %_template_vector(__name, T)
+ %{
+ typedef vector<T> __name;
+ %}
+ class __name {
+ T *data;
+ int sz;
+ public:
+ __name(int nitems);
+ T *get(int n);
+ ...
+ };
+ typedef __name vector<T>;
+ %enddef
+
+ A specific instantiation is created in exactly the same way:
+
+ %template(intvec) vector<int>;
+
+ The resulting code parsed by SWIG is then:
+
+ %{
+ typedef vector<int> intvec;
+ %}
+ class intvec {
+ int *data;
+ int sz;
+ public:
+ intvec(int nitems);
+ int *get(int n);
+ ...
+ };
+ typedef intvec vector<int>;
+
+ Note: the last typedef is non-standard C and is used by SWIG to provide
+ an association between the name "intvec" and the template type
+ "vector<int>".
+
+ CAUTION: This is an experimental feature and the first time SWIG has
+ supported C++ templates. Error reporting is essential non-existent.
+ It will probably break in certain cases.
+ *** EXPERIMENTAL NEW FEATURE ****
+
+8/15/2001: beazley
+ Change to wrapping of multi-dimensional arrays. Arrays
+ are now properly mapped to a pointer to an array of
+ one less dimension. For example:
+
+ int [10]; --> int *
+ int [10][20]; --> int (*)[20];
+ int [10][20][30]; --> int (*)[20][30];
+
+ This change may break certain SWIG extensions because
+ older versions simply mapped all arrays into a single
+ pointer such as "int *". Although possibly unusual,
+ the new version is correct in terms of the C type system.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/06/2001: cheetah (william fulton)
+ * [Java] Array setters generated for struct/class array members.
+
+8/13/2001: beazley
+ Many improvements to Tcl/Perl/Python modules to better
+ work with multiple interface files and the %import directive.
+
+8/13/2001: beazley
+ Fixed up the behavior of %import in the Python module.
+ SWIG no longer pollutes the module namespace by using
+ 'from module import *' to refer to the other module.
+ Instead, it does a proper 'import module'. Also, SWIG
+ may work a lot better when importing modules that include
+ references to other imported modules.
+
+8/13/2001: mkoeppe
+ Added new typemap substitutions, generalizing those of the
+ Guile-specific 5/27/2001 changes:
+ * $descriptor is the same as SWIGTYPE$mangle, but also
+ ensures that the type descriptor of this name gets
+ defined.
+ * $*type, $*ltype, $*mangle, $*descriptor are the same as
+ the variants without star, but they REMOVE one level of
+ pointers from the type. (This is only valid for pointer
+ types.)
+ * $&type, $&ltype, $&mangle, $&descriptor are the same as
+ the variants without ampersand, but they ADD one level of
+ pointers to the type.
+ The Guile-specific substitution $basedescriptor was removed
+ because it was useless.
+
+8/12/2001: beazley
+ The %extern directive is now deprecated and withdrawn. The
+ purpose of this directive was to import selected definitions
+ from other interface files and headers. However, the same
+ functionality is better handled through %import. This
+ leaves SWIG with two file inclusion directives:
+
+ %include filename - Inserts into current interface
+ %import filename - Import types and classes from
+ another module
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/09/2001: beazley
+ Added new support for wrapping C/C++ callback functions.
+ A common problem with some C libraries is that many
+ functions take a function pointer as an argument. For example:
+
+ int do_op(..., int (*op)(int,int), ...);
+
+ Unfortunately, the only way to call such a function is to
+ pass it a function pointer of some compatible type. In
+ previous versions of SWIG, you had to solve this problem
+ with some really gross hacks. For example, if you wanted to
+ use the following function as a callback,
+
+ int foo(int, int);
+
+ you had to install a pointer to it as a constant. For example:
+
+ %constant int (*FOO)(int,int) = foo;
+
+ or
+
+ const int (*FOO)(int,int) = foo;
+
+ or if you had a really old SWIG version:
+
+ typedef int (*OP_FUNC)(int,int);
+ int do_op(..., OP_FUNC, ...);
+ const OP_FUNC FOO = foo;
+
+
+ Now, you can do one of two things:
+
+ %constant int foo(int,int);
+
+ This creates a constant 'foo' of type int (*)(int,int).
+ Alternatively, you can do this:
+
+ %callback("%s");
+ int foo(int,int);
+ int bar(int,int);
+ %nocallback;
+
+ In this case, the functions are installed as constants where
+ the name is defined by the format string given to %callback().
+ If the names generated by the format string differ from the
+ actual function name, both a function wrapper and a callback
+ constant are created. For example:
+
+ %callback("%(upper)s");
+ int foo(int,int);
+ int bar(int,int);
+ %nocallback;
+
+ Creates two wrapper functions 'foo', 'bar' and additionally
+ creates two callback constants 'FOO', 'BAR'.
+
+ Note: SWIG still does not provide automatic support for
+ writing callback functions in the target language.
+ *** NEW FEATURE ***
+
+8/06/2001: cheetah (william fulton)
+ * struct nesting fixes as per SF bug #447488.
+
+8/03/2001: beazley
+ The %name directive now applies to constants created with
+ #define and %constant. However, most language modules
+ were never written to support this and will have to be
+ modified to make it work. Tcl, Python, and Perl modules
+ are working now.
+ *** NEW FEATURE ***
+
+8/03/2001: beazley
+ Massive changes and simplification of C declaration parsing.
+ Although SWIG is still not a full C parser, its ability
+ to handle complex datatypes including pointers to functions
+ and pointers to arrays has been vastly improved.
+
+8/03/2001: cheetah (william fulton)
+ * Distribution fixes: autoconf no longer needed to install SWIG.
+
+8/02/2001: beazley
+ Removed two undocumented parsing features. SWIG no longer
+ supports out-of-class static function or variable
+ declarations. For example:
+
+ static int Foo::bar;
+
+ This feature may return if there is sufficient demand.
+ However, since SWIG is most often used with header files,
+ it is more likely for these definitions to be included
+ in the class definition.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/02/2001: cheetah (william fulton)
+ * Cleanup of the GIFPlot examples. Upgraded Java GIFPlot example.
+
+8/01/2001: cheetah (william fulton)
+ * [Java] Efficiency changes: _cPtr used where possible rather than
+ getCPtr(). Bug fixes for inheritance - derived class sometimes
+ didn't delete the c memory when _delete() was called.
+ * [Java] Abstract c++ classes are wrapped with a java abstract shadow
+ class. Also a pure virtual function is mapped with an abstract method.
+ * The default output file has always been <module>_wrap.c. It is now
+ <module>_wrap.cxx if the -c++ commandline option is passed to swig.
+ This has been done as otherwise c++ code would appear in a c file.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/31/2001: beazley
+ Modified the %constant directive to be more C-like in syntax.
+ The syntax is now:
+
+ %constant NAME = VALUE;
+ %constant TYPE NAME = VALUE;
+
+ For example:
+
+ %constant Foo *Bar = &Spam;
+
+ A more subtle case is as follows:
+
+ %constant int (*FOO)(int,int) = blah;
+
+ *** POTENTIAL INCOMPATIBILITY *** Modules that were using
+ the %constant directive directly will need to be modified.
+
+7/30/2001: beazley
+ Removed obscure and undocumented form of the %inline directive:
+
+ %inline int blah(int a, int b) {
+ ...
+ }
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ (note: this feature was never documented and is withdrawn)
+
+7/30/2001: beazley
+ Removed support for functions with no explicitly declared
+ return type. For example:
+
+ foo(int);
+
+ In C, such functions were implicitly assumed to return an 'int'.
+ In C++, this is illegal. Either way, it's considered bad
+ style. Removing support for this in SWIG will simplify
+ certain issues in parsing.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/30/2001: mkoeppe
+ * Partial merge from the CVS trunk. The Source/DOH directory
+ and most of the Source/Swig directory is up-to-date now.
+ * [Guile] %scheme is now a macro for %insert("scheme").
+ New syntax: %scheme "FILENAME";
+ New syntax: %scheme %{ SCHEME-CODE %}
+ New macros %multiple_values, %values_as_list,
+ %values_as_vector.
+
+7/29/2001: beazley
+ %readonly and %readwrite have been turned into SWIG pragmas.
+ %pragma(swig) readonly and %pragma(swig) readwrite. Macros
+ are used to provide backwards compatibility.
+
+7/29/2001: beazley
+ Minor changes to %pragma directive. %pragma must always
+ be directed to a specific language. For example:
+
+ %pragma(swig) make_default;
+ %pragma(perl5) include = "blah.i";
+
+ Also extended the pragma directive to allow code blocks
+
+ %pragma(foo) code = %{
+ ... some code ...
+ %}
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/29/2001: beazley
+ Change to the way 'const' variables are wrapped. In
+ previous versions of SWIG, a 'const' variable was
+ wrapped as a constant. Now, 'const' variables are
+ wrapped as read-only variables. There are several
+ reasons for making this change, mostly pertaining to
+ subtle details of how 'const' actually works.
+
+ This will probably break old interfaces that used 'const'
+ to create constants. As a replacement, consider using this:
+
+ const int a = 4; ===> %constant int a = 4;
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/29/2001: beazley
+ Reorganization and simplification of type parsing.
+ Types with 'const' should work correctly now.
+
+7/29/2001: beazley
+ Most swig directives related to the documentation system
+ are now deprecated.
+
+7/29/2001: beazley
+ Removed support for Objective-C in order to simplify
+ parser reconstruction. Will return if there is sufficient
+ demand.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/29/2001: beazley
+ Code inclusion has been modified in the parser. A common
+ directive %insert is now used for everything. This
+ inserts a file into the output:
+
+ %insert(header) "foo.swg"
+
+ This inserts some inline code into the output
+
+ %insert(header) %{
+ ... some code ...
+ %}
+
+ There are five predefined targets for the insert directive:
+
+ "header" - Header section of wrapper file
+ "runtime" - Runtime section of wrapper file
+ "wrapper" - Wrapper section
+ "init" - Initialization function
+ "null" - Nothing. Discard.
+
+ The following directives are still supported, but are
+ now defined in terms of macros:
+
+ %{ ... %} -> %insert(header) %{ ... %}
+ %init %{ ... %} -> %insert(init) %{ ... %}
+ %wrapper %{ ... %} -> %insert(wrapper) %{ ... %}
+ %runtime %{ ... %} -> %insert(runtime) %{ ... %}
+
+ Language modules can define new named targets by using the
+ C API function Swig_register_filebyname() (see main.cxx).
+ For example, if you wanted to expose a shadow class file,
+ you could do this:
+
+ Swig_register_filebyname("shadow", f_shadow);
+
+ Then in the interface file:
+
+ %insert(shadow) %{ ... %}
+
+ Note: this change should not affect any old interfaces, but
+ does open up new possibilities for enhancements.
+
+7/29/2001: beazley
+ SWIG now always includes a standard library file 'swig.swg'.
+ This file defines a large number of macro definitions
+ that define the behavior of various SWIG directives.
+ Previously, all SWIG directives were handled as special
+ cases in the parser. This made the parser a large
+ bloated mess. Now, the parser is stripped down to a few
+ simple directives and macros are used to handle everything else.
+
+7/26/2001: cheetah (william fulton)
+ * Fixes for Sourceforge bug #444748 - new testcase cpp_static:
+ [TCL] Class with just static member variable/function fix
+ [Java] Fixed static variables support
+ [Ruby] Static variables workaround removed
+
+7/27/2001: mkoeppe
+ * stype.c (SwigType_default): Strip qualifiers first. The
+ default type of "int * const" is now "SWIGPOINTER *".
+ * main.cxx: Define "__cplusplus" in SWIG's preprocessor if
+ in C++ mode.
+ * [Guile]: Added some support for arrays and C++
+ references, fixing the "constant_pointers" test case.
+ * Moved most tests from the old Guile-specific test-suite
+ to the new test-suite. Also moved perl5/pointer-cxx
+ example there.
+
+7/26/2001: cheetah (william fulton)
+ * Test-suite added.
+ * Initial testcases: constant_pointers cpp_enum defines
+ sizeof_pointers unions virtual_destructor
+ * Make clean improvements.
+
+7/24/2001: cheetah (william fulton)
+ * [Java] Underscores in the package name and/or module name
+ no longer give linking problems.
+
+7/17/2001: cheetah (william fulton)
+ * More parser bug fixes for constant pointers
+
+7/19/2001: mkoeppe
+ * [Guile] Aesthetic improvement in variable wrappers.
+
+7/18/2001: beazley
+ * Fixed core-dump problem in pointer library when
+ freeing character arrays.
+ SF Bug [ #415837 ] pointer lib core dump
+
+7/18/2001: beazley
+ * Fixed problem with default destructors and shadow
+ classes. SF bug #221128.
+
+7/18/2001: beazley
+ * To provide better line-number tracking in interfaces
+ with lots of macros, special locator comments are
+ now generated by the SWIG preprocessor. For example:
+
+ /*@foo.i,42,BLAH@*/expanded macro/*@@*/
+
+ The first /*@...@*/ sequence sets the context
+ to point to the macro code. The /*@@*/ comment
+ terminates the context. The SWIG parser should
+ ignore all of the locator comments as should
+ the C compiler (should such comments end up
+ in generated wrapper code).
+
+7/18/2001: mkoeppe
+ * The parser now handles severely constified types in
+ typemaps. This introduced a new shift/reduce conflict, but
+ only with a heuristic function-pointer catch-all rule.
+ * [Guile]: Added typemaps for severely constified types.
+ * Fixed the "template-whitespace" problem by canonicalizing
+ whitespace, especially around angle brackets and commas.
+
+7/17/2001: mkoeppe
+ * [Guile]: A Scheme file is emitted if the -scmstub FILE.SCM
+ command-line option is used. The %scheme directive
+ (implemented as a macro for a pragma) allows to insert
+ arbitrary code here. In "simple" and "passive" linkage,
+ the file gets filled with define-module and export
+ declarations.
+
+7/17/2001: cheetah (william fulton)
+ * Parser bug fix to support constant pointers, eg int* const ptr.
+ Fixed everywhere - variables, parameters, return types etc. Note that
+ when wrapping a constant pointer variable only the getter is generated.
+
+7/17/2001: mkoeppe
+ * Fixed SF bug #441470 (#define X "//" would not be parsed,
+ see test-suite entry "preproc-1"), reported by T. W. Burton
+ * Changed the type of character constants to "char", rather
+ than "char *". Changed the individual language modules
+ to keep the old behaviour, except for the Guile module,
+ where it is desired to make them Scheme characters. This
+ fixes SF bug #231409, test-suite entry "char-constant".
+ * Applied patch for DOH/Doh/memory.c by Les Schaffer
+ <[email protected]> (avoid required side effects in
+ assert).
+
+7/17/2001: cheetah (william fulton)
+ * Bug fix in parser for virtual destructor with void as parameter
+ * Bug fix in parser #defines embedded within classes/structs/unions
+ Consequently %constant can now also be placed within a struct/class/union.
+ * Bug fix in parser to allow sizeof(*I_am_a_pointer) within a #define
+
+7/16/2001: mkoeppe
+ * Added changes for the Macintosh contributed by Luigi
+ Ballabio <[email protected]>.
+ * Some "const" fixes in the code.
+ * [Guile]: Made the constant-wrapper functions much shorter.
+
+7/13/2001: mkoeppe
+ * [Guile]: Some "const" fixes for Guile version 1.3.4.
+ * Handle anonymous arguments with default values and static
+ array members of classes. Both bugs reported by Annalisa Terracina
+ <[email protected]>; see the files
+ Examples/guile/test-suite/static-array-member.i and
+ anonymous-arg.i.
+
+Version 1.3.6 (July 9, 2001)
+=============================
+
+7/09/2001: cheetah (william fulton)
+ * GIFPlot examples: FOREGROUND and BACKGROUND definition missing
+ after TRANSPARENT #define fix in GIFPlot
+
+7/03/2001: beazley
+ Fixed up the version numbers so that the release is known
+ as 1.3.6. All future releases should have a similar
+ version format.
+
+7/02/2001: mkoeppe
+ * [Python]: Prevent the problem of self.thisown not being
+ defined if the C++ class constructor raised an exception.
+ Thanks to Luigi Ballabio <[email protected]>.
+
+6/29/2001: mkoeppe
+ * More portability fixes; fixed "gcc -Wall" warnings.
+
+6/29/2001: cheetah (william fulton)
+ * GIFPlot examples: TRANSPARENT #define multiple times on Solaris
+ (clashes with stream.h).
+ * Multiple definition bug fix for shadow classes. The perl and python
+ modules had workarounds which have been replaced with fixes in
+ the core. Many of the Language::cpp_xxxx functions now set a
+ flag which the derived classes can access through
+ is_multiple_definition() to see whether or not code should be
+ generated. The code below would have produced varying degrees
+ of incorrect shadow class code for the various modules:
+ class TestClass
+ {
+ public:
+ TestClass() {}
+ TestClass(int a) {}
+ ~TestClass() {}
+ unsigned long xyz(short k) {}
+ unsigned long xyz(int n) {}
+ static void static_func() {}
+ static void static_func(int a) {}
+ };
+ void delete_TestClass(int a);
+
+6/27/2001: mkoeppe
+ * [Perl] Another const-related portability fix.
+
+6/26/2001: cheetah (william fulton)
+ * [Java] Added in cpp_pragma() support with a host of new pragmas - see
+ jswig.html. These are designed for better mixing of Java and c++. It
+ enables the user to specify pure Java classes as bases and/or interfaces
+ for the wrapped c/c++.
+ * [Java] Old pragmas renamed. Warning given for the moment if used.
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+6/25/2001: mkoeppe
+ * Incorporated more build changes contributed by Wyss Clemens
+ <[email protected]> for swig/ruby on cygwin.
+
+6/20/2001: cheetah (william fulton)
+ * Makefile mods so that 'make check' uses the swig options in the makefiles
+ * [Java] Removed Generating wrappers message
+ * [Java] NULL pointer bug fix
+ * [Java] Bug fix for Kaffe JVM
+
+6/20/2001: mkoeppe
+ * SWIG_TypeQuery from common.swg now returns a
+ swig_type_info* rather than a void*. This fixes a problem
+ when using pointer.i and C++, as illustrated by the new
+ test-suite example perl5/pointer-cxx.
+ * Portability fixes (const char *).
+ * Incorporated build changes contributed by Wyss Clemens
+ <[email protected]>, which make swig runnable on cygwin.
+
+6/19/2001: cheetah (william fulton)
+ * [Java] Bug fix for SF bug #211144. This fix is a workaround
+ until fixed in the core.
+
+6/19/2001: mkoeppe
+ * [Guile]: Portability fixes for use with the Sun Forte
+ compilers.
+ * [Tcl]: Portability fix (const char *).
+ * [Tcl]: Configure now first tries to find a tclConfig.sh
+ file in order to find the Tcl include directory, library
+ location and library name.
+ * [Python]: Added a few possible library locations.
+
+6/18/2001: mkoeppe
+ * [Guile]: Don't call scm_c_export if nothing is to be
+ exported. Don't warn on %module if module has been set
+ already (this frequently occurs when %import is used).
+
+6/16/2001: mkoeppe
+ * [Guile]: New "passive" linkage, which is appropriate for
+ multi-module extensions without Guile module magic.
+
+6/15/2001: mkoeppe
+ * [Guile]: Fixed printing of smobs (space and angle were
+ missing).
+ * Properly generate type information for base classes
+ imported with the %import directive. Thanks to Marcelo
+ Matus <[email protected]> for the report and the
+ patch; this closes SF bug #231619; see also
+ Examples/guile/test-suite/import*.
+ * [Guile]: Fix casting between class and base class; the
+ runtime type system had it the wrong way around; see
+ Examples/guile/test-suite/casts.i
+ * Make typemaps for SWIGPOINTER * with arg name take
+ precedence over those without arg name, to match normal
+ typemap precedence rules.
+ * Fixed the random-line-numbers problem reported as SF bug
+ #217310; thanks to Michael Scharf <[email protected]>.
+ * [Guile]: Handle the %name and %rename directives.
+ * New syntax: %name and %rename now optionally take double
+ quotes around the scripting name. This is to allow scripting
+ names that aren't valid C identifiers.
+
+6/14/2001: beazley
+ Made a minor change to the way files are loaded in
+ order to get file/line number reporting correct in
+ the preprocessor.
+
+6/14/2001: mkoeppe
+ * The parser now understands the (non-standard) "long long"
+ types. It is up to the individual language modules to
+ provide typemaps if needed. Reported by Sam Steingold, SF
+ bug #429176.
+ * The parser now understands arguments like "const int *
+ const i". This fixes SF bug #215649.
+ * Fixed the Guile test-suite.
+
+6/13/2001: mkoeppe
+ Partial merge from the CVS trunk at tag
+ "mkoeppe-merge-1". This covers the following changes:
+
+| 01/16/01: ttn
+| Wrote table of contents for Doc/engineering.html. Added section
+| on CVS tagging conventions. Added copyright to other docs.
+| 9/25/00 : beazley
+| Modified the preprocessor so that macro names can start with a '%'.
+| This may allow new SWIG "directives" to be defined as macros instead
+| of having to be hard-coded into the parser.
+|
+| *** Also a yet-to-be-documented quoting mechanism with backquotes
+| *** has been implemented?
+
+6/13/2001: mkoeppe
+ * When configure does not find a language, don't use default
+ paths like /usr/local/include; this only causes build
+ problems.
+ * New directory: Examples/Guile/test-suite, where a few
+ bugs in 1.3a5 are demonstrated.
+ * Handle C++ methods that have both a "const" and a "throw"
+ directive (see Examples/Guile/test-suite/cplusplus-throw.i);
+ thanks to Scott B. Drummonds for the report and the fix.
+ * Handle C++ pointer-reference arguments (like "int *& arg")
+ (see Examples/Guile/test-suite/pointer-reference.i,
+ reported as SF bug #432224).
+ * [Ruby] Fixed typo in rubydec.swg; thanks to Lyle Johnson!
+ * Don't stop testing when one test fails.
+ * [Guile, MzScheme] Don't print "Generating wrappers...".
+
+6/12/2001: mkoeppe
+ [Guile] VECTORLENINPUT and LISTLENINPUT now have separate
+ list length variables. TYPEMAP_POINTER_INPUT_OUTPUT
+ attaches argument documentation involving SCM_TYPE to the
+ standard pointer typemaps. INOUT is now an alias for BOTH.
+
+6/12/2001: cheetah (william fulton)
+ Some Java documentation added.
+ [Java] Fixed bugs in import pragma and shadow pragma.
+
+6/12/2001: mkoeppe
+ Fix declarations of SWIG_define_class
+ (Lib/ruby/rubydec.swg) and SWIG_TypeQuery
+ (Lib/common.swg). Thanks to Lyle Johnson
+ <[email protected]> for the patches.
+
+6/11/2001: mkoeppe
+ [Guile] Use long instead of scm_bits_t; this makes the
+ generated wrapper code compatible with Guile 1.3.4
+ again. Thanks to Masaki Fukushima for pointing this out.
+
+6/11/2001: cheetah (william fulton)
+ The generic INSTALL file from autoconf added. Few changes to README file.
+
+6/11/2001: mkoeppe
+ Fixed typo in Makefile.in; thanks to Greg Troxel
+
+6/08/2001: cheetah (william fulton)
+ make check works again. Examples/GIFPlot configure generated by
+ top level autoconf now.
+
+6/08/2001: mkoeppe
+ Another build change: The new script autogen.sh runs
+ autoconf in the appropriate directories. The top-level
+ configure also configures in Examples/GIFPlot.
+
+6/07/2001: mkoeppe
+ Made the Makefile work with non-GNU make again.
+
+6/07/2001: cheetah (william fulton)
+ [Java] Class/struct members that are arrays of pointers to classes/structs -
+ Shadow class's get/set accessors now use Java classes instead of longs (pointers).
+ [Java] Shadow classes will now clean up memory if function return type
+ is a class/struct.
+ [Java] New example called reference based on the same example from other modules.
+
+6/06/2001: mkoeppe
+ New configure option --with-release-suffix allows for
+ attaching a suffix to the swig binary and the swig runtime
+ libraries. Minor changes to the build system. "swig
+ -swiglib" works again. If invoked with the new option
+ "-ldflags", SWIG prints a line of linker flags needed to
+ link with the runtime library of the selected language
+ module.
+
+6/06/2001: mkoeppe
+ [Guile] gswig_list_p is an int, not a SCM. This typo
+ caused warnings when compiling with a Guile configured with
+ strict C type checking. In INPUT and BOTH typemaps
+ generated by the SIMPLE_MAP macro, use the SCM_TO_C
+ function to convert from Guile to C (rather than C_TO_SCM).
+ Use scm_intprint to print pointers (rather than
+ sprintf). Allow using "-linkage" instead of "-Linkage".
+
+6/05/2001: cheetah (william fulton)
+ [Java] Mods for using inherited c++ classes from Java
+ [Java] New example called class based on the same example from other modules
+
+6/05/2001: cheetah (william fulton)
+ [Java] destructor (_delete()) was not aware of %name renaming
+ [Java] extends baseclass did not know about %name renaming
+ [Java] extends baseclass did extend even when the baseclass was not known to swig
+ [Java] sometimes enum-declarations occurred before the Java class declaration
+ [Java] unrelated enum initialisations no longer appear in Java class
+ [Java] if module ends in '_' correct JNI names are now produced
+
+6/04/2001: cheetah (william fulton)
+ [Java] Shadow class mods - Modified constructor replaces
+ newInstance(). _delete() now thread safe. getCPtr() replaces
+ _self. _selfClass() removed as now redundant.
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+ [Java] Not all output java files had SWIG banner. New banner.
+
+ [Java] Shadow class finalizers are output by default: Command
+ line option -finalize deprecated and replaced with -nofinalize.
+ *** POTENTIAL INCOMPATIBILITY FOR JAVA MODULE ***
+
+6/ 1/2001: mkoeppe
+ [Guile] Cast SCM_CAR() to scm_bits_t before shifting it.
+ This is required for compiling with a Guile configured with
+ strict C type checking.
+
+6/ 1/2001: mkoeppe
+ Added configure option "--with-swiglibdir".
+
+5/31/2001: mkoeppe
+ [Guile] Support multiple parallel lists or vectors in
+ the typemaps provided by list-vector.i. New typemaps file,
+ pointer-in-out.i.
+
+5/25/2001: cheetah (william fulton)
+ [Java] HTML update for examples.
+
+5/28/2001: mkoeppe
+ Minor changes to the build system. Added subdirectory for
+ Debian package control files.
+
+5/28/2001: mkoeppe
+ [Guile] Build a runtime library, libswigguile.
+
+5/28/2001: mkoeppe
+ [Guile] New typemap substitution $*descriptor. Use the {}
+ syntax, rather than the "" syntax for the standard
+ typemaps, in order to work around strange macro-expansion
+ behavior of the SWIG preprocessor. This introduces some
+ extra braces.
+
+5/27/2001: mkoeppe
+ [Guile] Handle pointer types with typemaps, rather than
+ hard-coded. New typemap substitutions $descriptor,
+ $basedescriptor; see documentation. Some clean-up in the
+ variable/constants wrapper generator code. New convenience
+ macro SWIG_Guile_MustGetPtr, which allows getting pointers
+ from smobs in a functional style. New typemap file
+ "list-vector.i", providing macros that define typemaps for
+ converting between C arrays and Scheme lists and vectors.
+
+5/25/2001: cheetah (william fulton)
+ [Java] STL string moved into its own typemap as it is c++ code and
+ it break any c code using the typemaps.i file.
+ - Fixes for wrappers around global variables - applies to primitive
+ types and user types (class/struct) and pointers to these.
+ - Structure member variables and class public member variables getters
+ and setters pass a pointer to the member as was in 1.3a3 and 1.1
+ (1.3a5 was passing by value)
+ - Parameters that were arrays and return types were incorrectly
+ being passed to create_function() as pointers.
+ - Fix for arrays of enums.
+ [Java] Updated java examples and added two more.
+ [Java] Java module updated from SWIG1.3a3 including code cleanup etc.
+ [Java] enum support added.
+ [Java] Array support implemented
+ [Java] Shadow classes improved - Java objects used rather than
+ longs holding the c pointer to the wrapped structure/c++class
+
+5/22/2001: mkoeppe
+ [Guile] Fixed extern "C" declarations in C++ mode. Thanks
+ to Greg Troxel <[email protected]>.
+
+5/21/2001: mkoeppe
+ [Guile] New linkage "module" for creating Guile modules for
+ Guile versions >= 1.5.0.
+
+4/18/2001: mkoeppe
+ [MzScheme] Added typemaps for passing through Scheme_Object
+ pointers.
+
+4/9/2001 : mkoeppe
+ [MzScheme] Added typemaps for `bool'. Inclusion of headers
+ and support routines is now data-driven via mzscheme.i.
+ Headers come from the new file mzschemdec.swg. Don't abort
+ immediately when a type-handling error is reported. When
+ searching for typemaps for enums, fall back to using int,
+ like the Guile backend does. Support char constants. Emit
+ correct wrapper code for variables.
+
+3/12/2001: mkoeppe
+ [Guile] Fixed typemaps for char **OUTPUT, char **BOTH.
+
+3/2/2001 : mkoeppe
+ [Guile] Every wrapper function now gets a boolean variable
+ gswig_list_p which indicates whether multiple values are
+ present. The macros GUILE_APPEND_RESULT, GUILE_MAYBE_VALUES
+ and GUILE_MAYBE_VECTOR use this variable, rather than
+ checking whether the current return value is a list. This
+ allows for typemaps returning a list as a single value (a
+ list was erroneously converted into a vector or a
+ multiple-value object in this case).
+
+3/1/2001 : mkoeppe
+ [Guile] Added support for returning multiple values as
+ vectors, or passing them to a muliple-value
+ continuation. By default, multiple values still get
+ returned as a list.
+
+3/1/2001 : mkoeppe
+ [Guile] Added a "beforereturn" pragma. The value of this
+ pragma is inserted just before every return statement.
+
+3/1/2001 : mkoeppe
+ [Guile] Added support for Guile 1.4.1 procedure
+ documentation formats, see internals.html.
+
+2/26/2001: mkoeppe
+ [Guile] Made the wrapper code compile with C++ if the
+ "-c++" command-line switch is given. Thanks to
+
+2/26/2001: mkoeppe
+ [Guile] Now two type tables, swig_types and
+ swig_types_initial, are used, as all other SWIG language
+ modules do. This removes the need for the tricky
+ construction used before that the broken Redhat 7.0 gcc
+ doesn't parse. Reported by <[email protected]>.
+
+2/26/2001: mkoeppe
+ [Guile] Fixed typemaps for char *OUTPUT, char *BOTH; a bad
+ free() would be emitted. Added typemap for SCM.
+
+
+Version 1.3 Alpha 5
+===================
+
+9/19/00 : beazley
+ [Python] Python module generates more efficient code for
+ creating the return value of a wrapper function. Modification
+ suggested by Jon Travis.
+
+9/19/00 : beazley
+ Library files specified with the -l option are now included at the
+ end of the interface file (reverting to the old behavior).
+
+9/19/00 : beazley
+ Fixed some problems with enum handling. enums are now manipulated as
+ 'int', but cast into the enum type when values are passed to the
+ corresponding C function.
+
+9/19/00 : mkoeppe
+ [Guile] Removed "-with-smobs" command-line option, as this is the
+ default now. Added "-emit-setters" command-line option,
+ which turns on generating procedures-with-setters; see
+ internals.html.
+
+9/18/00 : mkoeppe
+ Incorporated patch #101430, fixing bugs in the Guile module:
+ 1. Some arguments were erroneously taken as *optional* arguments when
+ ignored arguments were present.
+ 2. Guile 1.3.4 was not supported since functions introduced in Guile
+ 1.4 were used.
+ 3. Added handling of `const char *'.
+
+9/17/00 : beazley
+ Fixed problem with failed assertion and large files.
+
+9/17/00 : beazley
+ Fixed problem with the '%' character appearing in added methods
+ and function bodies. Preprocessor bug.
+
+Version 1.3 Alpha 4 (September 4, 2000)
+=======================================
+
+9/3/00 : ttn
+ Added instructions for maintainers in Examples/README on how
+ to make examples also be useful in the testing framework.
+ Also, "make check" now uses ./Lib by via env var `SWIG_LIB'.
+ This is overridable like so:
+ make chk-swiglib=/my/experimental/swig/Lib check
+
+9/3/00 : beazley
+ Added $typemap variable to typemaps. This gets replaced with
+ a string indicating the typemap that is applied. Feature
+ request from rsalz.
+
+9/3/00 : beazley
+ Experimental optimization to code generation for virtual
+ member functions. If you have two classes like this:
+
+ class A() {
+ virtual void foo();
+ }
+
+ class B() : public A {
+ virtual void foo();
+ }
+
+ Swig now will generate a single wrapper function for this
+
+ A_foo(A *a) {
+ a->foo();
+ }
+
+ and use it as the implementation of both A_foo() and B_foo().
+ This optimization only takes place if both methods are declared
+ as virtual and both take identical parameters.
+ *** EXPERIMENTAL FEATURE ***
+
+9/3/00 : beazley
+ Restored the "memberin" typemap for setting structure members.
+ Unlike the old version, the new version is expanded inline in the
+ wrapper function allowing access to scripting language
+ internals (a sometimes requested feature). The "memberout" typemap
+ is gone. Use the "out" typemaps instead.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+9/3/00 : beazley
+ Attribute set methods no longer return the value of a member.
+ For example:
+
+ struct Foo {
+ int x;
+ ...
+ }
+
+ now gets set as follows:
+
+ void Foo_x_set(Foo *f, int x) {
+ f->x = x;
+ }
+
+ In SWIG1.1 it used to be this:
+
+ int Foo_x_set(Foo *f, int x) {
+ return (f->x = x);
+ }
+
+ This has been changed due to the complexity created by trying
+ to do this with more exotic datatypes such as arrays. It also
+ complicates inlining and handling of the "memberin" typemap.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+9/2/00 : beazley
+ Removed the ptrcast() and ptrmap() functions from the
+ pointer.i library file. Old implementation is incompatible
+ with new type system.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+9/2/00 : beazley
+ New runtime function SWIG_TypeQuery(const char *name) added.
+ This function can be used to extract the type info structure
+ that is used for type-checking. It works with either the
+ nice C name or mangled version of a datatype. For example:
+
+ swig_type_info *ty = Swig_TypeQuery("int *");
+ swig_type_info *ty = Swig_TypeQuery("_p_int");
+
+ This is an advanced feature that has been added to support some
+ exotic extension modules that need to directly manipulate
+ scripting language objects.
+ *** NEW FEATURE ***
+
+9/2/00 : beazley
+ New directive %types() added. This is used to
+ explicitly list datatypes that should be included in
+ the runtime type-checking code. Normally it is never
+ necessary to use this but sometimes advanced extensions
+ (such as the pointer.i library) may need to manually
+ add types to the type-checker.
+ *** NEW FEATURE ***
+
+8/31/00 : beazley
+ Improved handling of string array variables. For example,
+ a global variable of the form "char name[64]" is automatically
+ managed as a 64 character string. Previously this didn't
+ work at all or required the use of a special typemap.
+ *** NEW FEATURE (Tcl, Perl, Python) ***
+
+8/31/00 : ttn
+ Added Makefile target `check-c++-examples', which uses new
+ files under Examples/C++ contributed by Tal Shalif. Now "make
+ check" also does "make check-c++-examples". Also, expanded
+ actions in `check-gifplot-example' and `check-aliveness'.
+
+8/30/00 : mkoeppe
+ Major clean-up in the Guile module. Added typemap-driven
+ documentation system. Changed to handle more than 10
+ args. Updated and extended examples.
+ *** NEW FEATURE ***
+
+8/29/00 : beazley
+ Added new %insert directive that inserts the contents of a file
+ into a portion of the output wrapper file. This is only intended
+ for use by writers of language modules. Works as follows:
+
+ %insert(headers) "file.swg";
+ %insert(runtime) "file.swg";
+ %insert(wrappers) "file.swg";
+ %insert(init) "file.swg";
+
+ *** NEW FEATURE ***
+
+8/29/00 : beazley
+ Added new %runtime directive which includes code into the runtime
+ portion of the wrapper code. For example:
+
+ %runtime %{
+ ... some internal runtime code ...
+ %}
+
+ There is no practical reason for ordinary users to use this
+ feature (almost everything can be done using %{ ... %}
+ instead). However, writers of language modules may want to
+ use this in language configuration files.
+ *** NEW FEATURE ***
+
+8/28/00 : beazley
+ Typemaps can now be specified using string literals like
+ this:
+
+ %typemap(in) int "$target = SvIV($source);"
+
+ When code is specified like this, it is *NOT* enclosed
+ inside a local scope (as with older typemap declarations).
+ Note: character escape sequences are interpreted in the
+ code string so if you want to include a quote or some
+ other special character, make sure you use a (\).
+ *** NEW FEATURE ***
+
+8/27/00 : beazley
+ Typemaps have been modified to follow typedef declarations.
+ For example, if you have this:
+
+ typedef int Number;
+
+ %typemap(in) int {
+ ... get an integer ...
+ }
+
+ void foo(Number a);
+
+ The typemap for 'int' will be applied to the argument 'Number a'.
+ Of course, if you specify a typemap for 'Number' it will take
+ precedence (nor will it ever be applied to an 'int').
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/27/00 : beazley
+ Default typemap specification has changed. In older
+ versions of swig, you could do this:
+
+ %typemap(in) int SWIG_DEFAULT_TYPE {
+ ...
+ }
+
+ To specify the default handling of a datatype. Now that
+ SWIG follows typedef declarations, this is unnecessary.
+ Simply specifying a typemap for 'int' will work for all
+ variations of integers that are typedef'd to 'int'.
+
+ Caveat, specifying the default behavior for pointers,
+ references, arrays, and user defined types is a little
+ different. This must be done as follows:
+
+ %typemap() SWIGPOINTER * {
+ ... a pointer ...
+ }
+ %typemap() SWIGREFERENCE & {
+ ... a reference ...
+ }
+ %typemap() SWIGARRAY [] {
+ ... an array ...
+ }
+ %typemap() SWIGTYPE {
+ ... a user-defined type (by value) ...
+ }
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/15/00 : dustin
+ The file swig-1.3a1-1.spec has been added to the Tools directory.
+ It can be used to build a redhat package for SWIG, although it
+ will need to be updated for the next public release.
+
+8/15/00 : beazley
+ Typemaps have been completely rewritten. Eventually they may be
+ replaced with something better, but for now they stay. However,
+ there are a number of a significant changes that may trip some
+ people up:
+
+ 1. Typemap scoping is currently broken. Because of this, the
+ following code won't work.
+
+ %typemap(in) blah * {
+ ...
+ }
+ class Foo {
+ ...
+ int bar(blah *x);
+ }
+ %typemap(in) blah *; /* Clear typemap */
+
+ (this breaks because the code for the class Foo is actually
+ generated after the entire interface file has been processed).
+ This is only a temporary bug.
+
+ 2. In SWIG1.1, the %apply directive worked by performing a
+ very complex type-aliasing procedure. From this point on,
+ %apply is simply a generalized typemap copy operation.
+ For example,
+
+ %apply double *OUTPUT { double *x, double *y };
+
+ Copies *ALL* currently defined typemaps for 'double *OUTPUT' and
+ copies them to 'double *x' and 'double *y'.
+
+ Most people probably won't even notice this change in
+ %apply. However, where it will break things is in code like
+ this:
+
+ %apply double *OUTPUT { double *x };
+ %typemap(in) double *OUTPUT {
+ ... whatever ...
+ }
+
+ void foo(double *x);
+
+ In SWIG1.1, you will find that 'foo' uses the 'double *OUTPUT' rule
+ even though it was defined after the %apply directive (this is
+ the weird aliasing scheme at work). In SWIG1.3 and later,
+ the 'double *OUTPUT' rule is ignored because it is defined
+ after the %apply directive.
+
+ 3. The %clear directive has been modified to erase all currently
+ defined typemaps for a particular type. This differs from
+ SWIG1.1 where %clear only removed rules that were added using
+ the %apply directive.
+
+ 4. Typemap matching is now performed using *exact* types.
+ This means that things like this
+
+ %typemap(in) char * { }
+ %typemap(in) const char * { }
+
+ are different typemaps. A similar rule applies for pointers,
+ arrays, and references. For example:
+
+ %typemap(in) double * { }
+
+ used to apply to 'double &', 'double []', Now, it only applies
+ to 'double *'. If you want a 'double &', you'll need to handle
+ that separately.
+
+ 5. Array matching has been simplfied. In SWIG1.1, array matching
+ was performed by trying various combinations of dimensions.
+ For example, 'double a[10][20]' was matched as follows:
+
+ double [10][20]
+ double [ANY][20]
+ double [10][ANY]
+ double [ANY][ANY]
+
+ In SWIG1.3, only the following matches are attempted:
+
+ double [10][20]
+ double [ANY][ANY]
+
+ On the positive side, typemap matching is now *significantly* faster
+ than before.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+8/15/00 : beazley
+ Secret developer feature. Since datatypes are now represented as
+ strings internally, you can bypass limitations of the parser and
+ create a wild datatype by simply enclosing the raw string encoding
+ in backticks (``) and sticking it in the interface file anywhere a
+ type is expected. For example, `a(20).a(10).p.f(int,int)`. This
+ feature is only intended for testing (i.e., you want to see what
+ happens to your language module if it gets a reference to a pointer
+ to an array of pointers to functions or something).
+ *** SICK HACK ***
+
+8/14/00 : beazley
+ Completely new type-system added to the implementation.
+ More details later.
+
+8/11/00 : beazley
+ Cleaned up some of the I/O handling. SWIG no longer generates
+ any temporary files such as _wrap.wrap, _wrap.ii, _wrap.init.
+ Instead, these "files" are kept around in memory as strings
+ (although this is transparent to language modules).
+
+8/4/00 : ttn
+ Added Makefile target "check" and variants.
+ This can be used like "make check" or, to explicitly skip a
+ language LANG: "make skip-LANG=true check". LANG is skipped
+ automatically if ./configure determines that LANG support is
+ insufficient.
+
+ Currently, the check is limited to doing the equivalent of
+ "make all" in some of the Examples directories. This should
+ be expanded both horizontally (different types of tests) and
+ vertically (after "make all" in an Examples subdir succeeds,
+ do some additional tests with the resulting interpreter, etc).
+
+8/4/00 : ttn
+ Added Makefile target "distclean", which deletes all the
+ files ./configure creates, including config.status and friends.
+
+8/3/00 : harcoh
+ java changes??? [todo: document changes]
+
+7/23/00 : beazley
+ Typemaps have been modified to key off of the real datatypes
+ used in the interface file. This means that typemaps for
+ "const char *" and "char *" will be difference as will typemaps
+ for "Vector" and "Vector *."
+ *** POTENTIAL INCOMPATIBILITY ***
+ This is likely to break interfaces that rely on the odd type
+ handling behavior of typemaps in SWIG1.1--especially with
+ respect to interfaces involving pass-by-value.
+
+7/23/00 : beazley
+ New %constant directive. This directive can be used to
+ create true constants in the target scripting language.
+ It's most simple form is something like this:
+
+ %constant FOO 42;
+
+ In this case, the type is inferred from the syntax of the
+ value (in reality, all #define macros are translated into
+ directives of this form).
+
+ An expanded version is as follows:
+
+ %constant(Foo *) FOO = &FooObj;
+
+ In this case, an explicit type can be specified. This
+ latter form may be useful for creating constants that
+ used to be specified as
+
+ const Foo *FOO = &FooObj;
+
+ (which are now treated as variables).
+ *** EXPERIMENTAL FEATURE *** The syntax may change in
+ the final release.
+
+7/23/00 : beazley
+ Modified the parser so that variable declarations of the form
+ "const type *a" are handled as variables, not constants.
+ Note: SWIG1.1 handled this case erroneously because
+ const char *a is a pointer variable that can be reassigned.
+ *** POTENTIAL INCOMPATIBILITY ***
+ Note: just because this is the "right" way to do things,
+ doesn't mean it's the most appropriate interpretation.
+ I suspect that many C programmers might use 'const char *'
+ with the intent of creating a constant, without realizing
+ that they've created a reassignable global variable.
+
+7/23/00 : beazley
+ The C/C++ wrapping layer has been completely redesigned and
+ reimplemented. This change should iron out a few rough
+ spots with the handling of datatypes. In addition, the
+ wrapper code is somewhat cleaner.
+ *** POTENTIAL INCOMPATIBILITY ***
+ This change may break interfaces that involve
+ subtle corner-cases with typemaps and the %addmethods
+ directive since some of these features had somewhat
+ type handling behavior in SWIG1.1.
+
+7/23/00 : beazley
+ The "memberin" and "memberout" typemaps are gone for the
+ moment, but they might return as soon as I figure out
+ how to integrate them with some of the streamlined C wrapper
+ functions.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/22/00 : beazley
+ A variety of old type handling functions such as print_type(),
+ print_full(), print_mangle(), etc... are gone and have been
+ replaced with a smaller set of functions. See the file
+ Doc/internals.html for details. This will break all third
+ party language modules.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/20/00 : beazley
+ Deprecated the %val and %out directives. These directives
+ shouldn't really be necessary since typemaps can be used
+ to achieve similar results. This also cleans up the
+ handling of types and parameters quite a bit.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/20/00 : ttn
+ Fixed unspecified-module bug in Guile support and removed
+ more non-"with-smobs" functionality using patches submitted
+ by Matthias Koeppe.
+
+ Re-enable recognition of "-with-smobs" (with no effect since
+ we use smobs by default now) for the time being. After the
+ 1.3a4 release, this option will signal an error.
+
+7/17/00 : ttn
+ Fixed NULL-input bug in parameter list handling.
+ Reported by Matthias Koeppe.
+
+7/12/00 : beazley
+ Fixed memory leak in Python type-checking code. Reported by
+ Keith Davidson. Bug #109379.
+
+7/10/00 : beazley
+ Changed internal data structures related to function parameters.
+
+7/10/00 : beazley
+ Fixed some bugs related to the handling of the %name() directive
+ and classes in the Tcl module. Problem reported by James Bailey.
+
+7/10/00 : beazley
+ Fixed parsing and enum handling problems with character constants.
+ Reported by Greg Kochanski.
+
+7/10/00 : beazley
+ Removed WrapperFunction class from the core and updated the language
+ module. This will break third party modules.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/9/00 : beazley
+ Implementation of SWIG no longer makes use of C++ operator overloading.
+ This will almost certainly break *all* third party language modules
+ that are not part of the main SWIG CVS tree. Sorry.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/8/00 : beazley
+ Removed the experimental and undocumented "build" typemap that
+ was intended to work with multiple arguments. Simply too weird
+ to keep around. Besides, a better replacement is in the works.
+
+7/6/00 : ttn
+ Removed non-"with-smobs" functionality (Guile support), i.e.,
+ "-with-smobs" is now the default and no longer needs to be
+ specified on the command-line.
+
+7/5/00 : ttn
+ Incorporated Ruby support contributed by Masaki Fukushima.
+
+6/28/00 : ttn
+ Applied more-than-10-args bugfix patch contributed
+ by Matthias Koeppe.
+
+6/27/00 : beazley
+ Rewrote some of the string handling and eliminated the C++
+ implementation (which is now just a wrapper).
+
+6/27/00 : ttn
+ Added Doc/index.html and Doc/internals.html. The target
+ audience for the latter is new SWIG developers.
+
+
+Version 1.3 Alpha 3 (June 18, 2000)
+===================================
+
+6/18/00 : beazley
+ Removed the naming.cxx, hash.cxx, and symbol.cxx files from
+ the SWIG1.1 directory. Continued to migrate things away
+ from the C++ base (although there's still a lot of work to do).
+
+6/17/00 : beazley
+ Added a few more examples to the Examples directory. Still
+ need to do a lot of work on this.
+
+6/16/00 : beazley
+ Added -includeall to follow all #include statements in the
+ preprocessor.
+
+6/15/00 : beazley
+ Tried to fix as many C++ warnings as possible when compiling
+ with the Sun Workshop C++ compiler. Unfortunately, this means
+ that there are a lot of statements that contain string literals
+ of the form (char*)"Blah".
+
+6/15/00: beazley
+ A variety of cleanup and performance optimization in the
+ low-level DOH library. This seems to result in a speedup
+ of 50-100% for preprocessing and other related tasks.
+
+5/10/00 : ttn
+ Applied variable-wrapping bugfix patch contributed
+ by Matthias Koeppe.
+
+4/17/00 : ttn
+ Updated MzScheme support contributed by Oleg Tolmatcev.
+ We now use a `Scheme_Type'-based structure to wrap pointers.
+
+4/11/00 : ttn
+ Incorporated further Guile-support patch by Matthias Koeppe.
+ Typemaps previously deleted have been re-added. There is now
+ exception handling (see Doc/engineering.html). `SWIG_init' is now
+ declared extern only for simple linkage. Some bugs were fixed.
+
+4/06/00 : ttn
+ Incorporated MzScheme support contributed by Oleg Tolmatcev.
+ This includes new directories Lib/mzscheme and Examples/mzscheme.
+
+4/03/00 : ttn
+ Added Examples/guile and children. This is an adaptation of
+ the same-named directory from the SWIG-1.1p5 distribution.
+ Added Guile-specific section to Doc/engineering.html.
+
+4/02/00 : ttn
+ Incorporated new guilemain.i by Martin Froehlich.
+ Incorporated Guile-support rewrite patch by Matthias Koeppe.
+ The command line option "-with-smobs" enables implementation of
+ pointer type handling using smobs, the canonical mechanism for
+ defining new types in Guile. Previous implementation (using
+ strings) is at the moment still supported but deprecated. At
+ some point, "-with-smobs" will be the default and no longer
+ required.
+
+3/13/00 : beazley
+ Added purify patches submitted by Ram Bhamidipaty.
+
+3/02/00 : ttn
+ Added support for different Guile "linkage" schemes.
+ Currently, "-Linkage hobbit" works.
+
+
+Version 1.3 Alpha 2 (March 1, 2000)
+===================================
+
+2/29/00 : beazley
+ Made SWIG ignore the 'mutable' keyword.
+
+2/29/00 : beazley
+ Incorporated some patches to the Perl5 module related to
+ the -hide option and the destruction of objects.
+ Patch submitted by Karl Forner.
+
+2/27/00 : ttn
+ Incorporated Guile support contributed by Matthias Koeppe.
+ This includes a cpp macro in Lib/guile/guile.swg and the
+ entire file Lib/guile/typemaps.i.
+
+2/25/00 : ttn
+ Modified configure.in and Makefile.in files to support
+ non-local build (useful in multi-arch environments).
+
+2/24/00 : ttn
+ Incorporated Guile support contributed by Clark McGrew.
+ This works with Guile 1.3, but since it depends heavily
+ on the gh_ interface, it should work for all later versions.
+ It has not been tested with versions before 1.3.
+ WARNING: Code is unstable due to experimentation by ttn.
+
+2/16/00 : beazley
+ A variety of performance improvements to the Python shadow
+ class code generation. Many of these result in substantial
+ runtime performance gains. However, these have come at
+ a cost of requiring the use of Python 1.5.2. For older
+ versions, use 'swig -noopt -python' to turn off these
+ optimization features.
+
+Version 1.3 Alpha 1 (February 11, 2000)
+=======================================
+
+2/11/00 : Added 'void' to prototype of Python module initializer.
+ Reported by Mark Howson (1/20/00).
+
+2/11/00 : beazley
+ Modified the Python shadow class code to discard ownership of an
+ object whenever it is assigned to a member of another object.
+ This problem has been around for awhile, but was most recently
+ reported by Burkhard Kloss (12/30/99).
+
+2/11/00 : beazley
+ Added braces around macros in the exception.i library. Reported
+ by Buck Hodges (12/19/99)
+
+2/11/00 : beazley
+ Fixed bug in the constraints.i library. Reported by Buck
+ Hodges (12/14/99)
+
+2/11/00 : beazley
+ The %native directive now generates Tcl8 object-style command calls.
+ A full solution for Tcl7 and Tcl8 is still needed. Patch suggested
+ by Mike Weiblen (11/29/99)
+
+2/11/00 : beazley
+ Modified the typemap code to include the $ndim variable for arrays.
+ Patch provided by Michel Sanner (11/12/99).
+
+2/11/00 : beazley
+ Modified the Python module to raise a Runtime error if an attempt
+ is made to set a read-only member of a shadow class. Reported by
+ Michel Sanner (11/5/99).
+
+2/10/00 : The documentation system has been removed. However, it is likely
+ to return at some point in the future.
+
+2/1/00 : Added a number of performance enhancements to the Python shadow
+ classing and type-checking code. Contributed by Vadim Chugunov.
+
+ 1. Remove _kwargs argument from the shadow wrappers when -keyword
+ option is not specified. This saves us a construction of keyword
+ dictionary on each method call.
+
+ def method1(self, *_args, **_kwargs):
+ val = apply(test2c.PyClass1_method1, (self,) + _args, _kwargs)
+ return val
+
+ becomes
+
+ def method1(self, *_args):
+ val = apply(test2c.PyClass1_method1, (self,) + _args)
+ return val
+
+ 2. Incorporate self into the _args tuple. This saves at least one tuple
+ allocation per method call.
+
+ def method1(self, *_args):
+ val = apply(test2c.PyClass1_method1, (self,) + _args)
+ return val
+
+ becomes
+
+ def method1(*_args):
+ val = apply(test2c.PyClass1_method1, _args)
+ return val
+
+ 3. Remove *Ptr classes.
+ Assume that we are SWIGging a c++ class CppClass.
+ Currently SWIG will generate both CppClassPtr class
+ that hosts all methods and also CppClass that is derived
+ from the former and contains just the constructor.
+ When CppClass method is called, the interpreter will try
+ to find it in the CppClass's dictionary first, and only then
+ check the base class.
+
+ CppClassPtr functionality may be emulated with:
+
+ import new
+ _new_instance = new.instance
+ def CppClassPtr(this):
+ return _new_instance(CppClass, {"this":this,"thisown":0})
+
+ This saves us one dictionary lookup per call.
+
+ <DB>The new module was first added in Python-1.5.2 so it
+ won't work with older versions. I've implemented an
+ alternative that achieves the same thing</DB>
+
+ 4. Use CObjects instead of strings for pointers.
+
+ Dave: This enhancements result in speedups of up to 50% in some
+ of the preliminary tests I ran.
+
+2/1/00 : Upgraded the Python module to use a new type-checking scheme that
+ is more memory efficient, provides better performance, and
+ is less error prone. Unfortunately, it will break all code that
+ depends on the SWIG_GetPtr() function call in typemaps.
+ These functions should be changed as follows:
+
+ if (SWIG_GetPtr(string,&ptr,"_Foo_p")) {
+ return NULL;
+ }
+
+ becomes
+
+ if (SWIG_ConvertPtr(pyobj, &ptr, SWIG_TYPE_Foo_p) == -1) {
+ return NULL;
+ }
+
+ Note: In the new implementation SWIG_TYPE_Foo_p is no longer
+ a type-signature string, but rather an index into a type
+ encoding table that contains type information.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+1/30/00 : loic
+ Conditionally compile experimental code with --enable-experiment
+ configure flag.
+ Fix .cvsignore to ignore configure & yacc generated files
+
+1/28/00 : loic
+ Apply automake everywhere
+ Keep configure scripts so that people are not *forced* to autoconf
+ Keep sources generated by yacc so that compilation without yacc
+ is possible.
+ Source/LParse/cscanner.c: change lyacc.h into parser.h to please
+ default yacc generation rules.
+ Use AC_CONFIG_SUBDIRS in configure.in instead of hand made script.
+ Update all relevant .cvsignore to include .deps
+ Fixed missing ; line 136 Source/Swig/swig.h
+
+1/13/00 : beazley
+ Fixed a number of minor end-of-file parsing problems in the
+ preprocessor.
+
+1/13/00 : beazley
+ Added -freeze option that forces SWIG to freeze upon exit.
+ This is only used as a debugging tool so that I can more
+ easily examine SWIG's memory footprint.
+
+1/13/00 : beazley
+ Added patch to guile module for supporting optional arguments
+ Patch contributed by Dieter Baron.
+
+1/13/00 : loic
+ Added .cvsignore, Examples/.cvsignore, Source/DOH/Doh/.cvsignore
+ Source/SWIG1.1/main.cxx: Fixed -I handling bug
+ Source/Modules1.1/java.cxx: fixed char* -> const char* warnings that are
+ errors when compiling with gcc-2.95.2
+ Source/SWIG1.1/main.cxx: cast const char* to char* for String_replace
+ token and rep should really be const.
+
+1/12/00 : beazley
+ Added Harco's Java modules.
+
+1/12/00 : beazley
+ Revoked the %ifdef, %ifndef, %endif, %if, %elif, and %else
+ directives. These are no longer needed as SWIG now has a real
+ preprocessor.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+1/12/00 : beazley
+ Moved the documentation modules from the SWIG directory
+ to the Modules directory (where they really should have been
+ to begin with).
+
+1/12/00 : beazley
+ Removed the -stat option for printing statistics. The
+ statistics reporting was inadequate and mostly broken
+ anyway.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+1/12/00 : beazley
+ Removed the -t option for reading a typemap file. More
+ trouble than it's worth. Just include typemaps at the top
+ of the interface file.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+1/12/00 : beazley
+ Removed the %checkout directive.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+1/12/00 : beazley
+ Removed the -ci option for file checkin. Too problematic
+ to implement. Probably better to just put your SWIG library
+ under CVS instead.
+ *** POTENTIAL INCOMPATIBILITY ***.
+
+1/11/00 : beazley
+ Deleted the LATEX module. Sorry... Didn't know anyone
+ who was using it. Besides, I'm looking to simplify
+ the documentation system.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+1/11/00 : beazley
+ Modified the ASCII documentation module to use a .txt
+ suffix for its output file instead of .doc.
+
+1/11/00 : beazley
+ Added the long-lost SWIG preprocessor back to the system.
+ It should be enabled by default. Raw preprocessed output
+ can be viewed using swig -E file.i.
+ *** NEW FEATURE ***
+
+1/11/00 : beazley and djmitche
+ Completely reorganized the SWIG directory structure. The
+ basic organization is now:
+
+ Source/ SWIG source code
+ Lib/ SWIG library files (swig_lib)
+ Doc/ Documentation
+ Examples/ Examples
+
+ More directories will be added as needed.
+
+12/08/99: Loic Dachary ([email protected])
+ Enhanced package handling for perl5 and c++.
+
+ With new option -hide Foo::Bar, every perl5 object (Frob) is
+ qualified by Foo::Bar::Frob. The package name is solely used
+ to encapsulate C/C++ wrappers output in <module>_wrap.c and the
+ corresponding perl package in <module>.pm. Note that a package
+ name may contain :: (Frob::Nitz) and will be relative to the
+ package name provided by -hide (Foo::Bar::Frob::Nitz).
+
+ In *_wrap.c, SWIG_init macro is used. Was previously defined
+ but not used and simplifies code.
+
+ Added typemap(perl5,perl5in) and typemap(perl5,perl5out) that
+ do the equivalent of typemap(perl5,in) and typemap(perl5,out)
+ but contain perl code and applies to wrappers generated by
+ -shadow.
+
+ Lacking proper regression tests I used
+ Examples/perl5/{c++,constraint,defarg,except,
+ graph/graph[1234],multinherit,nested,shadow,simple,tree,
+ typemaps/{argv,argv2,arraymember,database,file,ignore,integer,
+ output,passref,reference,return}}/. I ran swig with and without
+ the patches, diff the generatedsources, run the .pl files
+ and checked that the results are identical. In all those examples
+ I had no error.
+
+11/21/99: Modified the Tcl module to provide full variable linking capabilities
+ to all datatypes. In previous versions, a pair of accessor functions
+ were created for datatypes incompatible with the Tcl_LinkVar() function.
+ Now, we simply use variable traces to support everything. This may
+ break scripts that rely upon the older behavior.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+11/21/99: Added slight tweak to wrapper generator to collect local variables
+ of similar type. Produces somewhat more compact wrapper code.
+
+11/20/99: Modified the Tcl module to use SWIG_GetArgs() to parse
+ arguments. This is a technique borrowed from Python in which
+ arguments are converted using a format string convention similiar
+ to fprintf(). This results in a *substantial* reduction in the
+ size of the resulting wrapper code with only a modest runtime overhead
+ in going through the extra conversion function.
+
+11/13/99: Completely rewrote the class/structure generation code for the
+ Tcl module. Now, a small set of runtime functions are used
+ to implement the functionality for all classes (instead of a
+ massive amount of runtime code being generated for each class).
+ Class specific information is simply encoded in a series of
+ static tables. This results in a *HUGE* reduction in wrapper
+ code size--especially for C++.
+
+11/13/99: Removed the -tcl (Tcl 7.x) module. Tcl 8.0 is now several
+ years old and the defacto standard--no real reason to keep
+ supporting the old version at this point.
+
+11/13/99: Cleaned up -c option for Python module. The pyexp.swg file
+ is now gone.
+
+11/13/99: Fixed external declarations to work better with static linking
+ on Windows. Static linking should now be possible by defining
+ the -DSTATIC_LINK option on the command line. Patch contributed
+ by Alberto Fonseca.
+
+11/5/99 : Fixed an obscure code generation bug related to the generation
+ of default constructors. Bug reported by Brad Clements.
+
+11/5/99 : Fixed a few memory problems found by purify.
+
+11/5/99 : Officially deprecated the -htcl, -htk, and -plugin options
+ from the Tcl and Tcl8 modules.
+
+10/26/99: Removed unused variable from python/typemaps.i. Patch
+ contributed by Keith Davidson.
+
+8/16/99 : Added _WIN32 symbol to libraries to better support Windows.
+
+8/16/99 : Deprecated the Perl4 module. It is no longer included in the
+ distribution and no longer supported. In the entire 3 years SWIG
+ has been around I never received a single comment about it so I'm
+ assuming no one will miss it...
+
+8/16/99 : Modified the type-checking code to register type mappings using a
+ table instead of repeated calls to SWIG_RegisterMapping(). This
+ reduces the size of the module initialization function somewhat.
+
+8/15/99 : Cleaned up the pointer type-checking code in the Tcl module.
+
+8/15/99 : Many changes to the libraries to support runtime libraries.
+
+8/13/99 : Eliminated C++ compiler warning messages about extern "C" linkage.
+
+8/13/99 : Some cleanup of Python .swg files to better support runtime libraries
+ on Windows.
+
+8/13/99 : Modified the %pragma directive to attach pragmas declared inside
+ a class definition to the class itself. For example:
+
+ class foo {
+ ...
+ %pragma(python) addtomethod = "insert:print `hello world'"
+ ...
+ }
+
+ Most people don't need to worry about how this works. For people
+ writing backend modules, class-based pragmas work like this:
+
+ lang->cpp_open_class() // Open a class
+ lang->cpp_pragma() // Supply pragmas
+ ... // Emit members
+
+ lang->cpp_close_class() // Close the class
+
+ All of the pragmas are passed first since they might be used to
+ affect the code generation of other members. Please see
+ the Python module for an example. Patches contributed
+ by Robin Dunn.
+
+8/13/99 : Patch to Python shadow classes to eliminate ignored
+ exception errors in destructors. Patch contributed
+ by Robin Dunn.
+
+8/11/99 : Minor patch to swig_lib/python/swigptr.swg (added SWIGSTATIC
+ declaration). Patch contributed by Lyle Johnson.
+
+8/11/99 : Added FIRSTKEY/NEXTKEY methods to Perl5 shadow classes
+ Patch contributed by Dennis Marsa.
+
+8/11/99 : Modified Python module so that NULL pointers are returned
+ and passed as 'None.' Patch contributed by Tal Shalif.
+
+8/10/99 : Fixed missing 'int' specifiers in various places.
+
+8/10/99 : Added Windows makefile for Runtime libraries. Contributed
+ by Bob Techentin.
+
+8/10/99 : Fixed minor problem in Python runtime makefile introduced
+ by keyword arguments.
+
+8/8/99 : Changed $target of perl5(out) typemap from ST(0) to
+ ST(argvi). Patch contributed by Geoffrey Hort.
+
+8/8/99 : Fixed bug in typemap checking related to the ANY keyword
+ in arrays and ignored arguments. Error reported by
+ Geoffrey Hort.
+
+8/8/99 : %enabledoc and %disabledoc directives can now be used
+ inside class/structure definitions. However, no check
+ is made to see if they are balanced (i.e., a %disabledoc
+ directive inside a class does not have to have a matching
+ %enabledoc in the same class).
+
+8/8/99 : Keyword argument handling is now supported in the Python
+ module. For example:
+
+ int foo(char *bar, int spam, double x);
+
+ Can be called from Python as
+
+ foo(x = 3.4, bar="hello", spam=42)
+
+ To enable this feature, run SWIG with the '-keyword' command
+ line option. Mixing keyword and default arguments
+ should work as well. Unnamed arguments are assigned names
+ such as "arg1", "arg2", etc...
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ Functions with duplicate argument names such as
+ bar(int *OUTPUT, int *OUTPUT) will likely cause problematic
+ wrapper code to be generated. To fix this, use different
+ names or use %apply to map typemaps to alternate names.
+
+8/8/99 : Handling of the 'this' pointer has been changed in Python shadow
+ classes. Previously, dereferencing of '.this' occurred in the
+ Python shadow class itself. Now, this step occurs in the C
+ wrappers using the following function:
+
+ SWIG_GetPtrObj(PyObject *, void **ptr, char *type)
+
+ This function can accept either a string containing a pointer
+ or a shadow class instance with a '.this' attribute of
+ appropriate type. This change allows the following:
+
+ 1. The real shadow class instance for an object is
+ passed to the C wrappers where it can be examined/modified
+ by typemaps.
+
+ 2. Handling of default/keyword arguments is now greatly
+ simplified.
+
+ 3. The Python wrapper code is much more simple.
+
+ Plus, it eliminated more than 300 lines of C++ code in the
+ Python module.
+
+ *** CAVEAT : This requires the abstract object interface.
+ It should work with Python 1.4, but probably nothing older
+ than that.
+
+
+8/8/99 : Fixed handling of "const" and pointers in classes. In particular,
+ declarations such as
+
+ class foo {
+ ...
+ const char *msg;
+ const int *iptr;
+ }
+
+ are handled as assignable variables as opposed to constant
+ values (this is the correct behavior in C/C++). Note:
+ declarations such as "char *const msg" are still unsupported.
+ Constants declared at the global level using const are also
+ broken (because I have a number of interfaces that rely upon
+ this behavior).
+
+ *** POTENTIAL INCOMPATIBILITY *** This may break interfaces that
+ mistakenly treat 'const char *' types as constant values.
+
+8/8/99 : Modified the parser to support bit-fields. For example:
+
+ typedef struct {
+ unsigned int is_keyword : 1;
+ unsigned int is_extern : 1;
+ unsigned int is_static : 1;
+ } flags;
+
+ Bit-fields can only be applied to integer types and their
+ are other restrictions. SWIG performs no such type-checking
+ (although the C compiler will catch problems when it tries to
+ compile the wrapper code).
+
+8/8/99 : Removed trailing space of $basetype substitution in typemaps.
+ This is to allow things like this:
+
+ %typemap(python, argout) spam** OUTPUT{
+ ...
+ char* a = "$basetype_p";
+ ...
+ }
+
+ (Patch suggested by Nathan Dunfield).
+
+6/22/99 : Made a very slight tweak to the Perl5 shadow class
+ code that allows typemaps to alter the return type
+ of objects (to support polymorphic types). Patch
+ contributed by Drake Diedrich.
+
+4/8/99 : Fixed null pointer handling bug in Perl module.
+ Patch contributed by Junio Hamano.
+
+3/17/99 : Fixed bug in perl5ptr.swg for ActiveState Perl.
+ Patch contributed by Greg Anderson.
+
+2/27/99 : Eliminated segmentation fault when Swig runs on
+ empty files.
+
+2/27/99 : Added patch to Guile module to eliminate unused
+ variables. Contributed by Mike Simons.
+
+2/27/99 : Fixed problem with %addmethods returning references.
+
+2/27/99 : Fixed Runtime/Makefile. Patch contributed by
+ Mike Romberg.
+
+2/27/99 : Incorporated patches to the type-checker.
+
+2/27/99 : Fixed problem with -exportall switch and shadow classes
+ in Perl5 module. Patch contributed by Dennis Marsa.
+
+2/27/99 : Modified Perl5 module to recognize 'undef' as a NULL char *.
+ Patch contributed by Junio Hamano.
+
+2/27/99 : Fixed the Perl5 module to support the newer versions of
+ ActiveState Perl for Win32.
+
+2/27/99 : Fixed the include order of files specified with the
+ -I option.
+
+2/5/98- : Dave finishes his dissertation, goes job hunting, moves to
+2/5/99 Chicago and generally thrashes about.
+
+Version 1.1 Patch 5 (February 5, 1998)
+======================================
+
+2/4/98 : Fixed a bug in the configure script when different package
+ locations are specified (--with-tclincl, etc...).
+
+2/2/98 : Fixed name-clash bug related to the switch to C macros for accessor
+ functions. The new scheme did not work correctly for objects
+ with members such as 'obj', 'val', etc... Fixed the bug by
+ appending the word 'swig' to macro argument names. Patch
+ contributed by Rudy Albachten.
+
+2/2/98 : Slight fix to the Perl5 module to eliminate warning messages
+ about 'varname used only once : possible typo'. Fix
+ contributed by Rudy Albachten.
+
+1/9/98 : Fixed a bug in the Perl 5 module related to the creation of
+ constants and shadow classes.
+
+1/9/98 : Fixed linking bug with Python 1.5 embed.i library file.
+
+Version 1.1 Patch 4 (January 4, 1998)
+=====================================
+
+1/4/98 : Changed structured of the Examples directory to be more friendly
+ to Borland C++.
+
+1/4/98 : Added the function Makefile.win.bc for compiling the examples
+ under Borland 5.2.
+
+1/4/98 : Slight change to the perl5 module and C++ compilation. The
+ <math.h> library is now included before any Perl headers
+ because Perl the extern "C" linkage of math.h screws alot
+ of things up (especially on Windows).
+
+1/2/98 : Change to the Python module that reduces the number of constants
+ created by C++ classes, inheritance, and shadow classes. This
+ modification may introduce a few slight incompatibilities if
+ you attempt to use the non-shadow class interface with shadow
+ classes enabled. Patch contributed by Mike Romberg.
+
+1/2/98 : Support for Tcl 8.0 namespaces has been added. This *replaces*
+ the original SWIG mechanism that assumed [incr Tcl] namespaces.
+ To use namespaces, simply run SWIG with the following options
+
+ swig -tcl -namespace foo.i
+
+ This places everything in a namespace that matches
+ the module name
+
+ swig -tcl -namespace -prefix bar foo.i
+
+ This places everything in the namespace 'bar'
+
+ The use of namespaces is new in Tcl 8.0. However, the wrapper code
+ generated by SWIG will still work with all versions of Tcl newer
+ than and including Tcl 7.3/Tk3.6 even if the -namespace option is
+ used.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+ This change may break existing applications that relied on the
+ -prefix and -namespace options.
+
+1/2/98 : Added the following constants to the Tcl wrapper code
+
+ SWIG_name - Name of the SWIG module
+ SWIG_prefix - Prefix/namespace appended to command names
+ SWIG_namespace - Name of the namespace
+
+ SWIG library writers can use these to their advantages.
+
+1/2/98 : Fixed a bug in the Tcl8 module related to the creation of
+ pointer constants (the function SWIG_MakePtr was missing from
+ the wrapper code).
+
+1/2/98 : Added the consthash.i library file to the Tcl and Tcl8 modules.
+
+1/1/98 : Changed and cleaned up the Python typemaps.i file. The following
+ significant changes were made :
+
+ 1. The OUTPUT typemap now returns Python tuples instead of
+ lists. Lists can be returned as before by using the
+ L_OUTPUT type. If compatibility with older versions
+ is needed, run SWIG with the -DOUTPUT_LIST option.
+
+ 2. The BOTH typemap has been renamed to INOUT. For backwards
+ compatibility, the "BOTH" method still exists however.
+
+ 3. Output typemaps now generate less code than before.
+
+ Changes to typemaps.i may break existing Python scripts that assume
+ output in the form of a list.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+12/31/97: Fixed long overdue problems with the testing scripts and certain
+ makefiles that required the use of the bash shell. Everything should
+ work properly with the standard Bourne shell (sh) now.
+
+12/31/97: Modified typemaps to allow $basetype as a valid local variable.
+ This allows for all sorts of bizarre hackish typemaps that
+ do cool things. Patch contributed by Dominique Dumont.
+
+12/31/97: Switched accessor functions generated for member data to
+ C preprocessor macros (except in cases involving typemaps
+ or char *).
+
+12/31/97: Fixed a bug related to C++ member data involving references.
+
+12/31/97: Changed accessor functions for C++ member functions to
+ preprocessor macros. This cleans up the wrapper code
+ and results in fewer function definitions.
+
+12/31/97: Changed the default C constructor to use calloc() instead
+ of malloc()
+
+12/30/97: Changed the creation of constants in the Perl5 module.
+ For all practical purposes, they should work in exactly the
+ same way as before except that they now require much less
+ wrapper code. Modules containing large numbers of
+ constants may see greater than a 50% reduction in wrapper
+ code size.
+
+12/30/97: Modified the Python module to be more intelligent about the
+ creation of constants. SWIG no longer generates redundant
+ global variables and the size of the module initialization
+ function should be reduced. (Many thanks to Jim Fulton).
+
+12/29/97: Fixed a bug in C++ code generation related to member functions,
+ default arguments, and references.
+
+12/29/97: Fixed configure script and a few makefiles to support Python 1.5
+
+12/29/97: Added 'embed15.i' library file. This file should be used to
+ statically link versions of Python 1.5. To make it the default,
+ simply copy 'swig_lib/python/embed15.i' to 'swig_lib/python/embed.i'
+
+Version 1.1 Patch 3 (November 24, 1997)
+========================================
+
+11/23/97: Fixed a bug in the Perl5 module with shadow classes and
+ static class functions that return class instances.
+ Note : The fix for this bug requires a slight restructuring of
+ of the .pm files created by SWIG.
+
+11/23/97: Fixed a bug in the Tcl/Tcl8 modules related to variable linking
+ of character arrays. If you declared a global variable 'char foo[10]',
+ the generated wrapper code would either cause a segmentation fault
+ immediately upon loading or weird memory corruption elsewhere.
+ This should now be fixed although character arrays can only be
+ read-only.
+
+11/23/97: Fixed a bug with the %import directive that caused it to
+ fail if files were imported from directories other than
+ the current working directory.
+
+11/23/97: Fixed incorrect diagnostic message in the ASCII documentation
+ module.
+
+11/23/97: Changed the behavior of the -o option when used with shadow
+ classes. If -o was used to specify both the pathname and filename
+ of SWIG's output such as
+
+ swig -o /home/swig/wrapper.c -shadow -perl5 foo.i
+
+ The wrapper code would be placed the file specified with -o,
+ but the .pm file and documentation would be placed in the
+ directory where SWIG was run. Now, these files are placed
+ in the same directory as the file specified with the -o option.
+ This change is also needed for proper operation on the
+ Macintosh.
+
+11/23/97: Added a 'this()' method to Perl5 shadow classes. This can
+ be used to return the normal pointer value from a shadow
+ class that is represented as a tied hash. To use just
+ invoke as a method like this :
+
+ $l = new List; # Create an object
+ $ptr = $l->this(); # Get the normal pointer value
+
+ *** NEW FEATURE ***
+
+11/23/97: Fixed the Tcl 8 pointer.i library file (which was completely
+ broken in 1.1p2).
+
+11/23/97: Modified the Perl5 type-checker to fix a few problems
+ with global variables of pointer types and to allow
+ tied hashes to be used interchangably with normal
+ pointer values.
+
+11/23/97: Modified the typemap mechanism to allow output
+ typemaps of type 'void'. These were ignored previously,
+ but now if you specify,
+
+ %typemap(lang,out) void {
+ ... return a void ...
+ }
+
+ You can change or assign a return value to the function.
+
+11/23/97: Fixed processing of 'bool' datatypes in the Python module.
+
+11/23/97: Fixed minor parsing error with C++ initializers. For example,
+
+ class B : public A {
+ public:
+ B() : A() { ... };
+ ...
+ }
+
+11/23/97: Fixed the Tcl8 module so that C functions that call back into
+ Tcl don't corrupt the return result object (SWIG was gathering
+ the result object too early which leads to problems if subsequent
+ Tcl calls are made).
+
+11/23/97: Fixed a code generation bug in the Python module when two or
+ more output parameters were used as the first arguments of a
+ function. For example :
+
+ %include typemaps.i
+ void foo(double *OUTPUT, double *OUTPUT, double a);
+
+ Previously, doing this resulted in the creation of an
+ extraneous comma in the output, resulting in a C syntax error.
+
+11/22/97: Fixed a bug when template handling that was stripping whitespace
+ around nested templates. For example :
+
+ Foo<Bar<double> >
+
+ was getting munged into Foo<Bar>> which is a syntax error in
+ in the C++ compiler.
+
+11/22/97: Fixed bugs in the Borland C++ makefiles.
+
+11/22/97: Fixed memory corruption bug when processing integer
+ arguments in Tcl8 module.
+
+11/21/97: Fixed a bug in the Runtime/Makefile related to Tcl 8.
+
+11/21/97: Fixed a bug with the %new directive and Perl5 shadow classes.
+ No longer generates a perl syntax error.
+
+11/9/97 : Changed a strncpy() to strcpy() in the pointer type-checker.
+ This results in a substantial performance improvement in
+ type-checking.
+
+10/29/97: Fixed a bug in the code generation of default arguments and
+ user-defined types. For example :
+
+ void foo(Vector a, Vector b = d);
+
+ should now work properly.
+
+Version 1.1 Patch 2 (September 4, 1997)
+=======================================
+
+9/4/97 : Fixed problem with handling of virtual functions that
+ was introduced by some changes in the C++ module.
+
+Version 1.1 Patch 1 (August 27, 1997)
+=====================================
+
+8/26/97 : Fixed compilation and run-time bugs with Tcl 8.0 final.
+
+8/21/97 : Fixed code generation bug with arrays appearing as arguments
+ to C++ member functions. For example :
+
+ class Foo {
+ public:
+ void Bar(int a[20][20]);
+ };
+
+ There is still a bug using arrays with added methods
+ however.
+
+8/20/97 : Fixed a bug with generating the code for added methods
+ involving pass-by-value.
+
+8/19/97 : Modified the typemapper to substitute the '$arg' value
+ when declaring local variables. For example :
+
+ %typemap(in) double * (double temp_$arg) {
+ ... do something ...
+ }
+
+ When applied to a real function such as the following :
+
+ void foo(double *a, double *b, double *result);
+
+ three local variables will be created as follows :
+
+ double temp_a;
+ double temp_b;
+ double temp_result;
+
+ This can be used when writing multiple typemaps that need
+ to access the same local variables.
+
+
+7/27/97 : Fixed a variety of problems with the %apply directive and arrays.
+ The following types of declarations should now work :
+
+ %apply double [ANY] { Real [ANY] };
+ %apply double [4] { double [10] };
+
+ A generic version of apply like this :
+
+ %apply double { Real };
+
+ should now work--even if arrays involving doubles and Reals are
+ used later.
+
+7/27/97 : Changed warning message about "Array X has been converted to Y" to
+ only appear if running SWIG in verbose mode.
+
+7/27/97 : Added the variables $parmname and $basemangle to the typemap
+ generator. $parmname is the name of the parameter used
+ when the typemap was matched. It may be "" if no parameter
+ was used. $basemangle is a mangled version of the base
+ datatype. Sometimes used for array handling.
+
+7/27/97 : Changed the behavior of output arguments with Python shadow classes.
+ Originally, if a function returned an object 'Foo', the shadow class
+ mechanism would create code like this :
+
+ def return_foo():
+ val = FooPtr(shadowc.return_foo())
+ val.this = 1
+ return val
+
+ The problem with this is that typemaps allow a user to redefine
+ the output behavior of a function--as a result, we can no longer
+ make any assumptions about the return type being a pointer or
+ even being a single value for that matter (it could be a list,
+ tuple, etc...). If SWIG detects the use of output typemaps
+ (either "out" or "argout") it returns the result unmodified like
+ this :
+
+ def return_foo():
+ val = shadowc.return_foo()
+ return val
+
+ In this case, it is up to the user to figure out what to do
+ with the return value (including the possibility of converting it
+ into a Python class).
+
+7/26/97 : Fixed a parsing problem with types like 'unsigned long int',
+ 'unsigned short int', etc...
+
+7/24/97 : Minor bug fix to Tcl 8 module to parse enums properly. Also
+ fixed a memory corruption problem in the type-checker.
+ (patch contributed by Henry Rowley.
+
+7/24/97 : Added Python-tuple typemaps contributed by Robin Dunn.
+
+7/24/97 : Incorporated some changes to the Python module in support of
+ Mark Hammond's COM support. I'm not entirely sure they
+ work yet however. Needs documentation and testing.
+
+7/24/97 : Fixed code generation bugs when structures had array members
+ and typemaps were used. For example :
+
+ %typemap(memberin) double [20][20] {
+ ... get a double [20][20] ...
+ }
+ struct Foo {
+ double a[20][20];
+ }
+
+ Originally, this would generate a compiler-type error when
+ the wrapper code was compiled. Now, a helper function like
+ this is generated :
+
+ double *Foo_a_set(Foo *a, double val[20][20]) {
+ ... memberin typemap here ...
+ return (double *) val;
+ }
+
+ When writing typemaps, one can assume that the source variable
+ is an array of the *same* type as the structure member. This
+ may break some codes that managed to work around the array bug.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+7/13/97 : Fixed bug in Perl5 module when using C global variables that
+ are pointers. When used in function calls and other operations,
+ the value of the pointer would be invalid---causing core
+ dumps and other problems. SWIG implements global variables
+ using Perl magic variables. As it turns out, the error
+ was caused by the fact that the pointer-extraction code
+ was somehow bypassing the procedure used to resolve magical
+ variables (hence, leaving the value undefined). To fix
+ the problem, SWIG now explicitly resolves magic before
+ extracting pointer values.
+
+7/12/97 : Eliminated the last remnants of free() and malloc() from
+ the SWIG compiler.
+
+7/12/97 : Fixed parsing problems with typemaps involving arrays and
+ temporary variables of arrays. Also made it possible for
+ SWIG to handle typemaps like this :
+
+ %typemap(in) double [ANY] (double temp[$dim0]) {
+ ... store data in temp[$dim0] ...
+ }
+
+ Not only does this typemap match any double [] array, it
+ creates a local variable with precisely the right dimensions.
+ (ie. $dim0 gets filled in with the real number of dimensions).
+ Of course, off the record, this will be a way to add more
+ functionality to the typemaps.i libraries.
+
+7/9/97 : Fixed some problems with Perl5, static linking, and shadow
+ classes. When statically linking multiple modules together, write
+ a top-level interface file like this when shadow classes are not
+ used :
+
+ %module swig, foo, bar, glob;
+ %include perlmain.i
+
+ When shadow classes are used, the module names have an extra 'c'
+ appended so it should read as :
+
+ %module swig, fooc, barc, globc;
+ %include perlmain.i
+
+ When linking multiple modules, consider using the SWIG runtime
+ library.
+
+7/8/97 : Incorporated fixed versions of the Borland C++ Makefiles.
+
+7/8/97 : First cut at trying to eliminate excessive compiler warnings.
+ As it turns out, alot of warnings go away if you just make
+ declarations like this
+
+ clientData = clientData;
+
+ in the resulting wrapper code. Most compilers should just
+ ignore this code (at least would can hope).
+
+7/8/97 : Fixed bizarre code generation bug with typemaps and C++ classes.
+ In some cases, typemaps containing printf formatting strings such as
+
+ %typemap(memberout) int * {
+ printf("%d",42);
+ }
+
+ Would generate completely bogus code with garbage replacing
+ the '%d'. Caused by one faulty use of printf (wasn't able to find
+ any other occurrences).
+
+7/7/97 : Fixed bug in Python shadow class generation with non-member
+ functions that are returning more than one value.
+
+7/7/97 : Incorporated modifications to make SWIG work with Guile 1.2.
+ Still need to test it out, but it is rumored to work.
+
+7/2/97 : Fixed some bugs related to output arguments and Python shadow
+ classes. If an output argument is detected, SWIG assumes
+ that the result is a list and handles it appropriately.
+ If the normal return type of an function is an object,
+ it will be converted into a shadow class as before, but
+ with the assumption that it is the first element of a
+ list. *** NOTE : This behavior has been subsequently changed ***
+
+6/29/97 : Changed EXPORT to SWIGEXPORT in all of the language modules.
+ Should provide better compatibility with Windows.
+
+6/29/97 : Modified Python shadow classes so that output arguments
+ work correctly (when typemaps are used).
+
+Version 1.1 (June 24, 1997)
+===========================
+
+6/24/97 : Fixed Objective-C constructor bug when working with Perl5
+ shadow classes.
+
+6/23/97 : Fixed some parsing problems with Objective-C. Declarations
+ such as the following should work now :
+
+ - foo : (int) a with: (int) b;
+
+6/22/97 : Added SWIG Runtime library. This library contains
+ the SWIG pointer type-checker and support functions
+ that are normally included in every module. By using
+ the library, it is easier to work with multiple SWIG
+ generated modules.
+
+6/22/97 : Fixed minor bug in Perl5 module related to static linking
+ of multiple modules.
+
+6/22/97 : Fixed some bugs with the %import directive. When used with
+ Perl5 shadow classes, this generates a 'require' statement
+ to load in external modules.
+
+6/22/97 : Added -swiglib option. This prints out the location of the
+ SWIG library and exits. This option is only really useful to
+ configuration tools that are looking for SWIG and its library
+ location (e.g. autoconf, configure, etc...).
+
+6/21/97 : Fixed export bug with Perl5.004 on Windows-NT.
+
+6/20/97 : Minor change to code generation of class/structure members in
+ order to work better with typemaps. Should have no noticable
+ impact on existing SWIG modules.
+
+6/19/97 : Added -t option. This allows SWIG to load a typemap file before
+ processing any declarations. For example :
+
+ swig -t typemaps.i -python example.i
+
+ At most, only one typemap file can be specified in this manner.
+ *** NEW FEATURE ***
+
+6/18/97 : Need a Makefile fast? Type
+
+ swig [-tcl, -perl5, -python] -co Makefile
+
+ and you will get a Makefile specific to that target language.
+ You just need to modify it for your application and you're
+ ready to run.
+
+6/18/97 : Completed the -ci option. This option checks a file into the
+ SWIG library. It should be used in conjunction with a
+ language option. For example :
+
+ swig -tcl -ci foobar.i
+
+ Checks the file foobar.i into the Tcl part of the library.
+ In order to check a file into the general library (accessible
+ to all languages modules), do the following
+
+ swig -ci -o ../foobar.i foobar.i
+
+ (Admittedly this looks a little strange but is unavoidable).
+ The check-in option is primarily designed for SWIG maintenance
+ and library development. The command will fail if the user does
+ not have write permission to the SWIG library. Third party library
+ extensions can easily install themselves by simply providing
+ a shell script that uses 'swig -ci' to install the appropriate
+ library files. It is not necessary to know where the SWIG library
+ is located if you use this mechanism.
+ *** NEW FEATURE ***
+
+6/16/97 : Fixed a bug in shadow class generation when %name() was applied
+ to a class definition. Unfortunately, fixing the bug required
+ a change in the Language C API by adding an extra argument to
+ the Language::cpp_class_decl() function. This may break
+ SWIG C++ extensions.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+6/15/97 : Added a warning message if no module name is specified with the
+ %module directive or -module option.
+
+6/15/97 : Fixed line number bug when reporting errors for undefined
+ base classes.
+
+6/15/97 : Added new %rename directive. This allows the forward declaration
+ of a renaming. For example :
+
+ %rename OldName NewName;
+
+ .... later ...
+ int OldName(int);
+
+ Unlike %name, %rename will rename any occurrence of the old name.
+ This applies to functions, variables, class members and so forth.
+ There is no way to disable %rename once set, but you can change the
+ name by redeclaring it to something else.
+ *** NEW FEATURE ***
+
+6/15/97 : Improved the implementation of the %name directive so that it
+ could be used with conditional compilation :
+
+ #ifdef SWIG
+ %name(NewName)
+ #endif
+ int OldName(int);
+
+6/15/97 : Added support for functions with no return datatype. In this case,
+ SWIG assumes a return type of 'int'.
+
+6/11/97 : Improved error reporting in the parser. It should be a little
+ less sensitive to errors that occur inside class definitions
+ now. Also reports errors for function pointers.
+
+6/11/97 : Made '$' a legal symbol in identifiers. This is to support
+ some Objective-C libraries. Some compilers (such as gcc) may also
+ allow identifiers to contain a $ in C/C++ code as well (this is
+ an obscure feature of C). When '$' appears in identifier, SWIG
+ remaps it to the string '_S_' when creating the scripting language
+ function. Thus a function 'foo$bar' would be called 'foo_S_bar'.
+
+6/11/97 : Fixed bug in Python shadow classes with __repr__ method. If
+ supplied by the user, it was ignored, but now it should work.
+
+6/9/97 : Fixed the Tcl 8.0 module to work with Tcl 8.0b1. SWIG is no
+ longer compatible with *any* alpha release of Tcl 8.0.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+6/7/97 : Put a maximal error count in (currently set to 20). SWIG will bail out
+ if it generates more errors than this (useful for preventing SWIG
+ from printing 4000 syntax errors when it gets confused).
+
+6/7/97 : Fixed segmentation fault when parsing variable length arguments.
+
+6/7/97 : Minor change to Perl5 module. C++ static functions are now
+ put in the same package as their class when using shadow classes.
+
+6/7/97 : Centralized the naming of functions, members, wrappers etc... By
+ centralizing the naming scheme, it should be possible to make
+ some multi-file optimizations. Also, it should be possible to
+ change SWIG's naming scheme (perhaps a new feature to be added
+ later).
+
+6/2/97 : Added 'arginit' typemap. This can be used to assign initial values
+ to function arguments. Doing so makes it somewhat easier to detect
+ improper argument passing when working with other typemaps.
+
+6/2/97 : Fixed code generation bug when read-only variables were inherited
+ into other classes. Under inheritance, the variables would
+ become writable, but this has now been corrected.
+
+5/30/97 : An empty %name() directive is no longer allowed or supported.
+ This directive was originally used to strip the prefix
+ off of a class or structure. Unfortunately, this never really
+ seemed to work right and it complicated the C++ code generator
+ significantly. As far as I can tell no one uses it, so it
+ is now history. *** POTENTIAL INCOMPATIBILITY ***
+
+5/28/97 : Fixed a parsing bug with #define and C++ comments. Declarations
+ such as the following now work properly :
+
+ #define CONST 4 // A Comment
+
+5/28/97 : Made some performance improvements to the SWIG String class.
+ (only affects the SWIG compiler itself).
+
+5/28/97 : Modified the parser to skip template definitions and issue a
+ warning message.
+
+5/28/97 : Preliminary support for parameterized types added (ie. templates).
+ Types such as the following should pass through the SWIG compiler
+
+ void foo(vector<complex> *a, vector<double> *b);
+
+ When used, the entire name 'vector<complex>' becomes the name
+ of the datatype. Due to space limitations in datatype
+ representations, the name should not exceed 96 characters.
+
+ Note : This is only part of what is needed for template support.
+ Template class definitions are not yet supported by SWIG.
+
+ The template notation above may also be used when specifying
+ Objective-C protocol lists.
+ *** NEW FEATURE ***
+
+5/24/97 : First cut at Objective-C support added. As it turns out, almost
+ everything can be handled with only a few minor modifications to
+ the C++ module.
+ *** NEW FEATURE ***
+
+5/23/97 : Fixed repeated definition bug in multiple inheritance handling
+ when multiple base classes share a common base class (ie.
+ the evil diamond).
+
+5/21/97 : Fixed rather embarrassing typo that worked its way into the
+ Tests/Build directory.
+
+5/19/97 : Fixed code generation bug when using native methods and
+ shadow classes with Python and Perl5 modules.
+
+5/19/97 : Modified the %apply directive slightly so that it would work
+ with pointers a little better. For example :
+
+ %apply unsigned long { DWORD };
+
+ Applies *all* typemaps associated with "unsigned long" to
+ "DWORD". This now includes pointers to the two datatypes.
+ For example, a typemap applied to "unsigned long **" would
+ also be applied to any occurrence of "DWORD **" as well.
+
+5/19/97 : Fixed an ownership assignment bug in the Perl5 module when
+ class members were returning new objects belonging to
+ different classes.
+
+5/17/97 : Added a few more typemap variables.
+
+ $name - Name of function/variable/member
+ $basetype - Base datatype (type without pointers)
+ $argnum - Argument number
+
+5/16/97 : Fixed embarrassing underscore error in local variable
+ allocator.
+
+5/16/97 : Fixed namespace clash bug in parameterized typemaps
+ when creating arrays as new local variables.
+
+5/15/97 : Fixed some bugs with inheritance of added methods across
+ multiple files. SWIG now uses names of base classes
+ when generating such functions.
+
+5/14/97 : Finished support for default typemaps. Primarily used
+ internally, they can be used to match the basic
+ built-in datatypes used inside of SWIG. You can
+ specify them in interface files as well like this :
+
+ %typemap(tcl,in) int SWIG_DEFAULT_TYPE {
+ $target = atoi($target);
+ }
+
+ Unlike normal typemaps, this default map will get applied
+ to *all* integer datatypes encountered, including those
+ renamed with typedef, etc...
+
+5/13/97 : Fixed substring bug in type checker.
+
+5/12/97 : Fixed bug in parameterized typemaps when declaring local
+ variables of structures.
+
+Version 1.1 Beta6 (May 9, 1997)
+===============================
+
+5/9/97 : Fixed bizarre NULL pointer handling bug in Perl5 module.
+
+5/8/97 : Fixed mysterious segmentation fault when running SWIG on an
+ empty file.
+
+5/7/97 : The code generator will now replace the special symbol "$cleanup"
+ with the cleanup code specified with the "freearg" typemap.
+ This change needed to properly manage memory and exceptions.
+
+5/5/97 : Added the 'typemaps.i' library file. This contains a
+ variety of common typemaps for input values, pointers,
+ and so on.
+
+5/5/97 : Changed behavior of "argout" typemap in Python module.
+ Old versions automatically turned the result into a
+ Python list. The new version does nothing, leaving the
+ implementation up to the user. This provides more flexibility
+ but may break older codes that rely on typemaps.
+ *** POTENTIAL INCOMPATIBILITY ***
+
+5/5/97 : Fixed bug in Python module related to the interaction of
+ "argout" and "ignore" typemaps.
+
+5/5/97 : Fixed bug in Python module that would generate incorrect code
+ if all function arguments are "ignored".
+
+5/4/97 : Added %apply and %clear directives. These form a higher level
+ interface to the typemap mechanism. In a nutshell, they
+ can be used to change the processing of various datatypes without
+ ever having to write a typemap. See the SWIG documentation
+ for more details. ** NEW FEATURE **
+
+5/4/97 : Added a local variable extension to the typemap handler.
+ For example :
+
+ %typemap(tcl,in) double *(double temp) {
+ temp = atof($source);
+ $target = &temp;
+ }
+
+ In this case, 'temp' is a local variable that exists
+ in the entire wrapper function (not just the typemap
+ code). This mechanism provides better support for
+ certain types of argument handling and also makes it
+ possible to write thread-safe typemaps. Any number
+ local variables can be declared by supplying a comma
+ separated list. Local variables are guaranteed to be
+ unique, even if the same typemap is applied many times
+ in a given function.
+ ** Not currently supported in Perl4 or Guile modules.
+
+5/2/97 : Fixed processing of %ifdef, %endif, %if, etc... (These are
+ SWIG equivalents of the C preprocessor directives that
+ can pass through the C preprocessor without modification).
+
+5/2/97 : Fixed major (but subtle) bug in the run-time type checker
+ related to searching and type-checking for C++ inheritance.
+ To make a long story short, if you had two classes named
+ "Foo" and "FooObject" the type checker would sometimes
+ get confused and be unable to locate "Foo" in an internal
+ table.
+
+5/2/97 : Fixed some bugs in the -co option.
+
+4/24/97 : Pointer library added to the SWIG library.
+
+4/19/97 : Added the %new directive. This is a "hint" that can be used
+ to tell SWIG that a function is returning a new object. For
+ example :
+
+ %new Foo *create_foo();
+
+ This tells SWIG that create_foo() is creating a new object
+ and returning a pointer to it. Many language modules may
+ choose to ignore the hint, but when working with shadow classes,
+ the %new is used to handle proper ownership of objects.
+
+ %new can also be used with dynamically allocated strings.
+ For example :
+
+ %new char *create_string();
+
+ When used, all of the language modules will automatically cleanup
+ the returned string--eliminating memory leaks.
+ ** NEW FEATURE **
+
+4/19/97 : Added a new typemap "newfree". This is used in conjunction with
+ the %new directive and can be used to change the method by which
+ a new object returned by a function is deleted.
+
+4/19/97 : The symbol "__cplusplus" is now defined in the SWIG interpreter
+ when running with the -c++ option.
+
+4/17/97 : Added support for static member functions when used inside the
+ %addmethods directive.
+
+4/15/97 : Added a special typemap symbol PREVIOUS that can be used to
+ restore a previous typemap. For example :
+
+ %typemap(tcl,in) int * = PREVIOUS;
+
+ This is primarily used in library files.
+
+4/13/97 : Added %pragma directive for Perl5 module. Two new pragmas are
+ available :
+
+ %pragma(perl5) code = "string"
+ %pragma(perl5) include = "file.pl"
+
+ Both insert code into the .pm file created by SWIG. This can
+ be used to automatically customize the .pm file created by SWIG.
+
+4/13/97 : Scanner modified to only recognize C++ keywords when the -c++
+ option has been specified. This provides support for C programs
+ that make use of these keywords for identifiers.
+ SWIG may need to be explicitly run with the -c++ option when
+ compiling C++ code (this was allowed, but not recommended in
+ previous versions). **POTENTIAL INCOMPATIBILITY**
+
+4/11/97 : Fixed a rather nasty bug in the Perl5 module related to using
+ variable linking with complex datatypes and pointers. On Unix,
+ code would work (somehow), but would cause an access violation
+ under Windows-NT. The fix should correct the problem,
+ but there may still be a problem using global variables of
+ complex datatypes in conjunction with shadow classes. Fortunately,
+ this sort of thing seems to be relatively rare (considering
+ that the bug has been around for more than a year - yikes!).
+
+4/11/97 : Fixed bizarre constant evaluation bug in Perl5 code generation
+ when running under Windows-NT.
+
+4/8/97 : Bug when using default arguments and C++ references fixed.
+
+4/8/97 : Fixed code generation bugs in Python and Perl5 modules related to
+ using class renaming (applying the %name directive to a class
+ definition) and shadow classes.
+
+4/7/97 : Fixed minor bugs in swigptr.swg, tcl8ptr.swg, and perl5ptr.swg to
+ prevent infinite loops when weird datatypes are passed.
+
+3/29/97 : 'Makefile.win' added. This is used to build most of the examples
+ in the Examples directory under Windows NT/95.
+
+3/27/97 : Fixes to SWIG's error return codes. SWIG now returns non-zero
+ exit codes for certain kinds of errors (which makes it more
+ friendly to makefiles). An overhaul of the error handling
+ is on the to-do list and will probably show up in a later release.
+
+3/25/97 : Bug fix. "freearg" and "argout" typemaps have been fixed in
+ the Perl5 module. In previous versions, function input parameters
+ and function output parameters shared the same memory space--causing
+ all sorts of nasty problems when trying to pass perl values by
+ reference. SWIG now internally makes a "copy" (which is really
+ just a pointer) of affected parameters and uses that. This
+ is done transparently so there is no noticable impact on any
+ SWIG generated modules. This change is probably only noticable
+ to expert users.
+
+3/25/97 : Added type-check to verbose and stat mode. SWIG will now generate a list
+ of all datatypes that were used but undefined (useful for tracking
+ down weird bugs). This is enabled with the -v option (which
+ is now officially known as "overly verbose" mode) or the -stat option.
+
+3/25/97 : Slight change to the parser to make include guards work correctly.
+ For example :
+
+ #ifndef INTERFACE_I
+ #define INTERFACE_I
+ %module foobar.i
+ ... declarations ...
+ #endif
+
+3/24/97 : %checkout directive added. This allows an interface file to
+ extract files from the SWIG library and place them in the
+ current directory. This can be used to extract scripts and
+ other helper code that might be associated with library files.
+ For example :
+
+ %checkout array.tcl
+
+ Will look for a file "array.tcl" in the library and copy it
+ to the current directory. If the file already exists in the
+ directory, this directive does nothing (it will not overwrite an
+ existing file). This only an experimental feature for now.
+
+3/24/97 : SWIG will now look in the SWIG Library for a file if it can't
+ find it in the current directory. As a result, it is easy to
+ make modules from SWIG library files. For example, if you
+ want to make a Python module from the SWIG timers library, just
+ type this in any directory :
+
+ swig -python timers.i
+
+ You will get the files timers_wrap.c and timers_wrap.doc in
+ the current directory that you can now compile. The file
+ remains in the SWIG library (although you can check it out
+ using the -co option). *** New Feature ***
+
+3/24/97 : -co option added to SWIG to allow easy access to the SWIG library.
+ When used, this instructs SWIG to check out a library file and
+ place it in the current directory. For example :
+
+ unix > swig -co array.i
+ array.i checked out from the SWIG library
+ unix >
+
+ Once in your directory you can customize the file to suit your
+ particular purposes. The checkout option makes it easy to
+ grab library files without knowing anything about the SWIG
+ installation, but it also makes it possible to start
+ including scripts, C code, and other miscellaneous files
+ in the library. For example, you could put a cool script
+ in the library and check it out whenever you wanted to use it.
+ *** New Feature ***
+
+3/24/97 : #pragma export directives added to Tcl output for compiling
+ shared libraries on the Mac.
+
+3/24/97 : Minor changes to wish.i and tclsh.i library files to provide
+ support for the Macintosh.
+
+3/19/97 : SWIG's policy towards NULL pointers has been relaxed. The
+ policy of requiring a special compiler directive -DALLOW_NULL
+ to use NULL pointers is no longer supported. While this may
+ seem "unsafe", it turns out that you can use a "check"
+ typemap to achieve some safety. For example :
+
+ %typemap(perl5,check) Node * {
+ if (!$target)
+ croak("NULL Pointers not allowed.");
+ }
+
+ This prevents any NULL value of a "Node *" pointer to be
+ passed to a function. (I think this is much cleaner
+ than the old -DALLOW_NULL hack anyways).
+
+3/19/97 : Fixed pointer handling errors in Perl5 module. Modules no
+ longer core dump when a Perl reference is inadvertently
+ passed in as a C pointer.
+
+3/18/97 : Added a "check" typemap. This can be used to check the
+ validity of function input values. For example :
+
+ %typemap(perl5,check) int posint {
+ if ($target < 0)
+ croak("Argument is not a positive integer");
+ }
+
+3/18/97 : Added an $arg variable to Tcl typemaps. This makes it easier
+ to return argument values by "reference".
+
+3/18/97 : Fixed a code generation bug when using C++ references and
+ the %addmethods directive.
+
+3/18/97 : Fixed a few glitches in the typemap module with respect to
+ chaining. For example :
+
+ %typemap(tcl,in) int {
+ $in // Inserts prexisting typemap
+ printf("Received a %d\n", $target);
+ }
+
+ This has been allowed for quite some time, but didn't work
+ if no existing typemap was defined. Now, it still doesn't
+ work if no existing typemap is defined, but it issues a
+ warning message. There is some support using default typemaps,
+ but none of the language modules take advantage of it. This
+ should be considered experimental at this time.
+
+Version 1.1b5 Patch 1 (March 16, 1997)
+======================================
+
+3/16/97 : Fixed references bug with C++ code generation.
+
+3/16/97 : Fixed initialization bug in the documentation system that
+ was causing weird problems.
+
+3/16/97 : Fixed fatal bug with -c option in the Python module.
+
+3/13/97 : Fixed bug in the documentation system involving the %text directive
+ and sorting. In the old system, %text entries would float to the
+ top of a section because they were "nameless". Now they are
+ attached to the previous declaration and will stay in the proper
+ location relative to the previous entry.
+
+Version 1.1b5 (March 12, 1997)
+==============================
+
+3/11/97 : Fixed compilation problems introduced by Tcl/Tk 8.0a2.
+ *** INCOMPATIBILITY *** SWIG no longer works with Tcl/Tk 8.0a1.
+
+3/10/97 : Fixed bug with ignored arguments and C++ member functions in
+ the Python module.
+
+3/9/97 : Parsing bugs with nested class definitions and privately
+ declared nested class definitions fixed.
+
+3/9/97 : Fixed a few minor code generation bugs with C++ classes and
+ constructors. In some cases, the resulting wrapper code
+ would not compile properly. SWIG now attempts to use
+ the default copy constructor instead.
+
+3/8/97 : Added a -l option to SWIG that allows additional SWIG library files
+ to be grabbed without having them specified in the interface file.
+ This makes it easier to keep the interface file clean and move certain
+ options into a Makefile. For example :
+
+ swig -tcl example.i # Build a normal Tcl extension
+ swig -tcl -lwish.i example.i # Build it as a wish extension
+ # by including the 'wish.i' file.
+
+ swig -python example.i # Build a dynamically loaded extension
+ swig -python -lembed.i example.i # Build a static extension
+
+ These kinds of options could previously be accomplished with
+ conditional compilation such as :
+
+ %module example
+ ...
+ #ifdef STATIC
+ %include embed.i
+ #endif
+
+3/8/97 : Incorporated changes to Guile module to use the new gh interface
+ in FSF Guile 1.0. The older gscm interface used in Cygnus
+ Guile releases is no longer supported by SWIG.
+
+3/8/97 : Cleaned up the Tcl Netscape plugin example. It should work with
+ version 1.1 of the plugin now.
+
+3/8/97 : Added better array support to the typemap module. The keyword
+ ANY can now be used to match any array dimension. For example :
+
+ %typemap(tcl,in) double [ANY] {
+ ... get an array ...
+ }
+
+ This will match any single-dimensional double array. The array
+ dimension is passed in the variables $dim0, $dim1, ... $dim9. For
+ example :
+
+ %typemap(tcl,in) double [ANY][ANY][ANY] {
+ printf("Received a double[%d][%d][%d]\n",$dim0,$dim1,$dim2);
+ }
+
+ Any typemap involving a specific array dimension will override any
+ specified with the ANY tag. Thus, a %typemap(tcl,in) double [5][4][ANY] {}
+ would override a double [ANY][ANY][ANY]. However, overuse of the ANY
+ tag in arrays of high-dimensions may not work as you expect due to
+ the pattern matching rule used. For example, which of the following
+ typemaps has precedence?
+
+ %typemap(in) double [ANY][5] {} // Avoid this!
+ %typemap(in) double [5][ANY] {}
+
+3/7/97 : Fixed a number of bugs related to multi-dimensional array handling.
+ Typedefs involving multi-dimensional arrays now works correctly.
+ For example :
+
+ typedef double MATRIX[4][4];
+
+ ...
+ extern double foo(MATRIX a);
+
+ Typecasting of pointers into multi-dimensional arrays is now
+ implemented properly when making C/C++ function calls.
+
+3/6/97 : Fixed potentially dangerous bug in the Tcl Object-oriented
+ interface. Well, actually, didn't fix it but issued a
+ Tcl error instead. The bug would manifest itself as follows:
+
+ % set l [List] # Create an object
+ ...
+ % set m [List -this $l] # Make $m into an object assuming $l
+ # contains a pointer.
+ # Since $m == $l, $l gets destroyed
+ # (since its the same command name)
+ % $m insert Foo
+ Segmentation fault # Note : the list no longer exists!
+
+ Now, an error will be generated instead of redefining the command.
+ As in :
+
+ % set l [List]
+ ...
+ % set m [List -this $l]
+ Object name already exists!
+
+ Use catch{} to ignore the error.
+
+3/3/97 : Better support for enums added. Datatypes of 'enum MyEnum'
+ and typedefs such as 'typedef enum MyEnum Foo;' now work.
+
+3/3/97 : Parser modified to ignore constructor initializers such as :
+
+ class Foo : public Bar {
+ int a,b;
+ public:
+ Foo(int i) : a(0), b(i), Bar(i,0) { };
+ };
+
+3/3/97 : Modified parser to ignore C++ exception specifications such as :
+
+ int foo(double) throw(X,Y);
+
+3/3/97 : Added %import directive. This works exactly like %extern
+ except it tells the language module that the declarations are
+ coming from a separate module. This is usually only
+ needed when working with shadow classes.
+
+3/2/97 : Changed pointer type-checker to be significantly more
+ efficient when working with derived datatypes. This
+ has been accomplished by storing type-mappings in sorted
+ order, using binary search schemes, and caching recently
+ used datatypes. For SWIG generated C++ modules that
+ make a large number of C function calls with derived types,
+ this could result in speedups of between 100 and 50000 percent.
+ However, due to the required sorting operation, module
+ loading time may increased slightly when there are lots of
+ datatypes.
+
+3/2/97 : Fixed some C++ compilation problems with Python
+ embed.i library files.
+
+2/27/97 : Slight change to C++ code generation to use copy constructors
+ when returning complex data type by value.
+
+2/26/97 : Fixed bug in Python module with -c option.
+
+2/26/97 : Slight tweak of parser to allow trailing comma in enumerations
+ such as
+
+ enum Value (ALE, STOUT, LAGER, };
+
+2/25/97 : Fixed code generation bug in Tcl module when using the
+ %name() directive on a classname.
+
+2/25/97 : Finished code-size optimization of C++ code generation with
+ inheritance of attributes. Inherited attributes now
+ only generate one set of wrapper functions that are re-used
+ in any derived classes. This could provide big code
+ size improvements in some scripting language interfaces.
+
+2/25/97 : Perl5 module modified to support both the Unix and Windows
+ versions. The windows version has been tested with the
+ Activeware port of Perl 5.003 running under Windows 95.
+ The C source generated by SWIG should compile without
+ modification under both versions of Perl, but is now
+ even more hideous than before.
+
+2/25/97 : Modified parser to allow scope resolution operation to
+ appear in expressions and default arguments as in :
+
+ void foo(int a = Bar::defvalue);
+
+2/25/97 : Fixed bug when resolving symbols inside C++ classes.
+ For example :
+
+ class Foo {
+ public:
+ enum Value {ALE, STOUT, LAGER};
+ ...
+ void defarg(Value v = STOUT);
+
+ };
+
+2/24/97 : Fixed bug with member functions returning void *.
+
+2/23/97 : Modified Python module to be better behaved under Windows
+
+ - Module initialization function is now properly exported.
+ It should not be necessary to explicitly export this function
+ yourself.
+
+ - Bizarre compilation problems when compiling the SWIG wrapper
+ code as ANSI C under Visual C++ 4.x fixed.
+
+ - Tested with both the stock Python-1.4 distribution and Pythonwin
+ running under Win95.
+
+2/19/97 : Fixed typedef handling bug in Perl5 shadow classes.
+
+2/19/97 : Added exception support. To use it, do the following :
+
+ %except(lang) {
+ ... try part of the exception ...
+ $function
+ ... catch part of exception ...
+ }
+
+ $function is a SWIG variable that will be replaced by the
+ actual C/C++ function call in a wrapper function. Thus,
+ a real exception specification might look like this :
+
+ %except(perl5) {
+ try {
+ $function
+ } catch (char *& sz) {
+ ... process an exception ...
+ } catch(...) {
+ croak("Unknown exception. Bailing out...");
+ }
+ }
+
+2/19/97 : Added support for managing generic code fragments (needed
+ for exceptions).
+
+2/19/97 : Fixed some really obscure typemap scoping bugs in the C++
+ handler.
+
+2/18/97 : Cleaned up perlmain.i file by removing some problematic,
+ but seemingly unnecessary declarations.
+
+2/18/97 : Optimized handling of member functions under inheritance.
+ SWIG can now use wrapper functions generated for a
+ base class instead of regenerating wrappers for
+ the same functions in a derived class. This could
+ make a drastic reduction in wrapper code size for C++
+ applications with deep inheritance hierarchies and
+ lots of functions.
+
+2/18/97 : Additional methods specified with %addmethods can now
+ be inherited along with normal C++ member functions.
+
+2/18/97 : Minor internal fixes to make SWIG's string handling a little
+ safer.
+
+2/16/97 : Moved some code generation of Tcl shadow classes to
+ library files.
+
+2/16/97 : Fixed documentation error of '-configure' method in
+ Tcl modules.
+
+2/16/97 : Modified Perl5 module slightly to allow typemaps
+ to use Perl references.
+
+2/12/97 : Fixed argument checking bug that was introduced by
+ default arguments (function calls with too many
+ arguments would still be executed). Functions now
+ must have the same number of arguments as C version
+ (with possibility of default/optional arguments
+ still supported).
+
+2/12/97 : Fixed default argument bug in Perl5 module when
+ generating wrapper functions involving default
+ arguments of complex datatypes.
+
+2/12/97 : Fixed typemap scoping problems. For example :
+
+ %typemap(tcl,in) double {
+ .. get a double ..
+ }
+
+ class Foo {
+ public:
+ double bar(double);
+ }
+
+ %typemap(tcl,in) double {
+ .. new get double ..
+ }
+
+ Would apply the second typemap to all functions in Foo
+ due to delayed generation of C++ wrapper code (clearly this
+ is not the desired effect). Problem has been fixed by
+ assigning unique numerical identifiers to every datatype in
+ an interface file and recording the "range of effect" of each
+ typemap.
+
+2/11/97 : Added support for "ignore" and "default" typemaps. Only use
+ if you absolutely know what you're doing.
+
+2/9/97 : Added automatic creation of constructors and destructors for
+ C structs and C++ classes that do not specify any sort of
+ constructor or destructor. This feature can be enabled by
+ running SWIG with the '-make_default' option or by inserting
+ the following pragma into an interface file :
+
+ %pragma make_default
+
+ The following pragma disables automatic constructor generation
+
+ %pragma no_default
+
+2/9/97 : Added -make_default option for producing default constructors
+ and destructors for classes without them.
+
+2/9/97 : Changed the syntax of the SWIG %pragma directive to
+ %pragma option=value or %pragma(lang) option=value.
+ This change makes the syntax a little more consistent
+ between general pragmas and language-specific pragmas.
+ The old syntax still works, but will probably be phased
+ out (a warning message is currently printed).
+
+2/9/97 : Improved Tcl support of global variables that are of
+ structures, classes, and unions.
+
+2/9/97 : Fixed C++ compilation problem in Python 'embed.i' library file.
+
+2/9/97 : Fixed missing return value in perlmain.i library file.
+
+2/9/97 : Fixed Python shadow classes to return an AttributeError when
+ undefined attributes are accessed (older versions returned
+ a NameError).
+
+2/9/97 : Fixed bug when %addmethods is used after a class definition whose
+ last section is protected or private.
+
+2/8/97 : Made slight changes in include file processing to support
+ the Macintosh.
+
+2/8/97 : Extended swigmain.cxx to provide a rudimentary Macintosh interface.
+ It's a really bad interface, but works until something better
+ is written.
+
+1/29/97 : Fixed type-casting bug introduced by 1.1b4 when setting/getting the
+ value of global variables involving complex data types.
+
+1/29/97 : Removed erroneous white space before an #endif in the code generated
+ by the Python module (was causing errors on DEC Alpha compilers).
+
+1/26/97 : Fixed errors when using default/optional arguments in Python shadow
+ shadow classes.
+
+1/23/97 : Fixed bug with nested %extern declarations.
+
+1/21/97 : Fixed problem with typedef involving const datatypes.
+
+1/21/97 : Somewhat obscure, but serious bug with having multiple levels
+ of typedefs fixed. For example :
+
+ typedef char *String;
+ typedef String Name;
+
+Version 1.1 Beta4 (January 16, 1997)
+====================================
+
+Note : SWIG 1.1b3 crashed and burned shortly after take off due
+to a few major run-time problems that surfaced after release.
+This release should fix most, if not all, of those problems.
+
+1/16/97 : Fixed major memory management bug on Linux
+
+1/14/97 : Fixed bug in functions returning constant C++ references.
+
+1/14/97 : Modified C++ module to handle datatypes better.
+
+1/14/97 : Modified parser to allow a *single* scope resolution
+ operator in datatypes. Ie : Foo::bar. SWIG doesn't
+ yet handle nested classes, so this should be
+ sufficient for now.
+
+1/14/97 : Modified parser to allow typedef inside a C++ class.
+
+1/14/97 : Fixed some problems related to datatypes defined inside
+ a C++ class. SWIG was not generating correct code,
+ but a new scoping mechanism and method for handling
+ datatypes inside a C++ class have been added.
+
+1/14/97 : Changed enumerations to use the value name instead
+ of any values that might have appeared in the interface
+ file. This makes the code a little more friendly to
+ C++ compilers.
+
+1/14/97 : Removed typedef bug that made all enumerations
+ equivalent to each other in the type checker (since
+ it generated alot of unnecessary code).
+
+Version 1.1 Beta3 (January 9, 1997)
+===================================
+
+Note : A *huge* number of changes related to ongoing modifications.
+
+1. Support for C++ multiple inheritance added.
+
+2. Typemaps added.
+
+3. Some support for nested structure definitions added.
+
+4. Default argument handling added.
+
+5. -c option added for building bare wrapper code modules.
+
+6. Rewrote Pointer type-checking to support multiple inheritance
+ correctly.
+
+7. Tcl 8.0 module added.
+
+8. Perl4 and Guile modules resurrected from the dead (well, they
+ at least work again).
+
+9. New Object Oriented Tcl interface added.
+
+10. Bug fixes to Perl5 shadow classes.
+
+11. Cleaned up many of the internal modules of the parser.
+
+12. Tons of examples and testing modules added.
+
+13. Fixed bugs related to use of "const" return values.
+
+14. Fixed bug with C++ member functions returning void *.
+
+15. Changed SWIG configuration script.
+
+Version 1.1 Beta2 (December 3, 1996)
+====================================
+
+1. Completely rewrote the SWIG documentation system. The changes
+ involved are too numerous to mention. Basically, take everything
+ you knew about the old system, throw them out, and read the
+ file Doc/doc.ps.
+
+2. Limited support for #if defined() added.
+
+3. Type casts are now allowed in constant expressions. ie
+
+ #define A (int) 3
+
+4. Added support for typedef lists. For example :
+
+ typedef struct {
+ double x,y,z;
+ } Vector, *VectorPtr;
+
+5. New SWIG directives (related to documentation system)
+
+ %style
+ %localstyle
+ %subsection
+ %subsubsection
+
+6. Reorganized the C++ handling and made it a little easier to
+ work with internally.
+
+7. Fixed problem with inheriting data members in Python
+ shadow classes.
+
+8. Fixed symbol table problems with shadow classes in both
+ Python and Perl.
+
+9. Fixed annoying segmentation fault bug in wrapper code
+ generated for Perl5.
+
+10. Fixed bug with %addmethods directive. Now it can be placed
+ anywhere in a class.
+
+11. More test cases added to the SWIG self-test. Documentation
+ tests are now performed along with other things.
+
+12. Reorganized the SWIG library a little bit and set it up to
+ self-document itself using SWIG.
+
+13. Lots and lots of minor bug fixes (mostly obscure, but bugs
+ nonetheless).
+
+
+Version 1.1 Beta1 (October 30, 1996)
+====================================
+
+1. Added new %extern directive for handling multiple files
+
+2. Perl5 shadow classes added
+
+3. Rewrote conditional compilation to work better
+
+4. Added 'bool' datatype
+
+5. %{,%} block is now optional.
+
+6. Fixed some bugs in the Python shadow class module
+
+7. Rewrote all of the SWIG tests to be more informative
+ (and less scary).
+
+8. Rewrote parameter list handling to be more memory
+ efficient and flexible.
+
+9. Changed parser to ignore 'static' declarations.
+
+10. Initializers are now ignored. For example :
+
+ struct FooBar a = {3,4,5};
+
+11. Somewhat better parsing of arrays (although it's
+ usually just a better error message now).
+
+12. Lot's of minor bug fixes.
+
+
+Version 1.0 Final (August 31, 1996)
+===================================
+
+1. Fixed minor bug in C++ module
+
+2. Fixed minor bug in pointer type-checker when using
+ -DALLOW_NULL.
+
+3. Fixed configure script to work with Python 1.4beta3
+
+4. Changed configure script to allow compilation without
+ yacc or bison.
+
+Version 1.0 Final (August 28, 1996)
+===================================
+
+1. Changed parser to support more C/C++ datatypes (well,
+ more variants). Types like "unsigned", "short int",
+ "long int", etc... now work.
+
+2. "unions" added to parser.
+
+3. Use of "typedef" as in :
+
+ typedef struct {
+ double x,y,z;
+ } Vector;
+
+ Now works correctly. The name of the typedef is used as
+ the structure name.
+
+4. Conditional compilation with #ifdef, #else, #endif, etc...
+ added.
+
+5. New %disabledoc, %enabledoc directives allow documentation
+ to selectively be disabled for certain parts of a wrapper
+ file.
+
+6. New Python module supports better variable linking, constants,
+ and shadow classes.
+
+7. Perl5 module improved with better compatibility with XS
+ and xsubpp. SWIG pointers and now created so that they
+ are compatible with xsubpp pointers.
+
+8. Support for [incr Tcl] namespaces added to Tcl module.
+
+9. %pragma directive added.
+
+10. %addmethods directive added.
+
+11. %native directive added to allow pre-existing wrapper functions
+ to be used.
+
+12. Wrote configure script for SWIG installation.
+
+13. Function pointers now allowed with typedef statements.
+
+14. %typedef modified to insert a corresponding C typedef into
+ the output file.
+
+15. Fixed some problems related to C++ references.
+
+16. New String and WrapperFunction classes add to make generating
+ wrapper code easier.
+
+17. Fixed command line option processing to eliminate core dumps
+ and to allow help messages.
+
+18. Lot's of minor bug fixes to almost all code modules
+
+
+Version 1.0 Beta 3 (Patch 1) July 17, 1996
+==========================================
+
+1.0 Final is not quite ready yet, but this release fixes a
+number of immediate problems :
+
+1. Compiler errors when using -strict 1 type checking have been fixed.
+
+2. Pointer type checker now recognizes pointers of the form
+ _0_Type correctly.
+
+3. A few minor fixes were made in the Makefile
+
+Version 1.0 Beta 3 (June 14, 1996)
+==================================
+
+
+There are lots of changes in this release :
+
+1. SWIG is now invoked using the "swig" command instead of "wrap".
+ Hey, swig sounds cooler.
+
+2. The SWIG_LIB environment variable can be set to change the
+ location where SWIG looks for library files.
+
+3. C++ support has been added. You should use the -c++ option
+ to enable it.
+
+4. The %init directive has been replaced by the %module directive.
+ %module constructs a valid name for the initialization function
+ for whatever target language you're using (actually this makes
+ SWIG files a little cleaner). The old %init directive still works.
+
+5. The syntax of the %name directive has been changed. Use of the
+ old one should generate a warning message, but may still work.
+
+6. To support Tcl/Tk on non-unix platforms, SWIG imports a file called
+ swigtcl.cfg from the $(SWIG_LIB)/tcl directory. I don't have access
+ to an NT machine, but this file is supposedly allows SWIG to
+ produce wrapper code that compiles on both UNIX and non UNIX machines.
+ If this doesn't work, you'll have to edit the file swigtcl.cfg. Please
+ let me know if this doesn't work so I can update the file as
+ necessary.
+
+7. The SWIG run-time typechecker has been improved. You can also
+ now redefine how it works by supplying a file called "swigptr.cfg"
+ in the same directory as your SWIG interface files. By default,
+ SWIG reads this file from $(SWIG_LIB)/config.
+
+8. The documentation system has been changed to support the following :
+
+ - Documentation order is printed in interface file order by
+ default. This can be overridden by putting an %alpha
+ directive in the beginning of the interface file.
+
+ - You can supply additional documentation text using
+
+ %text %{ put your text here %}
+
+ - A few minor bugs were fixed.
+
+9. A few improvements have been made to the handling of command line
+ options (but it's still not finished).
+
+10. Lots of minor bug fixes in most of the language modules have been
+ made.
+
+11. Filenames have been changed to 8.3 for compatibility with a SWIG
+ port to non-unix platforms (work in progress).
+
+12. C++ file suffix is now .cxx (for same reason).
+
+13. The documentation has been upgraded significantly and is now
+ around 100 pages. I added new examples and a section on
+ C++. The documentation now includes a Table of Contents.
+
+14. The SWIG Examples directory is still woefully sparse, but is
+ getting better.
+
+Special notice about C++
+------------------------
+This is the first version of SWIG to support C++ parsing. Currently
+the C++ is far from complete, but seems to work for simple cases.
+No work has been done to add special C++ processing to any of
+the target languages. See the user manual for details about how
+C++ is handled. If you find problems with the C++ implementation,
+please let me know. Expect major improvements in this area.
+
+Note : I have only successfully used SWIG and C++ with Tcl and
+Python.
+
+Notice about Version 1.0Final
+-----------------------------
+
+Version 1.0B3 is the last Beta release before version 1.0 Final is
+released. I have frozen the list of features supported in version 1.0
+and will only fix bugs as they show up. Work on SWIG version 2.0 is
+already in progress, but is going to result in rather significant
+changes to SWIG's internal structure (hopefully for the better). No
+anticipated date for version 2.0 is set, but if you've got an idea,
+let me know.
+
+Version 1.0 Beta 2 (April 26, 1996)
+===================================
+
+This release is identical to Beta1 except a few minor bugs are
+fixed and the SWIG library has been updated to work with Tcl 7.5/Tk 4.1.
+A tcl7.5 examples directory is now included.
+
+- Fixed a bug in the Makefile that didn't install the libraries
+ correctly.
+
+- SWIG Library files are now updated to work with Tcl 7.5 and Tk 4.1.
+
+- Minor bug fixes in other modules.
+
+
+Version 1.0 Beta 1 (April 10, 1996).
+=====================================
+
+This is the first "semi-official" release of SWIG. It has a
+number of substantial improvements over the Alpha release. These
+notes are in no particular order--hope I remembered everything....
+
+1. Tcl/Tk
+
+SWIG is known to work with Tcl7.3, Tk3.6 and later versions.
+I've also tested SWIG with expect-5.19.
+
+Normally SWIG expects to use the header files "tcl.h" and "tk.h".
+Newer versions of Tcl/Tk use version numbers. You can specify these
+in SWIG as follows :
+
+ % wrap -htcl tcl7.4.h -htk tk4.0.h example.i
+
+Of course, I prefer to simply set up symbolic links between "tcl.h" and
+the most recent stable version on the machine.
+
+2. Perl4
+
+This implementation has been based on Perl-4.035. SWIG's interface to
+Perl4 is based on the documentation provided in the "Programming Perl"
+book by Larry Wall, and files located in the "usub" directory of the
+Perl4 distribution.
+
+In order to compile with Perl4, you'll need to link with the uperl.o
+file found in the Perl4 source directory. You may want to move this
+file to a more convenient location.
+
+3. Perl5
+
+This is a somewhat experimental implementation, but is alot less
+buggy than the alpha release. SWIG operates independently of
+the XS language and xsubpp supplied with Perl5. Currently SWIG
+produces the necessary C code and .pm file needed to dynamically
+load a module into Perl5.
+
+To support Perl5's notion of modules and packages (as with xsubpp),
+you can use the following command line options :
+
+ % wrap -perl5 -module MyModule -package MyPackage example.i
+
+Note : In order for dynamic loading to be effective, you need to be
+careful about naming. For a module named "MyModule", you'll need to
+create a shared object file called "MyModule.so" using something like
+
+ % ld -shared my_obj.o -o MyModule.so
+
+The use of the %init directive must match the module name since Perl5
+calls a function "boot_ModuleName" in order to initialize things.
+See the Examples directory for some examples of how to get things
+to work.
+
+4. Python1.3
+
+This is the first release supporting Python. The Python port is
+experimental and may be rewritten. Variable linkage is done through
+functions which is sort of a kludge. I also think it would be nice
+to import SWIG pointers into Python as a new object (instead of strings).
+Of course, this needs a little more work.
+
+5. Guile3
+
+If you really want to live on the edge, pick up a copy of Guile-iii and
+play around with this. This is highly experimental---especially since
+I'm not sure what the official state of Guile is these days. This
+implementation may change at any time should I suddenly figure out better
+ways to do things.
+
+6. Extending SWIG
+
+SWIG is written in C++ although I tend to think of the code as mostly
+being ANSI C with a little inheritance thrown in. Each target language
+is implemented as a C++ class that can be plugged into the system.
+If you want to add your own modifications, see Appendix C of the user
+manual. Then take a look at the "user" directory which contains some
+code for building your own extenions.
+
+7. The SWIG library
+
+The SWIG library is still incomplete. Some of the files mentioned in
+the user manual are unavailable. These files will be made available
+when they are ready. Subscribe to the SWIG mailing list for announcements
+and updates.
+
+8. SWIG Documentation
+
+I have sometimes experienced problems viewing the SWIG documentation in
+some postscript viewers. However, the documentation seems to print
+normally. I'm working on making much of the documentation online,
+but this takes time.
+
+Version 0.1 Alpha (February 9, 1996)
+====================================
+
+1. Run-time type-checking of SWIG pointers. Pointers are now represented
+ as strings with both numeric and encoded type information. This makes
+ it a little harder to shoot yourself in the foot (and it eliminates
+ some segmentation faults and other oddities).
+
+2. Python 1.3 now supported.
+
+3. #define and enum can be used to install constants.
+
+4. Completely rewrote the %include directive and made it alot more powerful.
+
+5. Restructured the SWIG library to make it work better.
+
+6. Various bug fixes to Tcl, Perl4, Perl5, and Guile implementations.
+
+7. Better implementation of %typedef directive.
+
+8. Made some changes to SWIG's class structure to make it easier to expand.
+ SWIG is now built into a library file that you can use to make your
+ own extenions.
+
+9. Made extensive changes to the documentation.
+
+10. Minor changes to the SWIG parser to make it use less memory.
+ Also took out some extraneous rules that were undocumented and
+ didn't work in the first place.
+
+11. The SWIG library files "tclsh", "wish", "expect", etc... in the first
+ release have been restructured and renamed to "tclsh.i", "wish.i",
+ and so on.
diff --git a/contrib/tools/swig/CHANGES.current b/contrib/tools/swig/CHANGES.current
new file mode 100644
index 00000000000..e91b5c33bac
--- /dev/null
+++ b/contrib/tools/swig/CHANGES.current
@@ -0,0 +1,34 @@
+Below are the changes for the current release.
+See the CHANGES file for changes in older releases.
+See the RELEASENOTES file for a summary of changes in each release.
+Issue # numbers mentioned below can be found on Github. For more details, add
+the issue number to the end of the URL: https://github.com/swig/swig/issues/
+
+Version 4.3.1 (15 Apr 2025)
+===========================
+
+2025-04-10: jschueller, wsfulton
+ [Python] #3067 Fix compile errors regression using external runtime and
+ PY_LIMITED_API.
+
+2025-03-31: alatina
+ #3149 [Octave] Fix to compile with Octave 10.0
+
+2025-01-27: StefanBattmer
+ [Python] #2889 Fix regression when using directors and threads
+ but not using limited API.
+
+2024-11-21: olly
+ [Java] #3070 Fix regression wrapping enum values which don't fit
+ in a Java signed int.
+
+2024-10-27: olly
+ #3058 Fix precedence of casts, which should have the same high
+ precedence as unary plus and minus, but actually had a lower
+ precedence than anything else. This could lead to the wrong type
+ being deduced in obscure cases, but also prevented SWIG deducing a
+ type for expressions such as (0)*1+2 which SWIG parses as a cast
+ and then fixes up afterwards. A bug fixed in 4.3.0 made this
+ latter problem manifest more often (previously type deduction
+ happened to work for (0)*1+2 due to an internal field not getting
+ cleared properly).
diff --git a/contrib/tools/swig/COPYRIGHT b/contrib/tools/swig/COPYRIGHT
new file mode 100644
index 00000000000..bfe284a6a4b
--- /dev/null
+++ b/contrib/tools/swig/COPYRIGHT
@@ -0,0 +1,115 @@
+SWIG Copyright and Authors
+--------------------------
+
+Copyright (c) 1995-2023 The SWIG Developers
+Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
+Copyright (c) 1998-2005 University of Chicago.
+Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
+
+Portions also copyrighted by:
+ Network Applied Communication Laboratory, Inc
+ Information-technology Promotion Agency, Japan
+
+Active SWIG Developers:
+ William Fulton ([email protected]) (SWIG core, Java, C#, Windows, Cygwin)
+ Olly Betts ([email protected]) (PHP)
+ Joseph Wang ([email protected]) (R)
+ Momtchil Momtchev ([email protected]) (Javascript Node-API)
+ Simon Marchetto ([email protected]) (Scilab)
+ Zackery Spytz ([email protected]) (OCaml, SWIG core)
+
+Past SWIG developers and major contributors include:
+ Dave Beazley ([email protected]) (SWIG core, Python, Tcl, Perl)
+ Henning Thielemann ([email protected]) (Modula3)
+ Matthias Köppe ([email protected]) (Guile, MzScheme)
+ Luigi Ballabio ([email protected]) (STL wrapping)
+ Mikel Bancroft ([email protected]) (Allegro CL)
+ Surendra Singhi ([email protected]) (CLISP, CFFI)
+ Marcelo Matus ([email protected]) (SWIG core, Python, UTL[python,perl,tcl,ruby])
+ Art Yerkes ([email protected]) (OCaml)
+ Lyle Johnson ([email protected]) (Ruby)
+ Charlie Savage ([email protected]) (Ruby)
+ Thien-Thi Nguyen ([email protected]) (build/test/misc)
+ Richard Palmer ([email protected]) (PHP)
+ Sam Liddicott - Ananova Ltd ([email protected]) (PHP)
+ Tim Hockin - Sun Microsystems ([email protected]) (PHP)
+ Kevin Ruland (PHP)
+ Shibukawa Yoshiki (Japanese Translation)
+ Jason Stewart ([email protected]) (Perl5)
+ Loic Dachary (Perl5)
+ David Fletcher (Perl5)
+ Gary Holt (Perl5)
+ Masaki Fukushima (Ruby)
+ Scott Michel ([email protected]) (Java directors)
+ Tiger Feng ([email protected]) (SWIG core)
+ Mark Rose ([email protected]) (Directors)
+ Jonah Beckford ([email protected]) (CHICKEN)
+ Ahmon Dancy ([email protected]) (Allegro CL)
+ Dirk Gerrits (Allegro CL)
+ Neil Cawse (C#)
+ Harco de Hilster (Java)
+ Alexey Dyachenko ([email protected]) (Tcl)
+ Bob Techentin (Tcl)
+ Martin Froehlich <[email protected]> (Guile)
+ Marcio Luis Teixeira <[email protected]> (Guile)
+ Duncan Temple Lang (R)
+ Miklos Vajna <[email protected]> (PHP directors)
+ Mark Gossage ([email protected]) (Lua)
+ Raman Gopalan ([email protected]) (eLua)
+ Gonzalo Garramuno ([email protected]) (Ruby, Ruby's UTL)
+ John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
+ Baozeng Ding <[email protected]> (Scilab)
+ Ian Lance Taylor (Go)
+ Dmitry Kabak ([email protected]) (Doxygen)
+ Vadim Zeitlin (PCRE, Python, Doxygen)
+ Stefan Zager ([email protected]) (Python)
+ Vincent Couvert (Scilab)
+ Sylvestre Ledru (Scilab)
+ Wolfgang Frisch (Scilab)
+ Oliver Buchtala ([email protected]) (Javascript)
+ Neha Narang ([email protected]) (Javascript)
+ Xavier Delacour ([email protected]) (Octave)
+ David Nadlinger ([email protected]) (D)
+ Leif Middelschulte ([email protected]) (C)
+
+Past contributors include:
+ James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
+ Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
+ Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
+ Klaus Wiederänders, Richard Beare, Hans Oesterholt.
+ (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
+
+Past students:
+ Songyan Feng (Chicago).
+ Xinghua Shi (Chicago).
+ Jing Cao (Chicago).
+ Aquinas Hobor (Chicago).
+
+Historically, the following people contributed to early versions of SWIG.
+Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
+at Los Alamos National Laboratory were the first users. Patrick
+Tullmann at the University of Utah suggested the idea of automatic
+documentation generation. John Schmidt and Kurtis Bleeker at the
+University of Utah tested out the early versions. Chris Johnson
+supported SWIG's developed at the University of Utah. John Buckman,
+Larry Virden, and Tom Schwaller provided valuable input on the first
+releases and improving the portability of SWIG. David Fletcher and
+Gary Holt have provided a great deal of input on improving SWIG's
+Perl5 implementation. Kevin Butler contributed the first Windows NT
+port.
+
+Early bug reports and patches:
+Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
+Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
+Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
+Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
+Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
+Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
+Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
+Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
+Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
+Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
+Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
+Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
+Zhong Ren.
+
diff --git a/contrib/tools/swig/INSTALL b/contrib/tools/swig/INSTALL
new file mode 100644
index 00000000000..666ffd9f8ae
--- /dev/null
+++ b/contrib/tools/swig/INSTALL
@@ -0,0 +1,226 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for variables by setting
+them in the environment. You can do that on the command line like this:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Environment Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it cannot guess the host type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the host
+platform (i.e., that on which the generated programs will eventually be
+run) with `--host=TYPE'. In this case, you should also specify the
+build platform with `--build=TYPE', because, in this case, it may not
+be possible to guess the build platform (it sometimes involves
+compiling and running simple test programs, and this can't be done if
+the compiler is a cross compiler).
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Environment Variables
+=====================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to configure. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/contrib/tools/swig/LICENSE b/contrib/tools/swig/LICENSE
new file mode 100644
index 00000000000..d7a422fda11
--- /dev/null
+++ b/contrib/tools/swig/LICENSE
@@ -0,0 +1,22 @@
+SWIG is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. See the LICENSE-GPL file for
+the full terms of the GNU General Public license version 3.
+
+Portions of SWIG are also licensed under the terms of the licenses
+in the file LICENSE-UNIVERSITIES. You must observe the terms of
+these licenses, as well as the terms of the GNU General Public License,
+when you distribute SWIG.
+
+The SWIG library and examples, under the Lib and Examples top level
+directories, are distributed under the following terms:
+
+ You may copy, modify, distribute, and make derivative works based on
+ this software, in source code or object code form, without
+ restriction. If you distribute the software to others, you may do
+ so according to the terms of your choice. This software is offered as
+ is, without warranty of any kind.
+
+See the COPYRIGHT file for a list of contributors to SWIG and their
+copyright notices.
diff --git a/contrib/tools/swig/LICENSE-GPL b/contrib/tools/swig/LICENSE-GPL
new file mode 100644
index 00000000000..94a9ed024d3
--- /dev/null
+++ b/contrib/tools/swig/LICENSE-GPL
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/contrib/tools/swig/LICENSE-UNIVERSITIES b/contrib/tools/swig/LICENSE-UNIVERSITIES
new file mode 100644
index 00000000000..44fcaa13f6e
--- /dev/null
+++ b/contrib/tools/swig/LICENSE-UNIVERSITIES
@@ -0,0 +1,95 @@
+SWIG is distributed under the following terms:
+
+I.
+
+Copyright (c) 1995-1998
+The University of Utah and the Regents of the University of California
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following two paragraphs
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+IN NO EVENT SHALL THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, THE
+UNIVERSITY OF UTAH OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
+PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
+EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, AND THE UNIVERSITY OF UTAH
+SPECIFICALLY DISCLAIM ANY WARRANTIES,INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
+THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+
+II.
+
+This software includes contributions that are Copyright (c) 1998-2005
+University of Chicago.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer. Redistributions
+in binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution. Neither the name of
+the University of Chicago nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF CHICAGO AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+CHICAGO OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+III.
+
+This software includes contributions that are Copyright (c) 2005-2006
+Arizona Board of Regents (University of Arizona).
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following paragraph
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF ARIZONA AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+ARIZONA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/contrib/tools/swig/Lib/allkw.swg b/contrib/tools/swig/Lib/allkw.swg
new file mode 100644
index 00000000000..a549aec1d0e
--- /dev/null
+++ b/contrib/tools/swig/Lib/allkw.swg
@@ -0,0 +1,34 @@
+#ifndef SWIG_INCLUDED_LIB_ALLKW_SWG
+#define SWIG_INCLUDED_LIB_ALLKW_SWG
+
+
+/*
+ Include all the known keyword warnings. Very useful for adding test
+ files to the test-suite, or checking if your own library is ok for all
+ the swig supported languages.
+
+ Use as
+
+ swig -Wallkw ...
+
+ If you add a new language, remember to create a separate languagekw.swg
+ file, and add it here.
+
+*/
+
+%include <csharp/csharpkw.swg>
+%include <d/dkw.swg>
+%include <go/gokw.swg>
+%include <java/javakw.swg>
+%include <javascript/javascriptkw.swg>
+%include <lua/luakw.swg>
+%include <ocaml/ocamlkw.swg>
+%include <perl5/perlkw.swg>
+%include <php/phpkw.swg>
+%include <python/pythonkw.swg>
+%include <r/rkw.swg>
+%include <ruby/rubykw.swg>
+%include <tcl/tclkw.swg>
+
+
+#endif // SWIG_INCLUDED_LIB_ALLKW_SWG
diff --git a/contrib/tools/swig/Lib/attribute.i b/contrib/tools/swig/Lib/attribute.i
new file mode 100644
index 00000000000..d580dbfe95f
--- /dev/null
+++ b/contrib/tools/swig/Lib/attribute.i
@@ -0,0 +1,21 @@
+/* -----------------------------------------------------------------------------
+ * attribute.i
+ *
+ * SWIG library file for implementing attributes.
+ * ----------------------------------------------------------------------------- */
+
+/* we use a simple exception warning here */
+%{
+#include <stdio.h>
+%}
+#define %attribute_exception(code,msg) printf("%s\n",msg)
+
+#ifndef %arg
+#define %arg(x...) x
+#endif
+
+#ifndef %mangle
+#define %mangle(Type...) #@Type
+#endif
+
+%include <typemaps/attribute.swg>
diff --git a/contrib/tools/swig/Lib/carrays.i b/contrib/tools/swig/Lib/carrays.i
new file mode 100644
index 00000000000..71712c83cc2
--- /dev/null
+++ b/contrib/tools/swig/Lib/carrays.i
@@ -0,0 +1,122 @@
+/* -----------------------------------------------------------------------------
+ * carrays.i
+ *
+ * SWIG library file containing macros that can be used to manipulate simple
+ * pointers as arrays.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef __cplusplus
+// C uses free/calloc/malloc
+%include "swigfragments.swg"
+%fragment("<stdlib.h>");
+#endif
+
+/* -----------------------------------------------------------------------------
+ * %array_functions(TYPE,NAME)
+ *
+ * Generates functions for creating and accessing elements of a C array
+ * (as pointers). Creates the following functions:
+ *
+ * TYPE *new_NAME(size_t nelements)
+ * void delete_NAME(TYPE *);
+ * TYPE NAME_getitem(TYPE *, size_t index);
+ * void NAME_setitem(TYPE *, size_t index, TYPE value);
+ *
+ * ----------------------------------------------------------------------------- */
+
+%define %array_functions(TYPE,NAME)
+%{
+static TYPE *new_##NAME(size_t nelements) { %}
+#ifdef __cplusplus
+%{ return new TYPE[nelements](); %}
+#else
+%{ return (TYPE *) calloc(nelements,sizeof(TYPE)); %}
+#endif
+%{}
+
+static void delete_##NAME(TYPE *ary) { %}
+#ifdef __cplusplus
+%{ delete [] ary; %}
+#else
+%{ free(ary); %}
+#endif
+%{}
+
+static TYPE NAME##_getitem(TYPE *ary, size_t index) {
+ return ary[index];
+}
+static void NAME##_setitem(TYPE *ary, size_t index, TYPE value) {
+ ary[index] = value;
+}
+%}
+
+TYPE *new_##NAME(size_t nelements);
+void delete_##NAME(TYPE *ary);
+TYPE NAME##_getitem(TYPE *ary, size_t index);
+void NAME##_setitem(TYPE *ary, size_t index, TYPE value);
+
+%enddef
+
+
+/* -----------------------------------------------------------------------------
+ * %array_class(TYPE,NAME)
+ *
+ * Generates a class wrapper around a C array. The class has the following
+ * interface:
+ *
+ * struct NAME {
+ * NAME(size_t nelements);
+ * ~NAME();
+ * TYPE getitem(size_t index);
+ * void setitem(size_t index, TYPE value);
+ * TYPE * cast();
+ * static NAME *frompointer(TYPE *t);
+ * }
+ *
+ * ----------------------------------------------------------------------------- */
+
+%define %array_class(TYPE,NAME)
+%{
+typedef TYPE NAME;
+%}
+typedef struct {
+ /* Put language specific enhancements here */
+} NAME;
+
+%extend NAME {
+
+#ifdef __cplusplus
+NAME(size_t nelements) {
+ return new TYPE[nelements]();
+}
+~NAME() {
+ delete [] self;
+}
+#else
+NAME(size_t nelements) {
+ return (TYPE *) calloc(nelements,sizeof(TYPE));
+}
+~NAME() {
+ free(self);
+}
+#endif
+
+TYPE getitem(size_t index) {
+ return self[index];
+}
+void setitem(size_t index, TYPE value) {
+ self[index] = value;
+}
+TYPE * cast() {
+ return self;
+}
+static NAME *frompointer(TYPE *t) {
+ return (NAME *) t;
+}
+
+};
+
+%types(NAME = TYPE);
+
+%enddef
+
diff --git a/contrib/tools/swig/Lib/cdata.i b/contrib/tools/swig/Lib/cdata.i
new file mode 100644
index 00000000000..528e0d1ea1e
--- /dev/null
+++ b/contrib/tools/swig/Lib/cdata.i
@@ -0,0 +1,50 @@
+/* -----------------------------------------------------------------------------
+ * cdata.i
+ *
+ * SWIG library file containing macros for manipulating raw C data.
+ * ----------------------------------------------------------------------------- */
+
+%typemap(in,noblock=0,fragment="SWIG_AsCharPtrAndSize") (const void *BYTES, size_t LENGTH) (int res, void *buf = 0, size_t len = 0, int alloc = 0) {
+ res = SWIG_AsCharPtrAndSize($input, (char **)&buf, &len, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $1 = %reinterpret_cast(buf, $1_ltype);
+ $2 = %numeric_cast(len, $2_ltype);
+}
+
+%typemap(freearg,noblock=1,match="in") (const void *BYTES, size_t LENGTH) {
+ if (alloc$argnum == SWIG_NEWOBJ) {
+ %delete_array((char*)(buf$argnum));
+ }
+}
+
+%typemap(directorin,noblock=1,fragment="SWIG_FromCharPtrAndSize") (const void *BYTES, size_t LENGTH) {
+ if ($1 && $2 > 0) {
+ $input = SWIG_FromCharPtrAndSize((const char*)$1, (size_t)$2);
+ } else {
+ $input = SWIG_FromCharPtrAndSize("", 0);
+ }
+}
+
+%typemap(in) (void *BYTES, size_t LENGTH) = (const void *BYTES, size_t LENGTH);
+%typemap(freearg) (void *BYTES, size_t LENGTH) = (const void *BYTES, size_t LENGTH);
+%typemap(directorin) (void *BYTES, size_t LENGTH) = (const void *BYTES, size_t LENGTH);
+%typemap(in) (const void *BYTES, int LENGTH) = (const void *BYTES, size_t LENGTH);
+%typemap(freearg) (const void *BYTES, int LENGTH) = (const void *BYTES, size_t LENGTH);
+%typemap(directorin) (const void *BYTES, int LENGTH) = (const void *BYTES, size_t LENGTH);
+%typemap(in) (void *BYTES, int LENGTH) = (const void *BYTES, int LENGTH);
+%typemap(freearg) (void *BYTES, int LENGTH) = (const void *BYTES, int LENGTH);
+%typemap(directorin) (void *BYTES, int LENGTH) = (const void *BYTES, int LENGTH);
+%typemap(in) (const void *indata, size_t inlen) = (const void *BYTES, size_t LENGTH);
+%typemap(freearg) (const void *indata, size_t inlen) = (const void *BYTES, size_t LENGTH);
+%typemap(directorin) (const void *indata, size_t inlen) = (const void *BYTES, size_t LENGTH);
+#define SWIG_CDATA_APPLIED
+
+%include <typemaps/cdata_begin.swg>
+
+%typemap(out,noblock=1,fragment="SWIG_FromCharPtrAndSize") SWIGCDATA {
+ %set_output(SWIG_FromCharPtrAndSize($1.data,$1.len));
+}
+
+%include <typemaps/cdata_end.swg>
diff --git a/contrib/tools/swig/Lib/cmalloc.i b/contrib/tools/swig/Lib/cmalloc.i
new file mode 100644
index 00000000000..9f58bc03ca4
--- /dev/null
+++ b/contrib/tools/swig/Lib/cmalloc.i
@@ -0,0 +1,110 @@
+/* -----------------------------------------------------------------------------
+ * cmalloc.i
+ *
+ * SWIG library file containing macros that can be used to create objects using
+ * the C malloc function.
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <stdlib.h>
+%}
+
+/* %malloc(TYPE [, NAME = TYPE])
+ %calloc(TYPE [, NAME = TYPE])
+ %realloc(TYPE [, NAME = TYPE])
+ %free(TYPE [, NAME = TYPE])
+ %allocators(TYPE [,NAME = TYPE])
+
+ Creates functions for allocating/reallocating memory.
+
+ TYPE *malloc_NAME(int nbytes = sizeof(TYPE);
+ TYPE *calloc_NAME(int nobj=1, int size=sizeof(TYPE));
+ TYPE *realloc_NAME(TYPE *ptr, int nbytes);
+ void free_NAME(TYPE *ptr);
+
+*/
+
+%define %malloc(TYPE,NAME...)
+#if #NAME != ""
+%rename(malloc_##NAME) ::malloc(int nbytes);
+#else
+%rename(malloc_##TYPE) ::malloc(int nbytes);
+#endif
+
+#if #TYPE != "void"
+%typemap(default) int nbytes "$1 = (int) sizeof(TYPE);"
+#endif
+TYPE *malloc(int nbytes);
+%typemap(default) int nbytes;
+%enddef
+
+%define %calloc(TYPE,NAME...)
+#if #NAME != ""
+%rename(calloc_##NAME) ::calloc(int nobj, int sz);
+#else
+%rename(calloc_##TYPE) ::calloc(int nobj, int sz);
+#endif
+#if #TYPE != "void"
+%typemap(default) int sz "$1 = (int) sizeof(TYPE);"
+#else
+%typemap(default) int sz "$1 = 1;"
+#endif
+%typemap(default) int nobj "$1 = 1;"
+TYPE *calloc(int nobj, int sz);
+%typemap(default) int sz;
+%typemap(default) int nobj;
+%enddef
+
+%define %realloc(TYPE,NAME...)
+%insert("header") {
+#if #NAME != ""
+TYPE *realloc_##NAME(TYPE *ptr, int nitems)
+#else
+TYPE *realloc_##TYPE(TYPE *ptr, int nitems)
+#endif
+{
+#if #TYPE != "void"
+return (TYPE *) realloc(ptr, nitems*sizeof(TYPE));
+#else
+return (TYPE *) realloc(ptr, nitems);
+#endif
+}
+}
+#if #NAME != ""
+TYPE *realloc_##NAME(TYPE *ptr, int nitems);
+#else
+TYPE *realloc_##TYPE(TYPE *ptr, int nitems);
+#endif
+%enddef
+
+%define %free(TYPE,NAME...)
+#if #NAME != ""
+%rename(free_##NAME) ::free(TYPE *ptr);
+#else
+%rename(free_##TYPE) ::free(TYPE *ptr);
+#endif
+void free(TYPE *ptr);
+%enddef
+
+%define %sizeof(TYPE,NAME...)
+#if #NAME != ""
+%constant int sizeof_##NAME = sizeof(TYPE);
+#else
+%constant int sizeof_##TYPE = sizeof(TYPE);
+#endif
+%enddef
+
+%define %allocators(TYPE,NAME...)
+%malloc(TYPE,NAME)
+%calloc(TYPE,NAME)
+%realloc(TYPE,NAME)
+%free(TYPE,NAME)
+#if #TYPE != "void"
+%sizeof(TYPE,NAME)
+#endif
+%enddef
+
+
+
+
+
diff --git a/contrib/tools/swig/Lib/constraints.i b/contrib/tools/swig/Lib/constraints.i
new file mode 100644
index 00000000000..20c4c15ce8b
--- /dev/null
+++ b/contrib/tools/swig/Lib/constraints.i
@@ -0,0 +1,217 @@
+/* -----------------------------------------------------------------------------
+ * constraints.i
+ *
+ * SWIG constraints library.
+ *
+ * SWIG library file containing typemaps for implementing various kinds of
+ * constraints. Depends upon the SWIG exception library for generating
+ * errors in a language-independent manner.
+ * ----------------------------------------------------------------------------- */
+
+// This library provides support for applying constraints to function
+// arguments. Using a constraint, you can restrict arguments to be
+// positive numbers, non-NULL pointers, and so on. The following
+// constraints are available :
+//
+// Number POSITIVE - Positive number (not zero)
+// Number NEGATIVE - Negative number (not zero)
+// Number NONZERO - Nonzero number
+// Number NONNEGATIVE - Positive number (including zero)
+// Number NONPOSITIVE - Negative number (including zero)
+// Pointer NONNULL - Non-NULL pointer
+// Pointer ALIGN8 - 8-byte aligned pointer
+// Pointer ALIGN4 - 4-byte aligned pointer
+// Pointer ALIGN2 - 2-byte aligned pointer
+//
+// To use the constraints, you need to "apply" them to specific
+// function arguments in your code. This is done using the %apply
+// directive. For example :
+//
+// %apply Number NONNEGATIVE { double nonneg };
+// double sqrt(double nonneg); // Name of argument must match
+//
+// %apply Pointer NONNULL { FILE *stream };
+// FILE *fdopen(int NONNEGATIVE); // May return a NULL pointer
+// int fclose(void *stream); // Does not accept a NULL pointer
+//
+// Any function argument of the type you specify with the %apply directive
+// will be checked with the appropriate constraint. Multiple types may
+// be specified as follows :
+//
+// %apply Pointer NONNULL { void *, Vector *, List *, double *};
+//
+// In this case, all of the types listed would be checked for non-NULL
+// pointers.
+//
+// The common datatypes of int, short, long, unsigned int, unsigned long,
+// unsigned short, unsigned char, signed char, float, and double can be
+// checked without using the %apply directive by simply using the
+// constraint name as the parameter name. For example :
+//
+// double sqrt(double NONNEGATIVE);
+// double log(double POSITIVE);
+//
+// If you have used typedef to change type-names, you can also do this :
+//
+// %apply double { Real }; // Make everything defined for doubles
+// // work for Reals.
+// Real sqrt(Real NONNEGATIVE);
+// Real log(Real POSITIVE);
+
+%include <exception.i>
+
+#if defined(SWIGCSHARP) || defined(SWIGD)
+// Required attribute for C# and D exception handling
+#define SWIGCSHARPCANTHROW , canthrow=1
+#else
+#define SWIGCSHARPCANTHROW
+#endif
+
+
+// Positive numbers
+
+%typemap(check SWIGCSHARPCANTHROW)
+ int POSITIVE,
+ short POSITIVE,
+ long POSITIVE,
+ unsigned int POSITIVE,
+ unsigned short POSITIVE,
+ unsigned long POSITIVE,
+ signed char POSITIVE,
+ unsigned char POSITIVE,
+ float POSITIVE,
+ double POSITIVE,
+ Number POSITIVE
+{
+ if ($1 <= 0) {
+ SWIG_exception(SWIG_ValueError,"Expected a positive value.");
+ }
+}
+
+// Negative numbers
+
+%typemap(check SWIGCSHARPCANTHROW)
+ int NEGATIVE,
+ short NEGATIVE,
+ long NEGATIVE,
+ unsigned int NEGATIVE,
+ unsigned short NEGATIVE,
+ unsigned long NEGATIVE,
+ signed char NEGATIVE,
+ unsigned char NEGATIVE,
+ float NEGATIVE,
+ double NEGATIVE,
+ Number NEGATIVE
+{
+ if ($1 >= 0) {
+ SWIG_exception(SWIG_ValueError,"Expected a negative value.");
+ }
+}
+
+// Nonzero numbers
+
+%typemap(check SWIGCSHARPCANTHROW)
+ int NONZERO,
+ short NONZERO,
+ long NONZERO,
+ unsigned int NONZERO,
+ unsigned short NONZERO,
+ unsigned long NONZERO,
+ signed char NONZERO,
+ unsigned char NONZERO,
+ float NONZERO,
+ double NONZERO,
+ Number NONZERO
+{
+ if ($1 == 0) {
+ SWIG_exception(SWIG_ValueError,"Expected a nonzero value.");
+ }
+}
+
+// Nonnegative numbers
+
+%typemap(check SWIGCSHARPCANTHROW)
+ int NONNEGATIVE,
+ short NONNEGATIVE,
+ long NONNEGATIVE,
+ unsigned int NONNEGATIVE,
+ unsigned short NONNEGATIVE,
+ unsigned long NONNEGATIVE,
+ signed char NONNEGATIVE,
+ unsigned char NONNEGATIVE,
+ float NONNEGATIVE,
+ double NONNEGATIVE,
+ Number NONNEGATIVE
+{
+ if ($1 < 0) {
+ SWIG_exception(SWIG_ValueError,"Expected a non-negative value.");
+ }
+}
+
+// Nonpositive numbers
+
+%typemap(check SWIGCSHARPCANTHROW)
+ int NONPOSITIVE,
+ short NONPOSITIVE,
+ long NONPOSITIVE,
+ unsigned int NONPOSITIVE,
+ unsigned short NONPOSITIVE,
+ unsigned long NONPOSITIVE,
+ signed char NONPOSITIVE,
+ unsigned char NONPOSITIVE,
+ float NONPOSITIVE,
+ double NONPOSITIVE,
+ Number NONPOSITIVE
+{
+ if ($1 > 0) {
+ SWIG_exception(SWIG_ValueError,"Expected a non-positive value.");
+ }
+}
+
+// Non-NULL pointer
+
+%typemap(check SWIGCSHARPCANTHROW)
+ void * NONNULL,
+ Pointer NONNULL
+{
+ if (!$1) {
+ SWIG_exception(SWIG_NullReferenceError,"Received a NULL pointer.");
+ }
+}
+
+// Aligned pointers
+
+%typemap(check SWIGCSHARPCANTHROW)
+ void * ALIGN8,
+ Pointer ALIGN8
+{
+ unsigned long long tmp;
+ tmp = (unsigned long long) $1;
+ if (tmp & 7) {
+ SWIG_exception(SWIG_ValueError,"Pointer must be 8-byte aligned.");
+ }
+}
+
+%typemap(check SWIGCSHARPCANTHROW)
+ void * ALIGN4,
+ Pointer ALIGN4
+{
+ unsigned long long tmp;
+ tmp = (unsigned long long) $1;
+ if (tmp & 3) {
+ SWIG_exception(SWIG_ValueError,"Pointer must be 4-byte aligned.");
+ }
+}
+
+%typemap(check SWIGCSHARPCANTHROW)
+ void * ALIGN2,
+ Pointer ALIGN2
+{
+ unsigned long long tmp;
+ tmp = (unsigned long long) $1;
+ if (tmp & 1) {
+ SWIG_exception(SWIG_ValueError,"Pointer must be 2-byte aligned.");
+ }
+}
+
+
diff --git a/contrib/tools/swig/Lib/cpointer.i b/contrib/tools/swig/Lib/cpointer.i
new file mode 100644
index 00000000000..df40c0426af
--- /dev/null
+++ b/contrib/tools/swig/Lib/cpointer.i
@@ -0,0 +1,186 @@
+/* -----------------------------------------------------------------------------
+ * cpointer.i
+ *
+ * SWIG library file containing macros that can be used to manipulate simple
+ * pointer objects.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef __cplusplus
+// C uses free/calloc/malloc
+%include "swigfragments.swg"
+%fragment("<stdlib.h>");
+#endif
+
+/* -----------------------------------------------------------------------------
+ * %pointer_class(type,name)
+ *
+ * Places a simple proxy around a simple type like 'int', 'float', or whatever.
+ * The proxy provides this interface:
+ *
+ * class type {
+ * public:
+ * type();
+ * ~type();
+ * type value();
+ * void assign(type value);
+ * };
+ *
+ * Example:
+ *
+ * %pointer_class(int, intp);
+ *
+ * int add(int *x, int *y) { return *x + *y; }
+ *
+ * In python (with proxies)
+ *
+ * >>> a = intp()
+ * >>> a.assign(10)
+ * >>> a.value()
+ * 10
+ * >>> b = intp()
+ * >>> b.assign(20)
+ * >>> print add(a,b)
+ * 30
+ *
+ * As a general rule, this macro should not be used on class/structures that
+ * are already defined in the interface.
+ * ----------------------------------------------------------------------------- */
+
+
+%define %pointer_class(TYPE, NAME)
+%{
+typedef TYPE NAME;
+%}
+
+typedef struct {
+} NAME;
+
+%extend NAME {
+#ifdef __cplusplus
+NAME() {
+ return new TYPE();
+}
+~NAME() {
+ delete $self;
+}
+#else
+NAME() {
+ return (TYPE *) calloc(1,sizeof(TYPE));
+}
+~NAME() {
+ free($self);
+}
+#endif
+}
+
+%extend NAME {
+
+void assign(TYPE value) {
+ *$self = value;
+}
+TYPE value() {
+ return *$self;
+}
+TYPE * cast() {
+ return $self;
+}
+static NAME * frompointer(TYPE *t) {
+ return (NAME *) t;
+}
+
+}
+
+%types(NAME = TYPE);
+
+%enddef
+
+/* -----------------------------------------------------------------------------
+ * %pointer_functions(type,name)
+ *
+ * Create functions for allocating/deallocating pointers. This can be used
+ * if you don't want to create a proxy class or if the pointer is complex.
+ *
+ * %pointer_functions(int, intp)
+ *
+ * int add(int *x, int *y) { return *x + *y; }
+ *
+ * In python (with proxies)
+ *
+ * >>> a = copy_intp(10)
+ * >>> intp_value(a)
+ * 10
+ * >>> b = new_intp()
+ * >>> intp_assign(b,20)
+ * >>> print add(a,b)
+ * 30
+ * >>> delete_intp(a)
+ * >>> delete_intp(b)
+ *
+ * ----------------------------------------------------------------------------- */
+
+%define %pointer_functions(TYPE,NAME)
+%{
+static TYPE *new_##NAME(void) { %}
+#ifdef __cplusplus
+%{ return new TYPE(); %}
+#else
+%{ return (TYPE *) calloc(1,sizeof(TYPE)); %}
+#endif
+%{}
+
+static TYPE *copy_##NAME(TYPE value) { %}
+#ifdef __cplusplus
+%{ return new TYPE(value); %}
+#else
+%{ TYPE *obj = (TYPE *) calloc(1,sizeof(TYPE));
+ *obj = value;
+ return obj; %}
+#endif
+%{}
+
+static void delete_##NAME(TYPE *obj) { %}
+#ifdef __cplusplus
+%{ delete obj; %}
+#else
+%{ free(obj); %}
+#endif
+%{}
+
+static void NAME ##_assign(TYPE *obj, TYPE value) {
+ *obj = value;
+}
+
+static TYPE NAME ##_value(TYPE *obj) {
+ return *obj;
+}
+%}
+
+TYPE *new_##NAME(void);
+TYPE *copy_##NAME(TYPE value);
+void delete_##NAME(TYPE *obj);
+void NAME##_assign(TYPE *obj, TYPE value);
+TYPE NAME##_value(TYPE *obj);
+
+%enddef
+
+/* -----------------------------------------------------------------------------
+ * %pointer_cast(type1,type2,name)
+ *
+ * Generates a pointer casting function.
+ * ----------------------------------------------------------------------------- */
+
+%define %pointer_cast(TYPE1,TYPE2,NAME)
+%inline %{
+TYPE2 NAME(TYPE1 x) {
+ return (TYPE2) x;
+}
+%}
+%enddef
+
+
+
+
+
+
+
+
diff --git a/contrib/tools/swig/Lib/cstring.i b/contrib/tools/swig/Lib/cstring.i
new file mode 100644
index 00000000000..6829f759742
--- /dev/null
+++ b/contrib/tools/swig/Lib/cstring.i
@@ -0,0 +1,12 @@
+/* -----------------------------------------------------------------------------
+ * cstring.i
+ * ----------------------------------------------------------------------------- */
+
+%echo "cstring.i not implemented for this target"
+#define SWIG_CSTRING_UNIMPL
+
+/* old name keep for compatibility */
+#define _CSTRING_UNIMPL
+
+
+
diff --git a/contrib/tools/swig/Lib/cwstring.i b/contrib/tools/swig/Lib/cwstring.i
new file mode 100644
index 00000000000..f0631d3280f
--- /dev/null
+++ b/contrib/tools/swig/Lib/cwstring.i
@@ -0,0 +1,11 @@
+/* -----------------------------------------------------------------------------
+ * cwstring.i
+ * ----------------------------------------------------------------------------- */
+
+%echo "cwstring.i not implemented for this target"
+#define SWIG_CWSTRING_UNIMPL
+
+
+
+
+
diff --git a/contrib/tools/swig/Lib/director_common.swg b/contrib/tools/swig/Lib/director_common.swg
new file mode 100644
index 00000000000..9ce93c7e778
--- /dev/null
+++ b/contrib/tools/swig/Lib/director_common.swg
@@ -0,0 +1,15 @@
+/* -----------------------------------------------------------------------------
+ * director_common.swg
+ *
+ * This file contains support for director classes which is common between
+ * languages.
+ * ----------------------------------------------------------------------------- */
+
+/*
+ Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the
+ 'Swig' namespace. This could be useful for multi-modules projects.
+*/
+#ifdef SWIG_DIRECTOR_STATIC
+/* Force anonymous (static) namespace */
+#define Swig
+#endif
diff --git a/contrib/tools/swig/Lib/director_guard.swg b/contrib/tools/swig/Lib/director_guard.swg
new file mode 100644
index 00000000000..b261fa5652d
--- /dev/null
+++ b/contrib/tools/swig/Lib/director_guard.swg
@@ -0,0 +1,105 @@
+/* -----------------------------------------------------------------------------
+ * director_guard.swg
+ *
+ * Generic Mutex implementation for directors
+ *
+ * Before including this file, there are two macros to define for choosing
+ * an implementation as follows:
+ * - SWIG_THREADS:
+ * If defined than mutexes are used.
+ * If not defined then mutexes are not used.
+ * - SWIG_HAVE_MUTEX:
+ * If there is a target language defined 'Mutex' class available, the target
+ * language will define this macro to use the class over the options below.
+ * The language 'Mutex' class needs to be Basic Lockable.
+ * It must have public 'void lock()' and 'void unlock()' methods.
+ * See: https://en.cppreference.com/w/cpp/named_req/BasicLockable
+ * If the macro is not defined, one of the following will be used in this order:
+ * - std::mutex if using C++11 or later.
+ * - CRITICAL_SECTION on Windows.
+ * - POSIX pthread mutex.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef SWIG_THREADS
+
+#if __cplusplus >= 201103L
+/*
+ * C++ 11 or above
+ * std::mutex https://en.cppreference.com/w/cpp/thread/mutex
+ * std::unique_lock https://en.cppreference.com/w/cpp/thread/unique_lock
+ */
+#include <mutex>
+#ifdef SWIG_HAVE_MUTEX
+/* Use Language defined Mutex class */
+#define SWIG_GUARD(_mutex) std::unique_lock<Mutex> _guard(_mutex)
+#define SWIG_GUARD_DEFINITION(_cls, _mutex) Mutex _cls::_mutex
+#define SWIG_GUARD_DECLARATION(_mutex) static Mutex _mutex
+#else
+#define SWIG_GUARD(_mutex) std::unique_lock<std::mutex> _guard(_mutex)
+#define SWIG_GUARD_DEFINITION(_cls, _mutex) std::mutex _cls::_mutex
+#define SWIG_GUARD_DECLARATION(_mutex) static std::mutex _mutex
+#endif
+
+#else /* __cplusplus */
+
+#ifdef SWIG_HAVE_MUTEX
+/* Use Language defined Mutex class */
+
+#elif defined(_WIN32)
+/*
+ * Windows Critical Section Objects
+ * https://learn.microsoft.com/en-us/windows/win32/Sync/critical-section-objects
+ */
+#include <windows.h>
+#include <synchapi.h>
+namespace Swig {
+ class Mutex {
+ CRITICAL_SECTION mutex_;
+ public:
+ Mutex() { InitializeCriticalSection(&mutex_); }
+ ~Mutex() { DeleteCriticalSection(&mutex_); }
+ void lock() { EnterCriticalSection(&mutex_); }
+ void unlock() { LeaveCriticalSection(&mutex_); }
+ };
+}
+
+#else /* _WIN32 */
+/*
+ * POSIX Thread mutex
+ * https://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread.h.html
+ */
+#include <pthread.h>
+namespace Swig {
+ class Mutex {
+ pthread_mutex_t mutex_;
+ public:
+ Mutex() { pthread_mutex_init(&mutex_, NULL); }
+ ~Mutex() { pthread_mutex_destroy(&mutex_); }
+ void lock() { pthread_mutex_lock(&mutex_); }
+ void unlock() { pthread_mutex_unlock(&mutex_); }
+ };
+}
+
+#endif /* _WIN32 */
+
+namespace Swig {
+ class Unique_lock {
+ Mutex &mutex_;
+ public:
+ Unique_lock(Mutex &_mutex) : mutex_(_mutex) { mutex_.lock(); }
+ ~Unique_lock() { mutex_.unlock(); }
+ };
+}
+#define SWIG_GUARD(_mutex) Unique_lock _guard(_mutex)
+#define SWIG_GUARD_DEFINITION(_cls, _mutex) Mutex _cls::_mutex
+#define SWIG_GUARD_DECLARATION(_mutex) static Mutex _mutex
+
+#endif /* __cplusplus */
+
+#else /* SWIG_THREADS */
+
+#define SWIG_GUARD(_mutex)
+#define SWIG_GUARD_DEFINITION(_cls, _mutex)
+#define SWIG_GUARD_DECLARATION(_mutex)
+
+#endif /* SWIG_THREADS */
diff --git a/contrib/tools/swig/Lib/exception.i b/contrib/tools/swig/Lib/exception.i
new file mode 100644
index 00000000000..c3629bbfaba
--- /dev/null
+++ b/contrib/tools/swig/Lib/exception.i
@@ -0,0 +1,341 @@
+/* -----------------------------------------------------------------------------
+ * exception.i
+ *
+ * SWIG library file providing language independent exception handling
+ * ----------------------------------------------------------------------------- */
+
+#if defined(SWIGUTL)
+#error "This version of exception.i should not be used"
+#endif
+
+
+%insert("runtime") "swigerrors.swg"
+
+
+#ifdef SWIGPHP
+%{
+#define SWIG_exception(code, msg) do { zend_throw_exception( \
+ code == SWIG_TypeError ? zend_ce_type_error : \
+ code == SWIG_ValueError ? zend_ce_value_error : \
+ code == SWIG_DivisionByZero ? zend_ce_division_by_zero_error : \
+ code == SWIG_SyntaxError ? zend_ce_parse_error : \
+ code == SWIG_OverflowError ? zend_ce_arithmetic_error : \
+ code == SWIG_NullReferenceError ? zend_ce_type_error : \
+ NULL, msg, code); SWIG_fail; } while (0)
+%}
+#endif
+
+#ifdef SWIGGUILE
+%{
+ SWIGINTERN void SWIG_exception_ (int code, const char *msg,
+ const char *subr) {
+#define ERROR(scmerr) \
+ scm_error(scm_from_locale_string(scmerr), \
+ subr, msg, SCM_EOL, SCM_BOOL_F)
+#define MAP(swigerr, scmerr) \
+ case swigerr: \
+ ERROR(scmerr); \
+ break
+ switch (code) {
+ MAP(SWIG_MemoryError, "swig-memory-error");
+ MAP(SWIG_IOError, "swig-io-error");
+ MAP(SWIG_RuntimeError, "swig-runtime-error");
+ MAP(SWIG_IndexError, "swig-index-error");
+ MAP(SWIG_TypeError, "swig-type-error");
+ MAP(SWIG_DivisionByZero, "swig-division-by-zero");
+ MAP(SWIG_OverflowError, "swig-overflow-error");
+ MAP(SWIG_SyntaxError, "swig-syntax-error");
+ MAP(SWIG_ValueError, "swig-value-error");
+ MAP(SWIG_SystemError, "swig-system-error");
+ MAP(SWIG_NullReferenceError, "swig-null-reference-error");
+ default:
+ ERROR("swig-error");
+ }
+#undef ERROR
+#undef MAP
+ }
+
+#define SWIG_exception(a,b) SWIG_exception_(a, b, FUNC_NAME)
+%}
+#endif
+
+#ifdef SWIGMZSCHEME
+
+%{
+SWIGINTERN void SWIG_exception_ (int code, const char *msg) {
+#define ERROR(errname) \
+ scheme_signal_error(errname " (%s)", msg);
+#define MAP(swigerr, errname) \
+ case swigerr: \
+ ERROR(errname); \
+ break
+ switch (code) {
+ MAP(SWIG_MemoryError, "swig-memory-error");
+ MAP(SWIG_IOError, "swig-io-error");
+ MAP(SWIG_RuntimeError, "swig-runtime-error");
+ MAP(SWIG_IndexError, "swig-index-error");
+ MAP(SWIG_TypeError, "swig-type-error");
+ MAP(SWIG_DivisionByZero, "swig-division-by-zero");
+ MAP(SWIG_OverflowError, "swig-overflow-error");
+ MAP(SWIG_SyntaxError, "swig-syntax-error");
+ MAP(SWIG_ValueError, "swig-value-error");
+ MAP(SWIG_SystemError, "swig-system-error");
+ MAP(SWIG_NullReferenceError, "swig-null-reference-error");
+ default:
+ ERROR("swig-error");
+ }
+#undef ERROR
+#undef MAP
+ }
+
+#define SWIG_exception(a,b) SWIG_exception_(a, b)
+%}
+#endif
+
+#ifdef SWIGJAVA
+%{
+SWIGINTERN void SWIG_JavaException(JNIEnv *jenv, int code, const char *msg) {
+ SWIG_JavaExceptionCodes exception_code = SWIG_JavaUnknownError;
+ switch(code) {
+ case SWIG_MemoryError:
+ exception_code = SWIG_JavaOutOfMemoryError;
+ break;
+ case SWIG_IOError:
+ exception_code = SWIG_JavaIOException;
+ break;
+ case SWIG_SystemError:
+ case SWIG_RuntimeError:
+ exception_code = SWIG_JavaRuntimeException;
+ break;
+ case SWIG_OverflowError:
+ case SWIG_IndexError:
+ exception_code = SWIG_JavaIndexOutOfBoundsException;
+ break;
+ case SWIG_DivisionByZero:
+ exception_code = SWIG_JavaArithmeticException;
+ break;
+ case SWIG_SyntaxError:
+ case SWIG_ValueError:
+ case SWIG_TypeError:
+ exception_code = SWIG_JavaIllegalArgumentException;
+ break;
+ case SWIG_NullReferenceError:
+ exception_code = SWIG_JavaNullPointerException;
+ break;
+ case SWIG_UnknownError:
+ default:
+ exception_code = SWIG_JavaUnknownError;
+ break;
+ }
+ SWIG_JavaThrowException(jenv, exception_code, msg);
+}
+%}
+
+#define SWIG_exception(code, msg)\
+{ SWIG_JavaException(jenv, code, msg); return $null; }
+#endif // SWIGJAVA
+
+#ifdef SWIGOCAML
+%{
+SWIGINTERN void SWIG_OCamlException(int code, const char *msg) {
+ CAMLparam0();
+
+ SWIG_OCamlExceptionCodes exception_code = SWIG_OCamlUnknownError;
+ switch (code) {
+ case SWIG_DivisionByZero:
+ exception_code = SWIG_OCamlArithmeticException;
+ break;
+ case SWIG_IndexError:
+ exception_code = SWIG_OCamlIndexOutOfBoundsException;
+ break;
+ case SWIG_IOError:
+ case SWIG_SystemError:
+ exception_code = SWIG_OCamlSystemException;
+ break;
+ case SWIG_MemoryError:
+ exception_code = SWIG_OCamlOutOfMemoryError;
+ break;
+ case SWIG_OverflowError:
+ exception_code = SWIG_OCamlOverflowException;
+ break;
+ case SWIG_RuntimeError:
+ exception_code = SWIG_OCamlRuntimeException;
+ break;
+ case SWIG_SyntaxError:
+ case SWIG_TypeError:
+ case SWIG_ValueError:
+ exception_code = SWIG_OCamlIllegalArgumentException;
+ break;
+ case SWIG_NullReferenceError:
+ exception_code = SWIG_OCamlNullReferenceException;
+ break;
+ case SWIG_UnknownError:
+ default:
+ exception_code = SWIG_OCamlUnknownError;
+ break;
+ }
+ SWIG_OCamlThrowException(exception_code, msg);
+ CAMLreturn0;
+}
+#define SWIG_exception(code, msg) SWIG_OCamlException(code, msg)
+%}
+#endif
+
+
+#ifdef SWIGCSHARP
+%{
+SWIGINTERN void SWIG_CSharpException(int code, const char *msg) {
+ if (code == SWIG_ValueError) {
+ SWIG_CSharpExceptionArgumentCodes exception_code = SWIG_CSharpArgumentOutOfRangeException;
+ SWIG_CSharpSetPendingExceptionArgument(exception_code, msg, 0);
+ } else {
+ SWIG_CSharpExceptionCodes exception_code = SWIG_CSharpApplicationException;
+ switch(code) {
+ case SWIG_MemoryError:
+ exception_code = SWIG_CSharpOutOfMemoryException;
+ break;
+ case SWIG_IndexError:
+ exception_code = SWIG_CSharpIndexOutOfRangeException;
+ break;
+ case SWIG_DivisionByZero:
+ exception_code = SWIG_CSharpDivideByZeroException;
+ break;
+ case SWIG_IOError:
+ exception_code = SWIG_CSharpIOException;
+ break;
+ case SWIG_OverflowError:
+ exception_code = SWIG_CSharpOverflowException;
+ break;
+ case SWIG_NullReferenceError:
+ exception_code = SWIG_CSharpNullReferenceException;
+ break;
+ case SWIG_RuntimeError:
+ case SWIG_TypeError:
+ case SWIG_SyntaxError:
+ case SWIG_SystemError:
+ case SWIG_UnknownError:
+ default:
+ exception_code = SWIG_CSharpApplicationException;
+ break;
+ }
+ SWIG_CSharpSetPendingException(exception_code, msg);
+ }
+}
+%}
+
+#define SWIG_exception(code, msg)\
+{ SWIG_CSharpException(code, msg); return $null; }
+#endif // SWIGCSHARP
+
+#ifdef SWIGLUA
+
+%{
+#define SWIG_exception(a,b)\
+{ lua_pushfstring(L,"%s:%s",#a,b);SWIG_fail; }
+%}
+
+#endif // SWIGLUA
+
+#ifdef SWIGD
+%{
+SWIGINTERN void SWIG_DThrowException(int code, const char *msg) {
+ SWIG_DExceptionCodes exception_code;
+ switch(code) {
+ case SWIG_IndexError:
+ exception_code = SWIG_DNoSuchElementException;
+ break;
+ case SWIG_IOError:
+ exception_code = SWIG_DIOException;
+ break;
+ case SWIG_ValueError:
+ exception_code = SWIG_DIllegalArgumentException;
+ break;
+ case SWIG_NullReferenceError:
+ exception_code = SWIG_DNullReferenceException;
+ break;
+ case SWIG_DivisionByZero:
+ case SWIG_MemoryError:
+ case SWIG_OverflowError:
+ case SWIG_RuntimeError:
+ case SWIG_TypeError:
+ case SWIG_SyntaxError:
+ case SWIG_SystemError:
+ case SWIG_UnknownError:
+ default:
+ exception_code = SWIG_DException;
+ break;
+ }
+ SWIG_DSetPendingException(exception_code, msg);
+}
+%}
+
+#define SWIG_exception(code, msg)\
+{ SWIG_DThrowException(code, msg); return $null; }
+#endif // SWIGD
+
+#ifdef __cplusplus
+/*
+ You can use the SWIG_CATCH_STDEXCEPT macro with the %exception
+ directive as follows:
+
+ %exception {
+ try {
+ $action
+ }
+ catch (my_except& e) {
+ ...
+ }
+ SWIG_CATCH_STDEXCEPT // catch std::exception
+ catch (...) {
+ SWIG_exception(SWIG_UnknownError, "Unknown exception");
+ }
+ }
+*/
+%{
+#include <typeinfo>
+#include <stdexcept>
+%}
+%define SWIG_CATCH_STDEXCEPT
+ /* catching std::exception */
+ catch (std::invalid_argument& e) {
+ SWIG_exception(SWIG_ValueError, e.what() );
+ } catch (std::domain_error& e) {
+ SWIG_exception(SWIG_ValueError, e.what() );
+ } catch (std::overflow_error& e) {
+ SWIG_exception(SWIG_OverflowError, e.what() );
+ } catch (std::out_of_range& e) {
+ SWIG_exception(SWIG_IndexError, e.what() );
+ } catch (std::length_error& e) {
+ SWIG_exception(SWIG_IndexError, e.what() );
+ } catch (std::runtime_error& e) {
+ SWIG_exception(SWIG_RuntimeError, e.what() );
+ } catch (std::bad_cast& e) {
+ SWIG_exception(SWIG_TypeError, e.what() );
+ } catch (std::exception& e) {
+ SWIG_exception(SWIG_SystemError, e.what() );
+ }
+%enddef
+%define SWIG_CATCH_UNKNOWN
+ catch (std::exception& e) {
+ SWIG_exception(SWIG_SystemError, e.what() );
+ }
+ catch (...) {
+ SWIG_exception(SWIG_UnknownError, "unknown exception");
+ }
+%enddef
+
+/* rethrow the unknown exception */
+
+#if defined(SWIGCSHARP) || defined(SWIGD)
+%typemap(throws,noblock=1, canthrow=1) (...) {
+ SWIG_exception(SWIG_RuntimeError,"unknown exception");
+}
+#else
+%typemap(throws,noblock=1) (...) {
+ SWIG_exception(SWIG_RuntimeError,"unknown exception");
+}
+#endif
+
+#endif /* __cplusplus */
+
+/* exception.i ends here */
diff --git a/contrib/tools/swig/Lib/go/.yandex_meta/licenses.list.txt b/contrib/tools/swig/Lib/go/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..8aad0f87d67
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/.yandex_meta/licenses.list.txt
@@ -0,0 +1,916 @@
+====================File: COPYRIGHT====================
+SWIG Copyright and Authors
+--------------------------
+
+Copyright (c) 1995-2023 The SWIG Developers
+Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
+Copyright (c) 1998-2005 University of Chicago.
+Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
+
+Portions also copyrighted by:
+ Network Applied Communication Laboratory, Inc
+ Information-technology Promotion Agency, Japan
+
+Active SWIG Developers:
+ William Fulton ([email protected]) (SWIG core, Java, C#, Windows, Cygwin)
+ Olly Betts ([email protected]) (PHP)
+ Joseph Wang ([email protected]) (R)
+ Momtchil Momtchev ([email protected]) (Javascript Node-API)
+ Simon Marchetto ([email protected]) (Scilab)
+ Zackery Spytz ([email protected]) (OCaml, SWIG core)
+
+Past SWIG developers and major contributors include:
+ Dave Beazley ([email protected]) (SWIG core, Python, Tcl, Perl)
+ Henning Thielemann ([email protected]) (Modula3)
+ Matthias Köppe ([email protected]) (Guile, MzScheme)
+ Luigi Ballabio ([email protected]) (STL wrapping)
+ Mikel Bancroft ([email protected]) (Allegro CL)
+ Surendra Singhi ([email protected]) (CLISP, CFFI)
+ Marcelo Matus ([email protected]) (SWIG core, Python, UTL[python,perl,tcl,ruby])
+ Art Yerkes ([email protected]) (OCaml)
+ Lyle Johnson ([email protected]) (Ruby)
+ Charlie Savage ([email protected]) (Ruby)
+ Thien-Thi Nguyen ([email protected]) (build/test/misc)
+ Richard Palmer ([email protected]) (PHP)
+ Sam Liddicott - Ananova Ltd ([email protected]) (PHP)
+ Tim Hockin - Sun Microsystems ([email protected]) (PHP)
+ Kevin Ruland (PHP)
+ Shibukawa Yoshiki (Japanese Translation)
+ Jason Stewart ([email protected]) (Perl5)
+ Loic Dachary (Perl5)
+ David Fletcher (Perl5)
+ Gary Holt (Perl5)
+ Masaki Fukushima (Ruby)
+ Scott Michel ([email protected]) (Java directors)
+ Tiger Feng ([email protected]) (SWIG core)
+ Mark Rose ([email protected]) (Directors)
+ Jonah Beckford ([email protected]) (CHICKEN)
+ Ahmon Dancy ([email protected]) (Allegro CL)
+ Dirk Gerrits (Allegro CL)
+ Neil Cawse (C#)
+ Harco de Hilster (Java)
+ Alexey Dyachenko ([email protected]) (Tcl)
+ Bob Techentin (Tcl)
+ Martin Froehlich <[email protected]> (Guile)
+ Marcio Luis Teixeira <[email protected]> (Guile)
+ Duncan Temple Lang (R)
+ Miklos Vajna <[email protected]> (PHP directors)
+ Mark Gossage ([email protected]) (Lua)
+ Raman Gopalan ([email protected]) (eLua)
+ Gonzalo Garramuno ([email protected]) (Ruby, Ruby's UTL)
+ John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
+ Baozeng Ding <[email protected]> (Scilab)
+ Ian Lance Taylor (Go)
+ Dmitry Kabak ([email protected]) (Doxygen)
+ Vadim Zeitlin (PCRE, Python, Doxygen)
+ Stefan Zager ([email protected]) (Python)
+ Vincent Couvert (Scilab)
+ Sylvestre Ledru (Scilab)
+ Wolfgang Frisch (Scilab)
+ Oliver Buchtala ([email protected]) (Javascript)
+ Neha Narang ([email protected]) (Javascript)
+ Xavier Delacour ([email protected]) (Octave)
+ David Nadlinger ([email protected]) (D)
+ Leif Middelschulte ([email protected]) (C)
+
+Past contributors include:
+ James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
+ Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
+ Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
+ Klaus Wiederänders, Richard Beare, Hans Oesterholt.
+ (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
+
+Past students:
+ Songyan Feng (Chicago).
+ Xinghua Shi (Chicago).
+ Jing Cao (Chicago).
+ Aquinas Hobor (Chicago).
+
+Historically, the following people contributed to early versions of SWIG.
+Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
+at Los Alamos National Laboratory were the first users. Patrick
+Tullmann at the University of Utah suggested the idea of automatic
+documentation generation. John Schmidt and Kurtis Bleeker at the
+University of Utah tested out the early versions. Chris Johnson
+supported SWIG's developed at the University of Utah. John Buckman,
+Larry Virden, and Tom Schwaller provided valuable input on the first
+releases and improving the portability of SWIG. David Fletcher and
+Gary Holt have provided a great deal of input on improving SWIG's
+Perl5 implementation. Kevin Butler contributed the first Windows NT
+port.
+
+Early bug reports and patches:
+Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
+Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
+Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
+Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
+Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
+Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
+Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
+Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
+Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
+Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
+Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
+Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
+Zhong Ren.
+
+
+
+====================File: LICENSE-GPL====================
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+====================File: LICENSE-UNIVERSITIES====================
+SWIG is distributed under the following terms:
+
+I.
+
+Copyright (c) 1995-1998
+The University of Utah and the Regents of the University of California
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following two paragraphs
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+IN NO EVENT SHALL THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, THE
+UNIVERSITY OF UTAH OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
+PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
+EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, AND THE UNIVERSITY OF UTAH
+SPECIFICALLY DISCLAIM ANY WARRANTIES,INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
+THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+
+II.
+
+This software includes contributions that are Copyright (c) 1998-2005
+University of Chicago.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer. Redistributions
+in binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution. Neither the name of
+the University of Chicago nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF CHICAGO AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+CHICAGO OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+III.
+
+This software includes contributions that are Copyright (c) 2005-2006
+Arizona Board of Regents (University of Arizona).
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following paragraph
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF ARIZONA AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+ARIZONA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+====================LicenseRef-scancode-swig====================
+SWIG is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. See the LICENSE-GPL file for
+the full terms of the GNU General Public license version 3.
+
+Portions of SWIG are also licensed under the terms of the licenses
+in the file LICENSE-UNIVERSITIES. You must observe the terms of
+these licenses, as well as the terms of the GNU General Public License,
+when you distribute SWIG.
+
+The SWIG library and examples, under the Lib and Examples top level
+directories, are distributed under the following terms:
+
+ You may copy, modify, distribute, and make derivative works based on
+ this software, in source code or object code form, without
+ restriction. If you distribute the software to others, you may do
+ so according to the terms of your choice. This software is offered as
+ is, without warranty of any kind.
+
+See the COPYRIGHT file for a list of contributors to SWIG and their
+copyright notices. \ No newline at end of file
diff --git a/contrib/tools/swig/Lib/go/argcargv.i b/contrib/tools/swig/Lib/go/argcargv.i
new file mode 100644
index 00000000000..f2dee2be955
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/argcargv.i
@@ -0,0 +1,62 @@
+/* -------------------------------------------------------------
+ * SWIG library containing argc and argv multi-argument typemaps
+ * ------------------------------------------------------------- */
+
+%typemap(gotype) (int ARGC, char **ARGV) "[]string"
+
+%insert(go_wrapper) %{
+//export cgo_swig_get_string_slice_idx
+func cgo_swig_get_string_slice_idx(s []string, i C.swig_intgo) string {
+ return s[i]
+}
+%}
+
+%{
+extern
+#ifdef __cplusplus
+ "C"
+#endif
+_gostring_ cgo_swig_get_string_slice_idx(_goslice_ s, intgo i);
+%}
+
+%typemap(in) (int ARGC, char **ARGV) {
+ $1_ltype len = ($1_ltype)$input.len;
+ size_t aralloc = (size_t)((len + 1) * sizeof(char *));
+ if (len < 0) {
+ _swig_gopanic("negative array length");
+ }
+ $2 = ($2_ltype) Swig_malloc((int)aralloc);
+ if ($2 == NULL) {
+ _swig_gopanic("fail allocating memory for array");
+ }
+ memset($2, 0, aralloc);
+ $1 = len;
+ {
+ $1_ltype i;
+ for (i = 0; i < len; i++) {
+ char *p;
+ _gostring_ st = cgo_swig_get_string_slice_idx($input, (intgo)i);
+ if (st.n < 0) {
+ _swig_gopanic("string length negative");
+ }
+ p = (char *) Swig_malloc((int)(st.n + 1));
+ if (p == NULL) {
+ _swig_gopanic("fail allocating memory for a string");
+ }
+ memcpy(p, st.p, st.n);
+ p[st.n] = 0;
+ $2[i] = p;
+ }
+ $2[i] = NULL;
+ }
+}
+
+%typemap(freearg) (int ARGC, char **ARGV) {
+ if ($2 != NULL) {
+ $1_ltype i;
+ for (i = 0; i < $1; i++) {
+ Swig_free((void *)$2[i]);
+ }
+ Swig_free((void *)$2);
+ }
+}
diff --git a/contrib/tools/swig/Lib/go/cdata.i b/contrib/tools/swig/Lib/go/cdata.i
new file mode 100644
index 00000000000..77b08ec7a62
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/cdata.i
@@ -0,0 +1,57 @@
+/* -----------------------------------------------------------------------------
+ * cdata.i
+ *
+ * SWIG library file containing macros for manipulating raw C data.
+ * ----------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------
+ * Typemap for passing bytes with length
+ * ------------------------------------------------------------ */
+
+%typemap(gotype) (const void *BYTES, size_t LENGTH) "[]byte"
+%typemap(in) (const void *BYTES, size_t LENGTH) %{
+ $1 = ($1_ltype)$input.array;
+ $2 = ($2_ltype)$input.len;
+%}
+%apply (const void *BYTES, size_t LENGTH) { (void *BYTES, size_t LENGTH) }
+
+%include <typemaps/cdata_begin.swg>
+
+%fragment("cdata", "header") %{
+struct swigcdata {
+ uintgo size;
+ void *data;
+};
+%}
+
+%typemap(gotype) SWIGCDATA "[]byte"
+%typemap(imtype) SWIGCDATA "uint64"
+
+%typemap(out, fragment="cdata") SWIGCDATA(struct swigcdata *swig_out) %{
+ swig_out = (struct swigcdata *)malloc(sizeof(*swig_out));
+ if (swig_out) {
+ swig_out->size = $1.len;
+ swig_out->data = malloc(swig_out->size);
+ if (swig_out->data) {
+ memcpy(swig_out->data, $1.data, swig_out->size);
+ }
+ }
+ $result = *(long long *)(void **)&swig_out;
+%}
+
+%typemap(goout) SWIGCDATA {
+ type swigcdata struct { size int; data uintptr }
+ p := (*swigcdata)(unsafe.Pointer(uintptr($1)))
+ if p == nil || p.data == 0 {
+ $result = nil
+ } else {
+ b := make([]byte, p.size)
+ a := (*[0x7fffffff]byte)(unsafe.Pointer(p.data))[:p.size]
+ copy(b, a)
+ Swig_free(p.data)
+ Swig_free(uintptr(unsafe.Pointer(p)))
+ $result = b
+ }
+}
+
+%include <typemaps/cdata_end.swg>
diff --git a/contrib/tools/swig/Lib/go/director.swg b/contrib/tools/swig/Lib/go/director.swg
new file mode 100644
index 00000000000..103ba22a34e
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/director.swg
@@ -0,0 +1,80 @@
+/* -----------------------------------------------------------------------------
+ * director.swg
+ *
+ * This file contains support for director classes so that Go proxy
+ * methods can be called from C++.
+ * ----------------------------------------------------------------------------- */
+
+#include <exception>
+#include <map>
+
+namespace Swig {
+
+ class DirectorException : public std::exception {
+ };
+}
+
+/* Handle memory management for directors. */
+
+namespace {
+ struct GCItem {
+ virtual ~GCItem() {}
+ };
+
+ struct GCItem_var {
+ GCItem_var(GCItem *item = 0) : _item(item) {
+ }
+
+ GCItem_var& operator=(GCItem *item) {
+ GCItem *tmp = _item;
+ _item = item;
+ delete tmp;
+ return *this;
+ }
+
+ ~GCItem_var() {
+ delete _item;
+ }
+
+ GCItem* operator->() {
+ return _item;
+ }
+
+ private:
+ GCItem *_item;
+ };
+
+ template <typename Type>
+ struct GCItem_T : GCItem {
+ GCItem_T(Type *ptr) : _ptr(ptr) {
+ }
+
+ virtual ~GCItem_T() {
+ delete _ptr;
+ }
+
+ private:
+ Type *_ptr;
+ };
+}
+
+class Swig_memory {
+public:
+ template <typename Type>
+ void swig_acquire_pointer(Type* vptr) {
+ if (vptr) {
+ swig_owner[vptr] = new GCItem_T<Type>(vptr);
+ }
+ }
+private:
+ typedef std::map<void *, GCItem_var> swig_ownership_map;
+ swig_ownership_map swig_owner;
+};
+
+template <typename Type>
+static void swig_acquire_pointer(Swig_memory** pmem, Type* ptr) {
+ if (!pmem) {
+ *pmem = new Swig_memory;
+ }
+ (*pmem)->swig_acquire_pointer(ptr);
+}
diff --git a/contrib/tools/swig/Lib/go/exception.i b/contrib/tools/swig/Lib/go/exception.i
new file mode 100644
index 00000000000..5abd306a4ed
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/exception.i
@@ -0,0 +1,7 @@
+%typemap(throws,noblock=1) (...) {
+ SWIG_exception(SWIG_RuntimeError,"unknown exception");
+}
+
+%insert("runtime") %{
+#define SWIG_exception(code, msg) _swig_gopanic(msg)
+%}
diff --git a/contrib/tools/swig/Lib/go/go.swg b/contrib/tools/swig/Lib/go/go.swg
new file mode 100644
index 00000000000..8f5bb4fcdcb
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/go.swg
@@ -0,0 +1,747 @@
+/* ------------------------------------------------------------
+ * go.swg
+ *
+ * Go configuration module.
+ * ------------------------------------------------------------ */
+
+%include <gostring.swg>
+
+/* Code insertion directives */
+#define %go_import(...) %insert(go_imports) %{__VA_ARGS__%}
+
+/* Basic types */
+
+%typemap(gotype) bool, const bool & "bool"
+%typemap(gotype) char, const char & "byte"
+%typemap(gotype) signed char, const signed char & "int8"
+%typemap(gotype) unsigned char, const unsigned char & "byte"
+%typemap(gotype) short, const short & "int16"
+%typemap(gotype) unsigned short, const unsigned short & "uint16"
+%typemap(gotype) int, const int & "int"
+%typemap(gotype) unsigned int, const unsigned int & "uint"
+%typemap(gotype) long, const long & "int64"
+%typemap(gotype) unsigned long, const unsigned long & "uint64"
+%typemap(gotype) long long, const long long & "int64"
+%typemap(gotype) unsigned long long, const unsigned long long & "uint64"
+%typemap(gotype) float, const float & "float32"
+%typemap(gotype) double, const double & "float64"
+
+%typemap(in) bool,
+ char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ unsigned long long,
+ float,
+ double
+%{ $1 = ($1_ltype)$input; %}
+
+%typemap(in) const bool &,
+ const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long long &,
+ const unsigned long long &,
+ const float &,
+ const double &
+%{ $1 = ($1_ltype)&$input; %}
+
+%typemap(in) const long & ($*1_ltype temp),
+ const unsigned long & ($*1_ltype temp)
+%{ temp = ($*1_ltype)$input;
+ $1 = ($1_ltype)&temp; %}
+
+%typemap(out) bool,
+ char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ unsigned long long,
+ float,
+ double
+%{ $result = $1; %}
+
+%typemap(goout) bool,
+ char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ unsigned long long,
+ float,
+ double
+""
+
+%typemap(out) const bool &,
+ const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long &,
+ const unsigned long &,
+ const long long &,
+ const unsigned long long &,
+ const float &,
+ const double &
+%{ $result = ($*1_ltype)*$1; %}
+
+%typemap(goout) const bool &,
+ const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long &,
+ const unsigned long &,
+ const long long &,
+ const unsigned long long &,
+ const float &,
+ const double &
+""
+
+%typemap(out) void ""
+
+%typemap(goout) void ""
+
+%typemap(directorin) bool,
+ char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ unsigned long long,
+ float,
+ double
+%{ $input = ($1_ltype)$1; %}
+
+%typemap(godirectorin) bool,
+ char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ unsigned long long,
+ float,
+ double
+""
+
+%typemap(directorin) const bool &,
+ const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long &,
+ const unsigned long &,
+ const long long &,
+ const unsigned long long &,
+ const float &,
+ const double &
+%{ $input = ($*1_ltype)$1; %}
+
+%typemap(godirectorin) const bool &,
+ const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long &,
+ const unsigned long &,
+ const long long &,
+ const unsigned long long &,
+ const float &,
+ const double &
+""
+
+%typemap(directorout) bool,
+ char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ unsigned long long,
+ float,
+ double
+%{ $result = ($1_ltype)$input; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) const bool &,
+ const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long &,
+ const unsigned long &,
+ const long long &,
+ const unsigned long long &,
+ const float &,
+ const double &
+%{
+ $result = new $*1_ltype($input);
+ swig_acquire_pointer(&swig_mem, $result);
+%}
+
+/* The size_t type. */
+
+%typemap(gotype) size_t, const size_t & %{int64%}
+
+%typemap(in) size_t
+%{ $1 = (size_t)$input; %}
+
+%typemap(in) const size_t &
+%{ $1 = ($1_ltype)&$input; %}
+
+%typemap(out) size_t
+%{ $result = $1; %}
+
+%typemap(goout) size_t ""
+
+%typemap(out) const size_t &
+%{ $result = ($*1_ltype)*$1; %}
+
+%typemap(goout) const size_t & ""
+
+%typemap(directorin) size_t
+%{ $input = (size_t)$1; %}
+
+%typemap(godirectorin) size_t ""
+
+%typemap(directorin) const size_t &
+%{ $input = ($*1_ltype)$1; %}
+
+%typemap(godirectorin) const size_t & ""
+
+%typemap(directorout) size_t
+%{ $result = ($1_ltype)$input; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) const size_t &
+%{
+ $result = new $*1_ltype($input);
+ swig_acquire_pointer(&swig_mem, $result);
+%}
+
+/* Member pointers. */
+
+%typemap(gotype) SWIGTYPE (CLASS::*)
+%{$gotypename%}
+
+%typemap(in) SWIGTYPE (CLASS::*)
+%{ $1 = *($&1_ltype)$input; %}
+
+%typemap(out) SWIGTYPE (CLASS::*)
+%{
+ struct swig_out_type { intgo size; void* val; } *swig_out;
+ swig_out = (struct swig_out_type*)malloc(sizeof(*swig_out));
+ if (swig_out) {
+ swig_out->size = sizeof($1_ltype);
+ swig_out->val = malloc(swig_out->size);
+ if (swig_out->val) {
+ *($&1_ltype)(swig_out->val) = $1;
+ }
+ }
+ $result = swig_out;
+%}
+
+%typemap(goout) SWIGTYPE (CLASS::*)
+%{
+ {
+ type swig_out_type struct { size int; val uintptr }
+ p := (*swig_out_type)(unsafe.Pointer($1))
+ if p == nil || p.val == 0 {
+ $result = nil
+ } else {
+ m := make([]byte, p.size)
+ a := (*[1024]byte)(unsafe.Pointer(p.val))[:p.size]
+ copy(m, a)
+ Swig_free(p.val)
+ Swig_free(uintptr(unsafe.Pointer(p)))
+ $result = &m[0]
+ }
+ }
+%}
+
+%typemap(directorin) SWIGTYPE (CLASS::*)
+%{ $input = *($&1_ltype)$1; %}
+
+%typemap(godirectorin) SWIGTYPE (CLASS::*) ""
+
+%typemap(directorout) SWIGTYPE (CLASS::*)
+%{
+ $result = new $1_ltype($input);
+ swig_acquire_pointer(&swig_mem, $result);
+%}
+
+/* Pointers. */
+
+/* We can't translate pointers using a typemap, so that is handled in
+ the C++ code. */
+%typemap(gotype) SWIGTYPE *
+%{$gotypename%}
+
+%typemap(in) SWIGTYPE *
+%{ $1 = *($&1_ltype)&$input; %}
+
+%typemap(out) SWIGTYPE *
+%{ *($&1_ltype)&$result = ($1_ltype)$1; %}
+
+%typemap(goout) SWIGTYPE * ""
+
+%typemap(directorin) SWIGTYPE *
+%{ *($&1_ltype)&$input = ($1_ltype)$1; %}
+
+%typemap(godirectorin) SWIGTYPE * ""
+
+%typemap(directorout) SWIGTYPE *
+%{ $result = *($&1_ltype)&$input; %}
+
+/* Pointer references. */
+
+%typemap(gotype) SWIGTYPE *const&
+%{$gotypename%}
+
+%typemap(in) SWIGTYPE *const& ($*1_ltype temp = 0)
+%{
+ temp = *($1_ltype)&$input;
+ $1 = ($1_ltype)&temp;
+%}
+
+%typemap(out) SWIGTYPE *const&
+%{ *($1_ltype)&$result = *$1; %}
+
+%typemap(goout) SWIGTYPE *const& ""
+
+/* References. */
+
+/* Converting a C++ reference to Go has to be handled in the C++
+ code. */
+%typemap(gotype) SWIGTYPE &
+%{$gotypename%}
+
+%typemap(in) SWIGTYPE &
+%{ $1 = *($&1_ltype)&$input; %}
+
+%typemap(out) SWIGTYPE &
+%{ *($&1_ltype)&$result = $1; %}
+
+%typemap(goout) SWIGTYPE & ""
+
+%typemap(directorin) SWIGTYPE &
+%{ $input = ($1_ltype)&$1; %}
+
+%typemap(godirectorin) SWIGTYPE & ""
+
+%typemap(directorout) SWIGTYPE &
+%{ *($&1_ltype)&$result = $input; %}
+
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *const&
+%{ static $*1_ltype swig_temp;
+ swig_temp = *($1_ltype)&$input;
+ $result = &swig_temp; %}
+
+%typemap(gotype) SWIGTYPE &&
+%{$gotypename%}
+
+%typemap(in, fragment="<memory>") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter)
+%{ $1 = *($&1_ltype)&$input;
+rvrdeleter.reset($1); %}
+
+%typemap(out) SWIGTYPE &&
+%{ *($&1_ltype)&$result = $1; %}
+
+%typemap(goout) SWIGTYPE && ""
+
+%typemap(directorin) SWIGTYPE &&
+%{ $input = ($1_ltype)&$1_name; %}
+
+%typemap(godirectorin) SWIGTYPE && ""
+
+%typemap(directorout) SWIGTYPE &&
+%{ *($&1_ltype)&$result = $input; %}
+
+/* C arrays turn into Go pointers. If we know the length we can use a
+ slice. */
+
+%typemap(gotype) SWIGTYPE []
+%{$gotypename%}
+
+%typemap(in) SWIGTYPE []
+%{ $1 = *($&1_ltype)&$input; %}
+
+%typemap(out) SWIGTYPE []
+%{ *($&1_ltype)&$result = $1; %}
+
+%typemap(goout) SWIGTYPE [] ""
+
+%typemap(directorin) SWIGTYPE []
+%{ $input = *($1_ltype)&$1; %}
+
+%typemap(godirectorin) SWIGTYPE [] ""
+
+%typemap(directorout) SWIGTYPE []
+%{ *($&1_ltype)&$result = $input; %}
+
+/* Strings. */
+
+%typemap(gotype)
+ char *, char *&, char[ANY], char[] "string"
+
+/* Needed to avoid confusion with the way the go module handles
+ references. */
+%typemap(gotype) char&, unsigned char& "*byte"
+%typemap(gotype) signed char& "*int8"
+
+%typemap(in)
+ char *, char[ANY], char[]
+%{
+ $1 = ($1_ltype)malloc($input.n + 1);
+ memcpy($1, $input.p, $input.n);
+ $1[$input.n] = '\0';
+%}
+
+%typemap(in) char *& (char *temp)
+%{
+ temp = (char *)malloc($input.n + 1);
+ memcpy(temp, $input.p, $input.n);
+ temp[$input.n] = '\0';
+ $1 = ($1_ltype)&temp;
+%}
+
+%typemap(freearg)
+ char *, char[ANY], char[]
+%{ free($1); %}
+
+%typemap(freearg) char *&
+%{ free(temp$argnum); %}
+
+%typemap(out,fragment="AllocateString")
+ char *, char *&, char[ANY], char[]
+%{ $result = Swig_AllocateString((char*)$1, $1 ? strlen((char*)$1) : 0); %}
+
+%typemap(goout,fragment="CopyString")
+ char *, char *&, char[ANY], char[]
+%{ $result = swigCopyString($1) %}
+
+%typemap(directorin,fragment="AllocateString")
+ char *, char *&, char[ANY], char[]
+%{
+ $input = Swig_AllocateString((char*)$1, $1 ? strlen((char*)$1) : 0);
+%}
+
+%typemap(godirectorin,fragment="CopyString")
+ char *, char *&, char[ANY], char[]
+%{
+ $result = swigCopyString($input)
+%}
+
+%typemap(godirectorout)
+ char *, char *&, char[ANY], char[]
+%{
+ {
+ p := Swig_malloc(len($input) + 1)
+ s := (*[1<<30]byte)(unsafe.Pointer(p))[:len($input) + 1]
+ copy(s, $input)
+ s[len($input)] = 0
+ $result = *(*string)(unsafe.Pointer(&s))
+ }
+%}
+
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG)
+ char *, char *&, char[ANY], char[]
+%{ $result = ($1_ltype)$input.p; %}
+
+/* String & length */
+
+%typemap(gotype) (const char *STRING, size_t LENGTH) "string"
+
+%typemap(in) (const char *STRING, size_t LENGTH)
+%{
+ $1 = ($1_ltype)$input.p;
+ $2 = ($2_ltype)$input.n;
+%}
+
+%typemap(out,fragment="AllocateString") (const char *STRING, size_t LENGTH)
+%{ $result = Swig_AllocateString((char*)$1, (size_t)$2); %}
+
+%typemap(goout,fragment="CopyString") (const char *STRING, size_t LENGTH)
+%{ $result = swigCopyString($1) %}
+
+%typemap(directorin,fragment="AllocateString") (const char *STRING, size_t LENGTH)
+%{ $input = Swig_AllocateString((char*)$1, $2); %}
+
+%typemap(godirectorin,fragment="CopyString") (const char *STRING, size_t LENGTH)
+%{ $result = swigCopyString($input) %}
+
+%typemap(directorout) (const char *STRING, size_t LENGTH)
+%{
+ $1 = ($1_ltype)$input.p;
+ $2 = ($2_ltype)$input.n;
+%}
+%apply (const char *STRING, size_t LENGTH) { (const char *STRING, int LENGTH) }
+%apply (const char *STRING, size_t LENGTH) { (char *STRING, size_t LENGTH) }
+%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
+
+/* The int & type needs to convert to intgo. */
+
+%typemap(gotype) int & "*int"
+
+%typemap(in) int & (int e)
+%{
+ e = (int)*$input;
+ $1 = &e;
+%}
+
+%typemap(out) int &
+%{ $result = new intgo(*$1); %}
+
+%typemap(argout) int &
+%{ *$input = (intgo)e$argnum; %}
+
+%typemap(goout) int & ""
+
+%typemap(directorin) int & (intgo e)
+%{
+ e = (intgo)$1;
+ $input = &e;
+%}
+
+%typemap(godirectorin) int & ""
+
+%typemap(directorout) int &
+%{
+ $*1_ltype f = ($*1_ltype)*$input;
+ $result = ($1_ltype)&f;
+%}
+
+%typemap(directorargout) int &
+%{ $1 = (int)*$input; %}
+
+%typemap(argout) const int & ""
+%typemap(directorargout) const int & ""
+
+/* Enums. We can't do the right thing for enums in typemap(gotype) so
+ we deliberately don't define them. The right thing would be to
+ capitalize the name. This is instead done in go.cxx. */
+
+%typemap(gotype) enum SWIGTYPE
+%{$gotypename%}
+
+%typemap(in) enum SWIGTYPE
+%{ $1 = ($1_ltype)$input; %}
+
+%typemap(out) enum SWIGTYPE
+%{ $result = (intgo)$1; %}
+
+%typemap(goout) enum SWIGTYPE ""
+
+%typemap(directorin) enum SWIGTYPE
+%{ $input = (intgo)$1; %}
+
+%typemap(godirectorin) enum SWIGTYPE ""
+
+%typemap(directorout) enum SWIGTYPE
+%{ $result = ($1_ltype)$input; %}
+
+%typemap(directorin) enum SWIGTYPE & (intgo e)
+%{
+ e = (intgo)$1;
+ $input = ($1_ltype)&e;
+%}
+
+%typemap(godirectorin) enum SWIGTYPE & ""
+
+%typemap(directorout) enum SWIGTYPE &
+%{ $result = $input; %}
+
+/* Arbitrary type. This is a type passed by value in the C/C++ code.
+ We convert it to a pointer for the Go code. Note that all basic
+ types are explicitly handled above. */
+
+%typemap(gotype) SWIGTYPE
+%{$gotypename%}
+
+%typemap(in) SWIGTYPE ($&1_type argp)
+%{
+ argp = ($&1_ltype)$input;
+ if (argp == NULL) {
+ _swig_gopanic("Attempt to dereference null $1_type");
+ }
+ $1 = ($1_ltype)*argp;
+%}
+
+%typemap(out) SWIGTYPE
+#ifdef __cplusplus
+%{ *($&1_ltype*)&$result = new $1_ltype($1); %}
+#else
+{
+ $&1_ltype $1ptr = ($&1_ltype)malloc(sizeof($1_ltype));
+ memmove($1ptr, &$1, sizeof($1_type));
+ *($&1_ltype*)&$result = $1ptr;
+}
+#endif
+
+%typemap(goout) SWIGTYPE ""
+
+%typemap(directorin) SWIGTYPE
+%{ $input = new $1_ltype(SWIG_STD_MOVE($1)); %}
+
+%typemap(godirectorin) SWIGTYPE ""
+
+%typemap(directorout) SWIGTYPE
+%{ $result = *($&1_ltype)$input; %}
+
+/* Exception handling */
+
+%typemap(throws) char *
+%{ _swig_gopanic($1); %}
+
+%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY]
+%{
+ (void)$1;
+ _swig_gopanic("C++ $1_type exception thrown");
+%}
+
+/* Typecheck typemaps. The purpose of these is merely to issue a
+ warning for overloaded C++ functions that cannot be overloaded in
+ Go as more than one C++ type maps to a single Go type. */
+
+%typecheck(SWIG_TYPECHECK_BOOL) /* Go bool */
+ bool,
+ const bool &
+ ""
+
+%typecheck(SWIG_TYPECHECK_CHAR) /* Go byte */
+ char,
+ const char &,
+ unsigned char,
+ const unsigned char &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT8) /* Go int8 */
+ signed char,
+ const signed char &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT16) /* Go int16 */
+ short,
+ const short &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT16) /* Go uint16 */
+ unsigned short,
+ const unsigned short &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT32) /* Go int */
+ int,
+ const int &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT32) /* Go uint */
+ unsigned int,
+ const unsigned int &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT64) /* Go int64 */
+ long,
+ const long &,
+ long long,
+ const long long &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT64) /* Go uint64 */
+ unsigned long,
+ const unsigned long &,
+ unsigned long long,
+ const unsigned long long &
+ ""
+
+%typecheck(SWIG_TYPECHECK_FLOAT) /* Go float32 */
+ float,
+ const float &
+ ""
+
+%typecheck(SWIG_TYPECHECK_DOUBLE) /* Go float64 */
+ double,
+ const double &
+ ""
+
+%typecheck(SWIG_TYPECHECK_STRING) /* Go string */
+ char *,
+ char *&,
+ char[ANY],
+ char [],
+ signed char *,
+ signed char *&,
+ signed char[ANY],
+ signed char [],
+ unsigned char *,
+ unsigned char *&,
+ unsigned char[ANY],
+ unsigned char []
+ ""
+
+%typecheck(SWIG_TYPECHECK_POINTER)
+ SWIGTYPE,
+ SWIGTYPE *,
+ SWIGTYPE &,
+ SWIGTYPE &&,
+ SWIGTYPE *const&,
+ SWIGTYPE [],
+ SWIGTYPE (CLASS::*)
+ ""
+
+%apply SWIGTYPE * { SWIGTYPE *const }
+%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) }
+%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) }
+
+/* Go keywords. */
+%include <gokw.swg>
+
+%include <goruntime.swg>
diff --git a/contrib/tools/swig/Lib/go/gokw.swg b/contrib/tools/swig/Lib/go/gokw.swg
new file mode 100644
index 00000000000..35428300246
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/gokw.swg
@@ -0,0 +1,33 @@
+/* Rename keywords. */
+
+#define GOKW(x) %keywordwarn("'" `x` "' is a Go keyword",rename="X%s") `x`
+#define GOBN(x) %builtinwarn("'" `x` "' conflicts with a built-in name in Go") "::"`x`
+
+GOKW(break);
+GOKW(case);
+GOKW(chan);
+GOKW(const);
+GOKW(continue);
+GOKW(default);
+GOKW(defer);
+GOKW(else);
+GOKW(fallthrough);
+GOKW(for);
+GOKW(func);
+GOKW(go);
+GOKW(goto);
+GOKW(if);
+GOKW(import);
+GOKW(interface);
+GOKW(package);
+GOKW(range);
+GOKW(return);
+GOKW(select);
+GOKW(struct);
+GOKW(switch);
+GOKW(type);
+GOKW(var);
+
+GOBN(map);
+
+#undef GOKW
diff --git a/contrib/tools/swig/Lib/go/goruntime.swg b/contrib/tools/swig/Lib/go/goruntime.swg
new file mode 100644
index 00000000000..7bf083bd3da
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/goruntime.swg
@@ -0,0 +1,217 @@
+/* ------------------------------------------------------------
+ * goruntime.swg
+ *
+ * Go runtime code for the various generated files.
+ * ------------------------------------------------------------ */
+
+%inline %{
+static void Swig_free(void* p) {
+ free(p);
+}
+
+static void* Swig_malloc(int c) {
+ return malloc(c);
+}
+%}
+
+%insert(runtime) %{
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+%}
+
+%insert(cgo_comment_typedefs) %{
+#include <stddef.h>
+#include <stdint.h>
+%}
+
+#if SWIGGO_INTGO_SIZE == 32
+%insert(runtime) %{
+typedef int intgo;
+typedef unsigned int uintgo;
+%}
+%insert(cgo_comment_typedefs) %{
+typedef int intgo;
+typedef unsigned int uintgo;
+%}
+#elif SWIGGO_INTGO_SIZE == 64
+%insert(runtime) %{
+typedef long long intgo;
+typedef unsigned long long uintgo;
+%}
+%insert(cgo_comment_typedefs) %{
+typedef long long intgo;
+typedef unsigned long long uintgo;
+%}
+#else
+%insert(runtime) %{
+typedef ptrdiff_t intgo;
+typedef size_t uintgo;
+%}
+%insert(cgo_comment_typedefs) %{
+typedef ptrdiff_t intgo;
+typedef size_t uintgo;
+%}
+#endif
+
+#ifndef SWIGGO_GCCGO
+// Set the host compiler struct attribute that will be
+// used to match gc's struct layout. For example, on 386 Windows,
+// gcc wants to 8-align int64s, but gc does not.
+// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86,
+// and https://golang.org/issue/5603.
+// See: https://github.com/golang/go/blob/fcbf04f9b93b4cd8addd05c2ed784118eb50a46c/src/cmd/cgo/out.go#L663
+%insert(runtime) %{
+# if !defined(__clang__) && (defined(__i386__) || defined(__x86_64__))
+# define SWIGSTRUCTPACKED __attribute__((__packed__, __gcc_struct__))
+# else
+# define SWIGSTRUCTPACKED __attribute__((__packed__))
+# endif
+%}
+#else
+# define SWIGSTRUCTPACKED
+#endif
+
+%insert(runtime) %{
+
+typedef struct { char *p; intgo n; } _gostring_;
+typedef struct { void* array; intgo len; intgo cap; } _goslice_;
+
+%}
+
+%insert(cgo_comment_typedefs) %{
+
+typedef struct { char *p; intgo n; } _gostring_;
+typedef struct { void* array; intgo len; intgo cap; } _goslice_;
+
+%}
+
+#ifdef SWIGGO_GCCGO
+
+/* Boilerplate for C/C++ code when using gccgo. */
+%insert(runtime) %{
+#define SWIGGO_GCCGO
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void *_cgo_allocate(size_t);
+extern void _cgo_panic(const char *);
+#ifdef __cplusplus
+}
+#endif
+
+#define _swig_goallocate _cgo_allocate
+#define _swig_gopanic _cgo_panic
+%}
+
+#endif
+
+#ifndef SWIGGO_GCCGO
+
+%go_import("unsafe", _ "runtime/cgo")
+
+#else
+
+%go_import("syscall", "unsafe")
+
+%insert(go_header) %{
+
+type _ syscall.Sockaddr
+
+%}
+
+#endif
+
+%insert(go_header) %{
+
+type _ unsafe.Pointer
+
+%}
+
+/* Swig_always_false is used to conditionally assign parameters to
+ Swig_escape_val so that the compiler thinks that they escape. We
+ only assign them if Swig_always_false is true, which it never is.
+ We export the variable so that the compiler doesn't realize that it
+ is never set. */
+%insert(go_header) %{
+var Swig_escape_always_false bool
+var Swig_escape_val interface{}
+%}
+
+/* Function pointers are translated by the code in go.cxx into
+ _swig_fnptr. Member pointers are translated to _swig_memberptr. */
+
+%insert(go_header) %{
+type _swig_fnptr *byte
+type _swig_memberptr *byte
+%}
+
+/* Convert a Go interface value into a C++ pointer. */
+
+%insert(go_header) %{
+func getSwigcptr(v interface { Swigcptr() uintptr }) uintptr {
+ if v == nil {
+ return 0
+ }
+ return v.Swigcptr()
+}
+%}
+
+/* For directors we need C++ to track a Go pointer. Since we can't
+ pass a Go pointer into C++, we use a map to track the pointers on
+ the Go side. */
+
+%go_import("sync")
+
+%insert(go_header) %{
+type _ sync.Mutex
+%}
+
+%insert(go_director) %{
+
+var swigDirectorTrack struct {
+ sync.Mutex
+ m map[int]interface{}
+ c int
+}
+
+func swigDirectorAdd(v interface{}) int {
+ swigDirectorTrack.Lock()
+ defer swigDirectorTrack.Unlock()
+ if swigDirectorTrack.m == nil {
+ swigDirectorTrack.m = make(map[int]interface{})
+ }
+ swigDirectorTrack.c++
+ ret := swigDirectorTrack.c
+ swigDirectorTrack.m[ret] = v
+ return ret
+}
+
+func swigDirectorLookup(c int) interface{} {
+ swigDirectorTrack.Lock()
+ defer swigDirectorTrack.Unlock()
+ ret := swigDirectorTrack.m[c]
+ if ret == nil {
+ panic("C++ director pointer not found (possible use-after-free)")
+ }
+ return ret
+}
+
+func swigDirectorDelete(c int) {
+ swigDirectorTrack.Lock()
+ defer swigDirectorTrack.Unlock()
+ if swigDirectorTrack.m[c] == nil {
+ if c > swigDirectorTrack.c {
+ panic("C++ director pointer invalid (possible memory corruption")
+ } else {
+ panic("C++ director pointer not found (possible use-after-free)")
+ }
+ }
+ delete(swigDirectorTrack.m, c)
+}
+
+%}
diff --git a/contrib/tools/swig/Lib/go/gostring.swg b/contrib/tools/swig/Lib/go/gostring.swg
new file mode 100644
index 00000000000..d9c47d28583
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/gostring.swg
@@ -0,0 +1,29 @@
+/* ------------------------------------------------------------
+ * gostring.swg
+ *
+ * Support for returning strings from C to Go.
+ * ------------------------------------------------------------ */
+
+// C/C++ code to convert a memory buffer into a Go string allocated in
+// C/C++ memory.
+%fragment("AllocateString", "runtime") %{
+static _gostring_ Swig_AllocateString(const char *p, size_t l) {
+ _gostring_ ret;
+ ret.p = (char*)malloc(l);
+ memcpy(ret.p, p, l);
+ ret.n = l;
+ return ret;
+}
+%}
+
+// Go code to convert a string allocated in C++ memory to one
+// allocated in Go memory.
+%fragment("CopyString", "go_runtime") %{
+type swig_gostring struct { p unsafe.Pointer; n int }
+func swigCopyString(s string) string {
+ p := *(*swig_gostring)(unsafe.Pointer(&s))
+ r := string((*[0x7fffffff]byte)(p.p)[:p.n])
+ Swig_free(uintptr(p.p))
+ return r
+}
+%}
diff --git a/contrib/tools/swig/Lib/go/std_array.i b/contrib/tools/swig/Lib/go/std_array.i
new file mode 100644
index 00000000000..36c790e3c1b
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_array.i
@@ -0,0 +1,43 @@
+/* -----------------------------------------------------------------------------
+ * std_array.i
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+namespace std {
+
+ template<class T, size_t N> class array {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ array();
+ array(const array& other);
+
+ size_type size() const;
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void fill(const T& u);
+ %extend {
+ const_reference get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("array index out of range");
+ }
+ void set(int i, const value_type& val) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = val;
+ else
+ throw std::out_of_range("array index out of range");
+ }
+ }
+ };
+}
diff --git a/contrib/tools/swig/Lib/go/std_common.i b/contrib/tools/swig/Lib/go/std_common.i
new file mode 100644
index 00000000000..c010facacd1
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_common.i
@@ -0,0 +1,4 @@
+%include <std_except.i>
+
+%apply size_t { std::size_t };
+%apply const size_t& { const std::size_t& };
diff --git a/contrib/tools/swig/Lib/go/std_deque.i b/contrib/tools/swig/Lib/go/std_deque.i
new file mode 100644
index 00000000000..cb98f6c2fb3
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_deque.i
@@ -0,0 +1 @@
+%include <std/_std_deque.i>
diff --git a/contrib/tools/swig/Lib/go/std_except.i b/contrib/tools/swig/Lib/go/std_except.i
new file mode 100644
index 00000000000..4f021a1264a
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_except.i
@@ -0,0 +1,31 @@
+/* -----------------------------------------------------------------------------
+ * std_except.i
+ *
+ * Typemaps used by the STL wrappers that throw exceptions.
+ * These typemaps are used when methods are declared with an STL exception specification, such as
+ * size_t at() const throw (std::out_of_range);
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <typeinfo>
+#include <stdexcept>
+%}
+
+namespace std
+{
+ %ignore exception;
+ struct exception {};
+}
+
+%typemap(throws) std::bad_cast %{_swig_gopanic($1.what());%}
+%typemap(throws) std::bad_exception %{_swig_gopanic($1.what());%}
+%typemap(throws) std::domain_error %{_swig_gopanic($1.what());%}
+%typemap(throws) std::exception %{_swig_gopanic($1.what());%}
+%typemap(throws) std::invalid_argument %{_swig_gopanic($1.what());%}
+%typemap(throws) std::length_error %{_swig_gopanic($1.what());%}
+%typemap(throws) std::logic_error %{_swig_gopanic($1.what());%}
+%typemap(throws) std::out_of_range %{_swig_gopanic($1.what());%}
+%typemap(throws) std::overflow_error %{_swig_gopanic($1.what());%}
+%typemap(throws) std::range_error %{_swig_gopanic($1.what());%}
+%typemap(throws) std::runtime_error %{_swig_gopanic($1.what());%}
+%typemap(throws) std::underflow_error %{_swig_gopanic($1.what());%}
diff --git a/contrib/tools/swig/Lib/go/std_list.i b/contrib/tools/swig/Lib/go/std_list.i
new file mode 100644
index 00000000000..ff6f700130f
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_list.i
@@ -0,0 +1,41 @@
+/* -----------------------------------------------------------------------------
+ * std_list.i
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <list>
+#include <stdexcept>
+%}
+
+namespace std {
+
+ template<class T>
+ class list {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ list();
+ list(const list& other);
+
+ size_type size() const;
+ bool empty() const;
+ %rename(isEmpty) empty;
+ void clear();
+ void push_front(const value_type& x);
+ void pop_front();
+ void push_back(const value_type& x);
+ void pop_back();
+ void remove(value_type x);
+ void reverse();
+ void unique();
+ void sort();
+ void merge(list& x);
+ };
+
+}
diff --git a/contrib/tools/swig/Lib/go/std_map.i b/contrib/tools/swig/Lib/go/std_map.i
new file mode 100644
index 00000000000..19281ad7d50
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_map.i
@@ -0,0 +1,70 @@
+/* -----------------------------------------------------------------------------
+ * std_map.i
+ *
+ * SWIG typemaps for std::map
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::map
+// ------------------------------------------------------------------------
+
+%{
+#include <map>
+#include <algorithm>
+#include <stdexcept>
+%}
+
+// exported class
+
+namespace std {
+
+ template<class K, class T, class C = std::less<K> > class map {
+ // add typemaps here
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef K key_type;
+ typedef T mapped_type;
+ typedef std::pair< const K, T > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ map();
+ map(const map& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %extend {
+ const T& get(const K& key) throw (std::out_of_range) {
+ std::map< K, T, C >::iterator i = self->find(key);
+ if (i != self->end())
+ return i->second;
+ else
+ throw std::out_of_range("key not found");
+ }
+ void set(const K& key, const T& x) {
+%#ifdef __cpp_lib_map_try_emplace
+ (*self).insert_or_assign(key, x);
+%#else
+ (*self)[key] = x;
+%#endif
+ }
+ void del(const K& key) throw (std::out_of_range) {
+ std::map< K, T, C >::iterator i = self->find(key);
+ if (i != self->end())
+ self->erase(i);
+ else
+ throw std::out_of_range("key not found");
+ }
+ bool has_key(const K& key) {
+ std::map< K, T, C >::iterator i = self->find(key);
+ return i != self->end();
+ }
+ }
+ };
+}
diff --git a/contrib/tools/swig/Lib/go/std_pair.i b/contrib/tools/swig/Lib/go/std_pair.i
new file mode 100644
index 00000000000..732347db583
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_pair.i
@@ -0,0 +1,36 @@
+/* -----------------------------------------------------------------------------
+ * std_pair.i
+ *
+ * SWIG typemaps for std::pair
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <exception.i>
+
+// ------------------------------------------------------------------------
+// std::pair
+// ------------------------------------------------------------------------
+
+%{
+#include <utility>
+%}
+
+namespace std {
+
+ template<class T, class U> struct pair {
+ typedef T first_type;
+ typedef U second_type;
+
+ pair();
+ pair(T first, U second);
+ pair(const pair& other);
+
+ template <class U1, class U2> pair(const pair<U1, U2> &other);
+
+ T first;
+ U second;
+ };
+
+ // add specializations here
+
+}
diff --git a/contrib/tools/swig/Lib/go/std_string.i b/contrib/tools/swig/Lib/go/std_string.i
new file mode 100644
index 00000000000..35b4a5e46b1
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_string.i
@@ -0,0 +1,162 @@
+/* -----------------------------------------------------------------------------
+ * std_string.i
+ *
+ * Typemaps for std::string and const std::string&
+ * These are mapped to a Go string and are passed around by value.
+ *
+ * To use non-const std::string references use the following %apply. Note
+ * that they are passed by value.
+ * %apply const std::string & {std::string &};
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <string>
+%}
+
+namespace std {
+
+%naturalvar string;
+
+class string;
+
+%typemap(gotype) string, const string & "string"
+
+%typemap(in) string
+%{ $1.assign($input.p, $input.n); %}
+
+%typemap(godirectorout) string
+%{
+ {
+ p := Swig_malloc(len($input))
+ s := (*[1<<30]byte)(unsafe.Pointer(p))[:len($input)]
+ copy(s, $input)
+ $result = *(*string)(unsafe.Pointer(&s))
+ }
+%}
+
+%typemap(directorout) string
+%{
+ $result.assign($input.p, $input.n);
+ free($input.p);
+%}
+
+%typemap(out,fragment="AllocateString") string
+%{ $result = Swig_AllocateString($1.data(), $1.length()); %}
+
+%typemap(goout,fragment="CopyString") string
+%{ $result = swigCopyString($1) %}
+
+%typemap(directorin,fragment="AllocateString") string
+%{ $input = Swig_AllocateString($1.data(), $1.length()); %}
+
+%typemap(godirectorin,fragment="CopyString") string
+%{ $result = swigCopyString($input) %}
+
+%typemap(throws) string
+%{ _swig_gopanic($1.c_str()); %}
+
+%typemap(in) const string &
+%{
+ $*1_ltype $1_str($input.p, $input.n);
+ $1 = &$1_str;
+%}
+
+%typemap(godirectorout) const string &
+%{
+ {
+ p := Swig_malloc(len($input))
+ s := (*[1<<30]byte)(unsafe.Pointer(p))[:len($input)]
+ copy(s, $input)
+ $result = *(*string)(unsafe.Pointer(&s))
+ }
+%}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string &
+%{
+ static $*1_ltype $1_str;
+ $1_str.assign($input.p, $input.n);
+ free($input.p);
+ $result = &$1_str;
+%}
+
+%typemap(out,fragment="AllocateString") const string &
+%{ $result = Swig_AllocateString((*$1).data(), (*$1).length()); %}
+
+%typemap(goout,fragment="CopyString") const string &
+%{ $result = swigCopyString($1) %}
+
+%typemap(directorin,fragment="AllocateString") const string &
+%{ $input = Swig_AllocateString($1.data(), $1.length()); %}
+
+%typemap(godirectorin,fragment="CopyString") const string &
+%{ $result = swigCopyString($input) %}
+
+%typemap(throws) const string &
+%{ _swig_gopanic($1.c_str()); %}
+
+
+%typemap(gotype) string * "*string"
+
+%typemap(in) string * (string temp)
+%{
+ if ($input) {
+ temp.assign($input->p, $input->n);
+ $1 = &temp;
+ } else
+ $1 = 0;
+%}
+
+%typemap(godirectorout) string *
+%{
+ if $input != nil {
+ p := Swig_malloc(len(*$input))
+ s := (*[1<<30]byte)(unsafe.Pointer(p))[:len(*$input)]
+ copy(s, *$input)
+ $result = (*string)(unsafe.Pointer(&s))
+ } else {
+ $result = nil
+ }
+%}
+
+%typemap(directorout) string * (string temp)
+%{
+ temp.assign($input->p, $input->n);
+ $result = &temp;
+ free($input.p);
+%}
+
+%typemap(out,fragment="AllocateString") string * (_gostring_ temp)
+%{
+ temp = Swig_AllocateString($1->data(), $1->length());
+ $result = &temp;
+%}
+
+%typemap(goout,fragment="CopyString") string *
+%{ *$result = swigCopyString(*$1) %}
+
+%typemap(directorin,fragment="AllocateString") string * (_gostring_ temp)
+%{
+ if ($1) {
+ temp = Swig_AllocateString($1->data(), $1->length());
+ $input = &temp;
+ } else
+ $input = 0;
+%}
+
+%typemap(godirectorin,fragment="CopyString") string *
+%{ *$result = swigCopyString(*$input); %}
+
+%typemap(argout,fragment="AllocateString") string *
+%{
+ if ($1)
+ *$input = Swig_AllocateString($1->data(), $1->length());
+%}
+
+%typemap(goargout,fragment="CopyString") string *
+%{
+ if $input != nil {
+ *$1 = swigCopyString(*$input)
+ }
+%}
+
+}
diff --git a/contrib/tools/swig/Lib/go/std_vector.i b/contrib/tools/swig/Lib/go/std_vector.i
new file mode 100644
index 00000000000..679c707596e
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/std_vector.i
@@ -0,0 +1,92 @@
+/* -----------------------------------------------------------------------------
+ * std_vector.i
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <vector>
+#include <stdexcept>
+%}
+
+namespace std {
+
+ template<class T> class vector {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ vector();
+ vector(size_type n);
+ vector(const vector& other);
+
+ size_type size() const;
+ size_type capacity() const;
+ void reserve(size_type n);
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ %rename(add) push_back;
+ void push_back(const value_type& x);
+ %extend {
+ const_reference get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ void set(int i, const value_type& val) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = val;
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+ };
+
+ // bool specialization
+ template<> class vector<bool> {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef bool value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef bool const_reference;
+
+ vector();
+ vector(size_type n);
+ vector(const vector& other);
+
+ size_type size() const;
+ size_type capacity() const;
+ void reserve(size_type n);
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ %rename(add) push_back;
+ void push_back(const value_type& x);
+ %extend {
+ bool get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ void set(int i, const value_type& val) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = val;
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+ };
+}
diff --git a/contrib/tools/swig/Lib/go/stl.i b/contrib/tools/swig/Lib/go/stl.i
new file mode 100644
index 00000000000..04f86014f2c
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/stl.i
@@ -0,0 +1,10 @@
+/* -----------------------------------------------------------------------------
+ * stl.i
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <std_string.i>
+%include <std_vector.i>
+%include <std_map.i>
+%include <std_pair.i>
+
diff --git a/contrib/tools/swig/Lib/go/swigmove.i b/contrib/tools/swig/Lib/go/swigmove.i
new file mode 100644
index 00000000000..e1984b6ea26
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/swigmove.i
@@ -0,0 +1,15 @@
+/* -----------------------------------------------------------------------------
+ * swigmove.i
+ *
+ * Input typemaps library for implementing full move semantics when passing
+ * parameters by value.
+ * ----------------------------------------------------------------------------- */
+
+%typemap(in) SWIGTYPE MOVE ($&1_type argp)
+%{
+ argp = ($&1_ltype)$input;
+ if (argp == NULL) {
+ _swig_gopanic("Attempt to dereference null $1_type");
+ }
+ SwigValueWrapper< $1_ltype >::reset($1, argp);
+%}
diff --git a/contrib/tools/swig/Lib/go/typemaps.i b/contrib/tools/swig/Lib/go/typemaps.i
new file mode 100644
index 00000000000..d2e60d37c8b
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/typemaps.i
@@ -0,0 +1,298 @@
+/* -----------------------------------------------------------------------------
+ * typemaps.i
+ *
+ * Pointer and reference handling typemap library
+ *
+ * These mappings provide support for input/output arguments and common
+ * uses for C/C++ pointers and C++ references.
+ * ----------------------------------------------------------------------------- */
+
+/*
+INPUT typemaps
+--------------
+
+These typemaps remap a C pointer or C++ reference to be an "INPUT" value which is
+passed by value instead of reference.
+
+The following typemaps can be applied to turn a pointer or reference into a simple
+input value. That is, instead of passing a pointer or reference to an object,
+you would use a real value instead.
+
+ bool *INPUT, bool &INPUT
+ signed char *INPUT, signed char &INPUT
+ unsigned char *INPUT, unsigned char &INPUT
+ short *INPUT, short &INPUT
+ unsigned short *INPUT, unsigned short &INPUT
+ int *INPUT, int &INPUT
+ unsigned int *INPUT, unsigned int &INPUT
+ long *INPUT, long &INPUT
+ unsigned long *INPUT, unsigned long &INPUT
+ long long *INPUT, long long &INPUT
+ unsigned long long *INPUT, unsigned long long &INPUT
+ float *INPUT, float &INPUT
+ double *INPUT, double &INPUT
+
+To use these, suppose you had a C function like this :
+
+ double fadd(double *a, double *b) {
+ return *a+*b;
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double fadd(double *INPUT, double *INPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INPUT { double *a, double *b };
+ double fadd(double *a, double *b);
+
+In Go you could then use it like this:
+ answer := modulename.Fadd(10.0, 20.0)
+
+There are no char *INPUT typemaps, however you can apply the signed
+char * typemaps instead:
+ %include <typemaps.i>
+ %apply signed char *INPUT {char *input};
+ void f(char *input);
+*/
+
+%define INPUT_TYPEMAP(TYPE, GOTYPE)
+%typemap(gotype) TYPE *INPUT, TYPE &INPUT "GOTYPE"
+
+ %typemap(in) TYPE *INPUT, TYPE &INPUT
+%{ $1 = ($1_ltype)&$input; %}
+
+%typemap(out) TYPE *INPUT, TYPE &INPUT ""
+
+%typemap(goout) TYPE *INPUT, TYPE &INPUT ""
+
+%typemap(freearg) TYPE *INPUT, TYPE &INPUT ""
+
+%typemap(argout) TYPE *INPUT, TYPE &INPUT ""
+
+// %typemap(typecheck) TYPE *INPUT = TYPE;
+// %typemap(typecheck) TYPE &INPUT = TYPE;
+%enddef
+
+INPUT_TYPEMAP(bool, bool);
+INPUT_TYPEMAP(signed char, int8);
+INPUT_TYPEMAP(char, byte);
+INPUT_TYPEMAP(unsigned char, byte);
+INPUT_TYPEMAP(short, int16);
+INPUT_TYPEMAP(unsigned short, uint16);
+INPUT_TYPEMAP(int, int);
+INPUT_TYPEMAP(unsigned int, uint);
+INPUT_TYPEMAP(long, int64);
+INPUT_TYPEMAP(unsigned long, uint64);
+INPUT_TYPEMAP(long long, int64);
+INPUT_TYPEMAP(unsigned long long, uint64);
+INPUT_TYPEMAP(float, float32);
+INPUT_TYPEMAP(double, float64);
+
+#undef INPUT_TYPEMAP
+
+// OUTPUT typemaps. These typemaps are used for parameters that
+// are output only. An array replaces the c pointer or reference parameter.
+// The output value is returned in this array passed in.
+
+/*
+OUTPUT typemaps
+---------------
+
+The following typemaps can be applied to turn a pointer or reference
+into an "output" value. When calling a function, no input value would
+be given for a parameter, but an output value would be returned. This
+works by a Go slice being passed as a parameter where a c pointer or
+reference is required. As with any Go function, the array is passed
+by reference so that any modifications to the array will be picked up
+in the calling function. Note that the array passed in MUST have at
+least one element, but as the c function does not require any input,
+the value can be set to anything.
+
+ bool *OUTPUT, bool &OUTPUT
+ signed char *OUTPUT, signed char &OUTPUT
+ unsigned char *OUTPUT, unsigned char &OUTPUT
+ short *OUTPUT, short &OUTPUT
+ unsigned short *OUTPUT, unsigned short &OUTPUT
+ int *OUTPUT, int &OUTPUT
+ unsigned int *OUTPUT, unsigned int &OUTPUT
+ long *OUTPUT, long &OUTPUT
+ unsigned long *OUTPUT, unsigned long &OUTPUT
+ long long *OUTPUT, long long &OUTPUT
+ unsigned long long *OUTPUT, unsigned long long &OUTPUT
+ float *OUTPUT, float &OUTPUT
+ double *OUTPUT, double &OUTPUT
+
+For example, suppose you were trying to wrap the modf() function in the
+C math library which splits x into integral and fractional parts (and
+returns the integer part in one of its parameters):
+
+ double modf(double x, double *ip);
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double modf(double x, double *OUTPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *OUTPUT { double *ip };
+ double modf(double x, double *ip);
+
+The Go output of the function would be the function return value and the
+value in the single element array. In Go you would use it like this:
+
+ ptr := []float64{0.0}
+ fraction := modulename.Modf(5.0,ptr)
+
+There are no char *OUTPUT typemaps, however you can apply the signed
+char * typemaps instead:
+ %include <typemaps.i>
+ %apply signed char *OUTPUT {char *output};
+ void f(char *output);
+*/
+
+%define OUTPUT_TYPEMAP(TYPE, GOTYPE)
+%typemap(gotype) TYPE *OUTPUT, TYPE &OUTPUT %{[]GOTYPE%}
+
+%typemap(in) TYPE *OUTPUT($*1_ltype temp), TYPE &OUTPUT($*1_ltype temp)
+{
+ if ($input.len == 0) {
+ _swig_gopanic("array must contain at least 1 element");
+ }
+ $1 = &temp;
+}
+
+%typemap(out) TYPE *OUTPUT, TYPE &OUTPUT ""
+
+%typemap(goout) TYPE *INPUT, TYPE &INPUT ""
+
+%typemap(freearg) TYPE *OUTPUT, TYPE &OUTPUT ""
+
+%typemap(argout) TYPE *OUTPUT, TYPE &OUTPUT
+{
+ TYPE* a = (TYPE *) $input.array;
+ a[0] = temp$argnum;
+}
+
+%enddef
+
+OUTPUT_TYPEMAP(bool, bool);
+OUTPUT_TYPEMAP(signed char, int8);
+OUTPUT_TYPEMAP(char, byte);
+OUTPUT_TYPEMAP(unsigned char, byte);
+OUTPUT_TYPEMAP(short, int16);
+OUTPUT_TYPEMAP(unsigned short, uint16);
+OUTPUT_TYPEMAP(int, int);
+OUTPUT_TYPEMAP(unsigned int, uint);
+OUTPUT_TYPEMAP(long, int64);
+OUTPUT_TYPEMAP(unsigned long, uint64);
+OUTPUT_TYPEMAP(long long, int64);
+OUTPUT_TYPEMAP(unsigned long long, uint64);
+OUTPUT_TYPEMAP(float, float32);
+OUTPUT_TYPEMAP(double, float64);
+
+#undef OUTPUT_TYPEMAP
+
+/*
+INOUT typemaps
+--------------
+
+Mappings for a parameter that is both an input and an output parameter
+
+The following typemaps can be applied to make a function parameter both
+an input and output value. This combines the behavior of both the
+"INPUT" and "OUTPUT" typemaps described earlier. Output values are
+returned as an element in a Go slice.
+
+ bool *INOUT, bool &INOUT
+ signed char *INOUT, signed char &INOUT
+ unsigned char *INOUT, unsigned char &INOUT
+ short *INOUT, short &INOUT
+ unsigned short *INOUT, unsigned short &INOUT
+ int *INOUT, int &INOUT
+ unsigned int *INOUT, unsigned int &INOUT
+ long *INOUT, long &INOUT
+ unsigned long *INOUT, unsigned long &INOUT
+ long long *INOUT, long long &INOUT
+ unsigned long long *INOUT, unsigned long long &INOUT
+ float *INOUT, float &INOUT
+ double *INOUT, double &INOUT
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ void neg(double *INOUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INOUT { double *x };
+ void neg(double *x);
+
+This works similarly to C in that the mapping directly modifies the
+input value - the input must be an array with a minimum of one element.
+The element in the array is the input and the output is the element in
+the array.
+
+ x := []float64{5.0}
+ Neg(x);
+
+The implementation of the OUTPUT and INOUT typemaps is different to
+other languages in that other languages will return the output value
+as part of the function return value. This difference is due to Go
+being a typed language.
+
+There are no char *INOUT typemaps, however you can apply the signed
+char * typemaps instead:
+ %include <typemaps.i>
+ %apply signed char *INOUT {char *inout};
+ void f(char *inout);
+*/
+
+%define INOUT_TYPEMAP(TYPE, GOTYPE)
+%typemap(gotype) TYPE *INOUT, TYPE &INOUT %{[]GOTYPE%}
+
+%typemap(in) TYPE *INOUT, TYPE &INOUT {
+ if ($input.len == 0) {
+ _swig_gopanic("array must contain at least 1 element");
+ }
+ $1 = ($1_ltype) $input.array;
+}
+
+%typemap(out) TYPE *INOUT, TYPE &INOUT ""
+
+%typemap(goout) TYPE *INOUT, TYPE &INOUT ""
+
+%typemap(freearg) TYPE *INOUT, TYPE &INOUT ""
+
+%typemap(argout) TYPE *INOUT, TYPE &INOUT ""
+
+%enddef
+
+INOUT_TYPEMAP(bool, bool);
+INOUT_TYPEMAP(signed char, int8);
+INOUT_TYPEMAP(char, byte);
+INOUT_TYPEMAP(unsigned char, byte);
+INOUT_TYPEMAP(short, int16);
+INOUT_TYPEMAP(unsigned short, uint16);
+INOUT_TYPEMAP(int, int);
+INOUT_TYPEMAP(unsigned int, uint);
+INOUT_TYPEMAP(long, int64);
+INOUT_TYPEMAP(unsigned long, uint64);
+INOUT_TYPEMAP(long long, int64);
+INOUT_TYPEMAP(unsigned long long, uint64);
+INOUT_TYPEMAP(float, float32);
+INOUT_TYPEMAP(double, float64);
+
+#undef INOUT_TYPEMAP
diff --git a/contrib/tools/swig/Lib/go/ya.make b/contrib/tools/swig/Lib/go/ya.make
new file mode 100644
index 00000000000..21a9b3ed30a
--- /dev/null
+++ b/contrib/tools/swig/Lib/go/ya.make
@@ -0,0 +1,24 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+LICENSE(LicenseRef-scancode-swig)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+SUBSCRIBER(g:cpp-contrib)
+
+VERSION(4.3.1)
+
+ORIGINAL_SOURCE(https://github.com/swig/swig/archive/v4.3.1.tar.gz)
+
+ADDINCL(
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib/go
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib
+)
+
+END()
diff --git a/contrib/tools/swig/Lib/intrusive_ptr.i b/contrib/tools/swig/Lib/intrusive_ptr.i
new file mode 100644
index 00000000000..a4e8df0aad8
--- /dev/null
+++ b/contrib/tools/swig/Lib/intrusive_ptr.i
@@ -0,0 +1,58 @@
+// Allow for different namespaces for shared_ptr / intrusive_ptr - they could be boost or std or std::tr1
+// For example for std::tr1, use:
+// #define SWIG_SHARED_PTR_NAMESPACE std
+// #define SWIG_SHARED_PTR_SUBNAMESPACE tr1
+// #define SWIG_INTRUSIVE_PTR_NAMESPACE boost
+// #define SWIG_INTRUSIVE_PTR_SUBNAMESPACE
+
+#if !defined(SWIG_INTRUSIVE_PTR_NAMESPACE)
+# define SWIG_INTRUSIVE_PTR_NAMESPACE boost
+#endif
+
+#if defined(SWIG_INTRUSIVE_PTR_SUBNAMESPACE)
+# define SWIG_INTRUSIVE_PTR_QNAMESPACE SWIG_INTRUSIVE_PTR_NAMESPACE::SWIG_INTRUSIVE_PTR_SUBNAMESPACE
+#else
+# define SWIG_INTRUSIVE_PTR_QNAMESPACE SWIG_INTRUSIVE_PTR_NAMESPACE
+#endif
+
+namespace SWIG_INTRUSIVE_PTR_NAMESPACE {
+#if defined(SWIG_INTRUSIVE_PTR_SUBNAMESPACE)
+ namespace SWIG_INTRUSIVE_PTR_SUBNAMESPACE {
+#endif
+ template <class T> class intrusive_ptr {
+ };
+#if defined(SWIG_INTRUSIVE_PTR_SUBNAMESPACE)
+ }
+#endif
+}
+
+%fragment("SWIG_intrusive_deleter", "header") {
+template<class T> struct SWIG_intrusive_deleter {
+ void operator()(T *p) {
+ if (p)
+ intrusive_ptr_release(p);
+ }
+};
+}
+
+%fragment("SWIG_null_deleter", "header") {
+struct SWIG_null_deleter {
+ void operator() (void const *) const {
+ }
+};
+%#define SWIG_NO_NULL_DELETER_0 , SWIG_null_deleter()
+%#define SWIG_NO_NULL_DELETER_1
+}
+
+// Main user macro for defining intrusive_ptr typemaps for both const and non-const pointer types
+%define %intrusive_ptr(TYPE...)
+%feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > }
+SWIG_INTRUSIVE_PTR_TYPEMAPS(, TYPE)
+SWIG_INTRUSIVE_PTR_TYPEMAPS(const, TYPE)
+%enddef
+
+%define %intrusive_ptr_no_wrap(TYPE...)
+%feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > }
+SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(, TYPE)
+SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(const, TYPE)
+%enddef
diff --git a/contrib/tools/swig/Lib/inttypes.i b/contrib/tools/swig/Lib/inttypes.i
new file mode 100644
index 00000000000..f5a09f0bb80
--- /dev/null
+++ b/contrib/tools/swig/Lib/inttypes.i
@@ -0,0 +1,60 @@
+/* -----------------------------------------------------------------------------
+ * inttypes.i
+ *
+ * SWIG library file for ISO C99 types: 7.8 Format conversion of integer types <inttypes.h>
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <inttypes.h>
+%}
+
+%include <stdint.i>
+%include <wchar.i>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SWIGWORDSIZE64
+
+ /* We have to define the `uintmax_t' type using `ldiv_t'. */
+ typedef struct
+ {
+ long int quot; /* Quotient. */
+ long int rem; /* Remainder. */
+ } imaxdiv_t;
+
+#else
+
+ /* We have to define the `uintmax_t' type using `lldiv_t'. */
+ typedef struct
+ {
+ long long int quot; /* Quotient. */
+ long long int rem; /* Remainder. */
+ } imaxdiv_t;
+
+#endif
+
+ /* Compute absolute value of N. */
+ extern intmax_t imaxabs (intmax_t n);
+
+ /* Return the `imaxdiv_t' representation of the value of NUMER over DENOM. */
+ extern imaxdiv_t imaxdiv (intmax_t numer, intmax_t denom);
+
+#ifdef SWIG_WCHAR
+ /* Like `wcstol' but convert to `intmax_t'. */
+ extern intmax_t wcstoimax (const wchar_t *nptr, wchar_t **endptr, int base);
+
+ /* Like `wcstoul' but convert to `uintmax_t'. */
+ extern uintmax_t wcstoumax (const wchar_t *nptr, wchar_t ** endptr, int base);
+#endif
+
+ /* Like `strtol' but convert to `intmax_t'. */
+ extern intmax_t strtoimax (const char *nptr, char **endptr, int base);
+
+ /* Like `strtoul' but convert to `uintmax_t'. */
+ extern uintmax_t strtoumax (const char *nptr, char **endptr,int base);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/tools/swig/Lib/java/.yandex_meta/licenses.list.txt b/contrib/tools/swig/Lib/java/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..8aad0f87d67
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/.yandex_meta/licenses.list.txt
@@ -0,0 +1,916 @@
+====================File: COPYRIGHT====================
+SWIG Copyright and Authors
+--------------------------
+
+Copyright (c) 1995-2023 The SWIG Developers
+Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
+Copyright (c) 1998-2005 University of Chicago.
+Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
+
+Portions also copyrighted by:
+ Network Applied Communication Laboratory, Inc
+ Information-technology Promotion Agency, Japan
+
+Active SWIG Developers:
+ William Fulton ([email protected]) (SWIG core, Java, C#, Windows, Cygwin)
+ Olly Betts ([email protected]) (PHP)
+ Joseph Wang ([email protected]) (R)
+ Momtchil Momtchev ([email protected]) (Javascript Node-API)
+ Simon Marchetto ([email protected]) (Scilab)
+ Zackery Spytz ([email protected]) (OCaml, SWIG core)
+
+Past SWIG developers and major contributors include:
+ Dave Beazley ([email protected]) (SWIG core, Python, Tcl, Perl)
+ Henning Thielemann ([email protected]) (Modula3)
+ Matthias Köppe ([email protected]) (Guile, MzScheme)
+ Luigi Ballabio ([email protected]) (STL wrapping)
+ Mikel Bancroft ([email protected]) (Allegro CL)
+ Surendra Singhi ([email protected]) (CLISP, CFFI)
+ Marcelo Matus ([email protected]) (SWIG core, Python, UTL[python,perl,tcl,ruby])
+ Art Yerkes ([email protected]) (OCaml)
+ Lyle Johnson ([email protected]) (Ruby)
+ Charlie Savage ([email protected]) (Ruby)
+ Thien-Thi Nguyen ([email protected]) (build/test/misc)
+ Richard Palmer ([email protected]) (PHP)
+ Sam Liddicott - Ananova Ltd ([email protected]) (PHP)
+ Tim Hockin - Sun Microsystems ([email protected]) (PHP)
+ Kevin Ruland (PHP)
+ Shibukawa Yoshiki (Japanese Translation)
+ Jason Stewart ([email protected]) (Perl5)
+ Loic Dachary (Perl5)
+ David Fletcher (Perl5)
+ Gary Holt (Perl5)
+ Masaki Fukushima (Ruby)
+ Scott Michel ([email protected]) (Java directors)
+ Tiger Feng ([email protected]) (SWIG core)
+ Mark Rose ([email protected]) (Directors)
+ Jonah Beckford ([email protected]) (CHICKEN)
+ Ahmon Dancy ([email protected]) (Allegro CL)
+ Dirk Gerrits (Allegro CL)
+ Neil Cawse (C#)
+ Harco de Hilster (Java)
+ Alexey Dyachenko ([email protected]) (Tcl)
+ Bob Techentin (Tcl)
+ Martin Froehlich <[email protected]> (Guile)
+ Marcio Luis Teixeira <[email protected]> (Guile)
+ Duncan Temple Lang (R)
+ Miklos Vajna <[email protected]> (PHP directors)
+ Mark Gossage ([email protected]) (Lua)
+ Raman Gopalan ([email protected]) (eLua)
+ Gonzalo Garramuno ([email protected]) (Ruby, Ruby's UTL)
+ John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
+ Baozeng Ding <[email protected]> (Scilab)
+ Ian Lance Taylor (Go)
+ Dmitry Kabak ([email protected]) (Doxygen)
+ Vadim Zeitlin (PCRE, Python, Doxygen)
+ Stefan Zager ([email protected]) (Python)
+ Vincent Couvert (Scilab)
+ Sylvestre Ledru (Scilab)
+ Wolfgang Frisch (Scilab)
+ Oliver Buchtala ([email protected]) (Javascript)
+ Neha Narang ([email protected]) (Javascript)
+ Xavier Delacour ([email protected]) (Octave)
+ David Nadlinger ([email protected]) (D)
+ Leif Middelschulte ([email protected]) (C)
+
+Past contributors include:
+ James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
+ Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
+ Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
+ Klaus Wiederänders, Richard Beare, Hans Oesterholt.
+ (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
+
+Past students:
+ Songyan Feng (Chicago).
+ Xinghua Shi (Chicago).
+ Jing Cao (Chicago).
+ Aquinas Hobor (Chicago).
+
+Historically, the following people contributed to early versions of SWIG.
+Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
+at Los Alamos National Laboratory were the first users. Patrick
+Tullmann at the University of Utah suggested the idea of automatic
+documentation generation. John Schmidt and Kurtis Bleeker at the
+University of Utah tested out the early versions. Chris Johnson
+supported SWIG's developed at the University of Utah. John Buckman,
+Larry Virden, and Tom Schwaller provided valuable input on the first
+releases and improving the portability of SWIG. David Fletcher and
+Gary Holt have provided a great deal of input on improving SWIG's
+Perl5 implementation. Kevin Butler contributed the first Windows NT
+port.
+
+Early bug reports and patches:
+Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
+Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
+Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
+Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
+Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
+Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
+Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
+Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
+Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
+Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
+Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
+Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
+Zhong Ren.
+
+
+
+====================File: LICENSE-GPL====================
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+====================File: LICENSE-UNIVERSITIES====================
+SWIG is distributed under the following terms:
+
+I.
+
+Copyright (c) 1995-1998
+The University of Utah and the Regents of the University of California
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following two paragraphs
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+IN NO EVENT SHALL THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, THE
+UNIVERSITY OF UTAH OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
+PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
+EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, AND THE UNIVERSITY OF UTAH
+SPECIFICALLY DISCLAIM ANY WARRANTIES,INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
+THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+
+II.
+
+This software includes contributions that are Copyright (c) 1998-2005
+University of Chicago.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer. Redistributions
+in binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution. Neither the name of
+the University of Chicago nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF CHICAGO AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+CHICAGO OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+III.
+
+This software includes contributions that are Copyright (c) 2005-2006
+Arizona Board of Regents (University of Arizona).
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following paragraph
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF ARIZONA AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+ARIZONA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+====================LicenseRef-scancode-swig====================
+SWIG is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. See the LICENSE-GPL file for
+the full terms of the GNU General Public license version 3.
+
+Portions of SWIG are also licensed under the terms of the licenses
+in the file LICENSE-UNIVERSITIES. You must observe the terms of
+these licenses, as well as the terms of the GNU General Public License,
+when you distribute SWIG.
+
+The SWIG library and examples, under the Lib and Examples top level
+directories, are distributed under the following terms:
+
+ You may copy, modify, distribute, and make derivative works based on
+ this software, in source code or object code form, without
+ restriction. If you distribute the software to others, you may do
+ so according to the terms of your choice. This software is offered as
+ is, without warranty of any kind.
+
+See the COPYRIGHT file for a list of contributors to SWIG and their
+copyright notices. \ No newline at end of file
diff --git a/contrib/tools/swig/Lib/java/argcargv.i b/contrib/tools/swig/Lib/java/argcargv.i
new file mode 100644
index 00000000000..cf0f85ba8b8
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/argcargv.i
@@ -0,0 +1,36 @@
+/* -------------------------------------------------------------
+ * SWIG library containing argc and argv multi-argument typemaps
+ * ------------------------------------------------------------- */
+
+%typemap(jni) (int ARGC, char **ARGV) "jobjectArray"
+%typemap(jtype) (int ARGC, char **ARGV) "String[]"
+%typemap(jstype) (int ARGC, char **ARGV) "String[]"
+
+%typemap(in) (int ARGC, char **ARGV) {
+ $1_ltype i, len;
+ if ($input == (jobjectArray)0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array");
+ return $null;
+ }
+ len = ($1_ltype)JCALL1(GetArrayLength, jenv, $input);
+ if (len < 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "array length negative");
+ return $null;
+ }
+ $2 = ($2_ltype) malloc((len+1)*sizeof($*2_ltype));
+ if ($2 == NULL) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "memory allocation failed");
+ return $null;
+ }
+ $1 = len;
+ for (i = 0; i < len; i++) {
+ jstring j_string = (jstring)JCALL2(GetObjectArrayElement, jenv, $input, (jsize)i);
+ const char *c_string = JCALL2(GetStringUTFChars, jenv, j_string, 0);
+ $2[i] = ($*2_ltype)c_string;
+ }
+ $2[i] = NULL;
+}
+
+%typemap(freearg) (int ARGC, char **ARGV) {
+ free((void *)$2);
+}
diff --git a/contrib/tools/swig/Lib/java/arrays_java.i b/contrib/tools/swig/Lib/java/arrays_java.i
new file mode 100644
index 00000000000..a8f5180c402
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/arrays_java.i
@@ -0,0 +1,398 @@
+/* -----------------------------------------------------------------------------
+ * arrays_java.i
+ *
+ * These typemaps give more natural support for arrays. The typemaps are not efficient
+ * as there is a lot of copying of the array values whenever the array is passed to C/C++
+ * from Java and vice versa. The Java array is expected to be the same size as the C array.
+ * An exception is thrown if they are not.
+ *
+ * Example usage:
+ * Wrapping:
+ *
+ * %include <arrays_java.i>
+ * %inline %{
+ * short FiddleSticks[3];
+ * %}
+ *
+ * Use from Java like this:
+ *
+ * short[] fs = new short[] {10, 11, 12};
+ * example.setFiddleSticks(fs);
+ * fs = example.getFiddleSticks();
+ * ----------------------------------------------------------------------------- */
+
+/* Primitive array support is a combination of SWIG macros and functions in order to reduce
+ * code bloat and aid maintainability. The SWIG preprocessor expands the macros into functions
+ * for inclusion in the generated code. */
+
+/* Array support functions declarations macro */
+%define JAVA_ARRAYS_DECL(CTYPE, JNITYPE, JAVATYPE, JFUNCNAME)
+%{
+static int SWIG_JavaArrayIn##JFUNCNAME (JNIEnv *jenv, JNITYPE **jarr, CTYPE **carr, JNITYPE##Array input);
+static void SWIG_JavaArrayArgout##JFUNCNAME (JNIEnv *jenv, JNITYPE *jarr, CTYPE *carr, JNITYPE##Array input);
+static JNITYPE##Array SWIG_JavaArrayOut##JFUNCNAME (JNIEnv *jenv, CTYPE *result, jsize sz);
+%}
+%enddef
+
+/* Array support functions macro */
+%define JAVA_ARRAYS_IMPL(CTYPE, JNITYPE, JAVATYPE, JFUNCNAME)
+%{
+/* CTYPE[] support */
+static int SWIG_JavaArrayIn##JFUNCNAME (JNIEnv *jenv, JNITYPE **jarr, CTYPE **carr, JNITYPE##Array input) {
+ int i;
+ jsize sz;
+ if (!input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array");
+ return 0;
+ }
+ sz = JCALL1(GetArrayLength, jenv, input);
+ *jarr = JCALL2(Get##JAVATYPE##ArrayElements, jenv, input, 0);
+ if (!*jarr)
+ return 0; %}
+#ifdef __cplusplus
+%{ *carr = new CTYPE[sz]; %}
+#else
+%{ *carr = (CTYPE*) malloc(sz * sizeof(CTYPE)); %}
+#endif
+%{ if (!*carr) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed");
+ return 0;
+ }
+ for (i=0; i<sz; i++)
+ JAVA_TYPEMAP_ARRAY_ELEMENT_ASSIGN(CTYPE)
+ return 1;
+}
+
+static void SWIG_JavaArrayArgout##JFUNCNAME (JNIEnv *jenv, JNITYPE *jarr, CTYPE *carr, JNITYPE##Array input) {
+ int i;
+ jsize sz = JCALL1(GetArrayLength, jenv, input);
+ for (i=0; i<sz; i++)
+ jarr[i] = (JNITYPE)carr[i];
+ JCALL3(Release##JAVATYPE##ArrayElements, jenv, input, jarr, 0);
+}
+
+static JNITYPE##Array SWIG_JavaArrayOut##JFUNCNAME (JNIEnv *jenv, CTYPE *result, jsize sz) {
+ JNITYPE *arr;
+ int i;
+ JNITYPE##Array jresult = JCALL1(New##JAVATYPE##Array, jenv, sz);
+ if (!jresult)
+ return NULL;
+ arr = JCALL2(Get##JAVATYPE##ArrayElements, jenv, jresult, 0);
+ if (!arr)
+ return NULL;
+ for (i=0; i<sz; i++)
+ arr[i] = (JNITYPE)result[i];
+ JCALL3(Release##JAVATYPE##ArrayElements, jenv, jresult, arr, 0);
+ return jresult;
+}
+%}
+%enddef
+
+%{
+#if defined(SWIG_NOINCLUDE) || defined(SWIG_NOARRAYS)
+%}
+
+#ifdef __cplusplus
+JAVA_ARRAYS_DECL(bool, jboolean, Boolean, Bool) /* bool[] */
+#endif
+
+JAVA_ARRAYS_DECL(signed char, jbyte, Byte, Schar) /* signed char[] */
+JAVA_ARRAYS_DECL(unsigned char, jshort, Short, Uchar) /* unsigned char[] */
+JAVA_ARRAYS_DECL(short, jshort, Short, Short) /* short[] */
+JAVA_ARRAYS_DECL(unsigned short, jint, Int, Ushort) /* unsigned short[] */
+JAVA_ARRAYS_DECL(int, jint, Int, Int) /* int[] */
+JAVA_ARRAYS_DECL(unsigned int, jlong, Long, Uint) /* unsigned int[] */
+JAVA_ARRAYS_DECL(long, jint, Int, Long) /* long[] */
+JAVA_ARRAYS_DECL(unsigned long, jlong, Long, Ulong) /* unsigned long[] */
+JAVA_ARRAYS_DECL(long long, jlong, Long, Longlong) /* long long[] */
+JAVA_ARRAYS_DECL(float, jfloat, Float, Float) /* float[] */
+JAVA_ARRAYS_DECL(double, jdouble, Double, Double) /* double[] */
+
+%{
+#else
+%}
+
+#ifdef __cplusplus
+/* Bool array element assignment different to other types to keep Visual C++ quiet */
+#define JAVA_TYPEMAP_ARRAY_ELEMENT_ASSIGN(CTYPE) (*carr)[i] = ((*jarr)[i] != 0);
+JAVA_ARRAYS_IMPL(bool, jboolean, Boolean, Bool) /* bool[] */
+#undef JAVA_TYPEMAP_ARRAY_ELEMENT_ASSIGN
+#endif
+
+#define JAVA_TYPEMAP_ARRAY_ELEMENT_ASSIGN(CTYPE) (*carr)[i] = (CTYPE)(*jarr)[i];
+JAVA_ARRAYS_IMPL(signed char, jbyte, Byte, Schar) /* signed char[] */
+JAVA_ARRAYS_IMPL(unsigned char, jshort, Short, Uchar) /* unsigned char[] */
+JAVA_ARRAYS_IMPL(short, jshort, Short, Short) /* short[] */
+JAVA_ARRAYS_IMPL(unsigned short, jint, Int, Ushort) /* unsigned short[] */
+JAVA_ARRAYS_IMPL(int, jint, Int, Int) /* int[] */
+JAVA_ARRAYS_IMPL(unsigned int, jlong, Long, Uint) /* unsigned int[] */
+JAVA_ARRAYS_IMPL(long, jint, Int, Long) /* long[] */
+JAVA_ARRAYS_IMPL(unsigned long, jlong, Long, Ulong) /* unsigned long[] */
+JAVA_ARRAYS_IMPL(long long, jlong, Long, Longlong) /* long long[] */
+JAVA_ARRAYS_IMPL(float, jfloat, Float, Float) /* float[] */
+JAVA_ARRAYS_IMPL(double, jdouble, Double, Double) /* double[] */
+
+%{
+#endif
+%}
+
+
+/* The rest of this file has the array typemaps */
+
+/* Arrays of primitive types use the following macro. The array typemaps use support functions. */
+%define JAVA_ARRAYS_TYPEMAPS(CTYPE, JTYPE, JNITYPE, JFUNCNAME, JNIDESC)
+
+%typemap(jni) CTYPE[ANY], CTYPE[] %{JNITYPE##Array%}
+%typemap(jtype) CTYPE[ANY], CTYPE[] %{JTYPE[]%}
+%typemap(jstype) CTYPE[ANY], CTYPE[] %{JTYPE[]%}
+
+%typemap(in) CTYPE[] (JNITYPE *jarr)
+%{ if (!SWIG_JavaArrayIn##JFUNCNAME(jenv, &jarr, ($&1_ltype)&$1, $input)) return $null; %}
+%typemap(in) CTYPE[ANY] (JNITYPE *jarr)
+%{ if ($input && JCALL1(GetArrayLength, jenv, $input) != $1_size) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "incorrect array size");
+ return $null;
+ }
+ if (!SWIG_JavaArrayIn##JFUNCNAME(jenv, &jarr, ($&1_ltype)&$1, $input)) return $null; %}
+%typemap(argout) CTYPE[ANY], CTYPE[]
+%{ SWIG_JavaArrayArgout##JFUNCNAME(jenv, jarr$argnum, ($1_ltype)$1, $input); %}
+%typemap(out) CTYPE[ANY]
+%{$result = SWIG_JavaArrayOut##JFUNCNAME(jenv, ($1_ltype)$1, $1_dim0); %}
+%typemap(out) CTYPE[]
+%{$result = SWIG_JavaArrayOut##JFUNCNAME(jenv, ($1_ltype)$1, FillMeInAsSizeCannotBeDeterminedAutomatically); %}
+%typemap(freearg) CTYPE[ANY], CTYPE[]
+#ifdef __cplusplus
+%{ delete [] $1; %}
+#else
+%{ free($1); %}
+#endif
+
+%typemap(javain) CTYPE[ANY], CTYPE[] "$javainput"
+%typemap(javaout) CTYPE[ANY], CTYPE[] {
+ return $jnicall;
+ }
+
+%typemap(memberin) CTYPE[ANY], CTYPE[];
+%typemap(globalin) CTYPE[ANY], CTYPE[];
+%enddef
+
+JAVA_ARRAYS_TYPEMAPS(bool, boolean, jboolean, Bool, "[Z") /* bool[ANY] */
+JAVA_ARRAYS_TYPEMAPS(signed char, byte, jbyte, Schar, "[B") /* signed char[ANY] */
+JAVA_ARRAYS_TYPEMAPS(unsigned char, short, jshort, Uchar, "[S") /* unsigned char[ANY] */
+JAVA_ARRAYS_TYPEMAPS(short, short, jshort, Short, "[S") /* short[ANY] */
+JAVA_ARRAYS_TYPEMAPS(unsigned short, int, jint, Ushort, "[I") /* unsigned short[ANY] */
+JAVA_ARRAYS_TYPEMAPS(int, int, jint, Int, "[I") /* int[ANY] */
+JAVA_ARRAYS_TYPEMAPS(unsigned int, long, jlong, Uint, "[J") /* unsigned int[ANY] */
+JAVA_ARRAYS_TYPEMAPS(long, int, jint, Long, "[I") /* long[ANY] */
+JAVA_ARRAYS_TYPEMAPS(unsigned long, long, jlong, Ulong, "[J") /* unsigned long[ANY] */
+JAVA_ARRAYS_TYPEMAPS(long long, long, jlong, Longlong, "[J") /* long long[ANY] */
+JAVA_ARRAYS_TYPEMAPS(float, float, jfloat, Float, "[F") /* float[ANY] */
+JAVA_ARRAYS_TYPEMAPS(double, double, jdouble, Double, "[D") /* double[ANY] */
+
+
+%typecheck(SWIG_TYPECHECK_BOOL_ARRAY) /* Java boolean[] */
+ bool[ANY], bool[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT8_ARRAY) /* Java byte[] */
+ signed char[ANY], signed char[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT16_ARRAY) /* Java short[] */
+ unsigned char[ANY], unsigned char[],
+ short[ANY], short[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT32_ARRAY) /* Java int[] */
+ unsigned short[ANY], unsigned short[],
+ int[ANY], int[],
+ long[ANY], long[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT64_ARRAY) /* Java long[] */
+ unsigned int[ANY], unsigned int[],
+ unsigned long[ANY], unsigned long[],
+ long long[ANY], long long[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT128_ARRAY) /* Java BigInteger[] */
+ unsigned long long[ANY], unsigned long long[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_FLOAT_ARRAY) /* Java float[] */
+ float[ANY], float[]
+ ""
+
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY) /* Java double[] */
+ double[ANY], double[]
+ ""
+
+#if defined(SWIGWORDSIZE64)
+%apply long long[ANY] { long[ANY] };
+%apply unsigned long long[ANY] { unsigned long[ANY] };
+%apply long long[] { long[] };
+%apply unsigned long long[] { unsigned long[] };
+#endif
+
+/* Arrays of proxy classes. The typemaps in this macro make it possible to treat an array of
+ * class/struct/unions as an array of Java classes.
+ * Use the following macro to use these typemaps for an array of class/struct/unions called name:
+ * JAVA_ARRAYSOFCLASSES(name)
+ * Note that multiple copies of the class/struct is made when using the array as a parameter input. */
+%define JAVA_ARRAYSOFCLASSES(ARRAYSOFCLASSES)
+
+%typemap(jni) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[] "jlongArray"
+%typemap(jtype) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[] "long[]"
+%typemap(jstype) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[] "$javaclassname[]"
+
+%typemap(javain) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[] "$javaclassname.cArrayUnwrap($javainput)"
+%typemap(javaout) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[] {
+ return $javaclassname.cArrayWrap($jnicall, $owner);
+ }
+
+%typemap(in) ARRAYSOFCLASSES[] (jlong *jarr, jsize sz)
+{
+ int i;
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array");
+ return $null;
+ }
+ sz = JCALL1(GetArrayLength, jenv, $input);
+ jarr = JCALL2(GetLongArrayElements, jenv, $input, 0);
+ if (!jarr) {
+ return $null;
+ }
+#ifdef __cplusplus
+ $1 = new $*1_ltype[sz];
+#else
+ $1 = ($1_ltype) malloc(sz * sizeof($*1_ltype));
+#endif
+ if (!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed");
+ return $null;
+ }
+ for (i=0; i<sz; i++) {
+ $1[i] = **($&1_ltype)&jarr[i];
+ }
+}
+
+%typemap(in) ARRAYSOFCLASSES[ANY] (jlong *jarr, jsize sz)
+{
+ int i;
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null array");
+ return $null;
+ }
+ sz = JCALL1(GetArrayLength, jenv, $input);
+ if (sz != $1_size) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "incorrect array size");
+ return $null;
+ }
+ jarr = JCALL2(GetLongArrayElements, jenv, $input, 0);
+ if (!jarr) {
+ return $null;
+ }
+#ifdef __cplusplus
+ $1 = new $*1_ltype[sz];
+#else
+ $1 = ($1_ltype) malloc(sz * sizeof($*1_ltype));
+#endif
+ if (!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaOutOfMemoryError, "array memory allocation failed");
+ return $null;
+ }
+ for (i=0; i<sz; i++) {
+ $1[i] = **($&1_ltype)&jarr[i];
+ }
+}
+
+%typemap(argout) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[]
+{
+ int i;
+ for (i=0; i<sz$argnum; i++) {
+ **($&1_ltype)&jarr$argnum[i] = $1[i];
+ }
+ JCALL3(ReleaseLongArrayElements, jenv, $input, jarr$argnum, 0);
+}
+
+%typemap(out) ARRAYSOFCLASSES[ANY]
+{
+ jlong *arr;
+ int i;
+ $result = JCALL1(NewLongArray, jenv, $1_dim0);
+ if (!$result) {
+ return $null;
+ }
+ arr = JCALL2(GetLongArrayElements, jenv, $result, 0);
+ if (!arr) {
+ return $null;
+ }
+ for (i=0; i<$1_dim0; i++) {
+ arr[i] = 0;
+ *($&1_ltype)&arr[i] = &$1[i];
+ }
+ JCALL3(ReleaseLongArrayElements, jenv, $result, arr, 0);
+}
+
+%typemap(freearg) ARRAYSOFCLASSES[ANY], ARRAYSOFCLASSES[]
+#ifdef __cplusplus
+%{ delete [] $1; %}
+#else
+%{ free($1); %}
+#endif
+
+/* Add some code to the proxy class of the array type for converting between type used in
+ * JNI class (long[]) and type used in proxy class ( ARRAYSOFCLASSES[] ) */
+%extend ARRAYSOFCLASSES {
+%proxycode %{
+ protected static long[] cArrayUnwrap($javaclassname[] arrayWrapper) {
+ long[] cArray = new long[arrayWrapper.length];
+ for (int i=0; i<arrayWrapper.length; i++)
+ cArray[i] = $javaclassname.getCPtr(arrayWrapper[i]);
+ return cArray;
+ }
+
+ protected static $javaclassname[] cArrayWrap(long[] cArray, boolean cMemoryOwn) {
+ $javaclassname[] arrayWrapper = new $javaclassname[cArray.length];
+ for (int i=0; i<cArray.length; i++)
+ arrayWrapper[i] = new $javaclassname(cArray[i], cMemoryOwn);
+ return arrayWrapper;
+ }
+%}
+}
+
+%enddef /* JAVA_ARRAYSOFCLASSES */
+
+
+/* Arrays of enums.
+ * Use the following to use these typemaps for an array of enums called name:
+ * %apply ARRAYSOFENUMS[ANY] { name[ANY] }; */
+%typemap(jni) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[] "jintArray"
+%typemap(jtype) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[] "int[]"
+%typemap(jstype) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[] "int[]"
+
+%typemap(javain) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[] "$javainput"
+%typemap(javaout) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[] {
+ return $jnicall;
+ }
+
+%typemap(in) ARRAYSOFENUMS[] (jint *jarr)
+%{ if (!SWIG_JavaArrayInInt(jenv, &jarr, (int **)&$1, $input)) return $null; %}
+%typemap(in) ARRAYSOFENUMS[ANY] (jint *jarr) {
+ if ($input && JCALL1(GetArrayLength, jenv, $input) != $1_size) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "incorrect array size");
+ return $null;
+ }
+ if (!SWIG_JavaArrayInInt(jenv, &jarr, (int **)&$1, $input)) return $null;
+}
+%typemap(argout) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[]
+%{ SWIG_JavaArrayArgoutInt(jenv, jarr$argnum, (int *)$1, $input); %}
+%typemap(out) ARRAYSOFENUMS[ANY]
+%{$result = SWIG_JavaArrayOutInt(jenv, (int *)$1, $1_dim0); %}
+%typemap(freearg) ARRAYSOFENUMS[ANY], ARRAYSOFENUMS[]
+#ifdef __cplusplus
+%{ delete [] $1; %}
+#else
+%{ free($1); %}
+#endif
+
diff --git a/contrib/tools/swig/Lib/java/boost_intrusive_ptr.i b/contrib/tools/swig/Lib/java/boost_intrusive_ptr.i
new file mode 100644
index 00000000000..072a31e8c2f
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/boost_intrusive_ptr.i
@@ -0,0 +1,484 @@
+// Users can provide their own SWIG_INTRUSIVE_PTR_TYPEMAPS or SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP macros before including this file to change the
+// visibility of the constructor and getCPtr method if desired to public if using multiple modules.
+#ifndef SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP
+#define SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP(CONST, TYPE...) SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP_IMPLEMENTATION(protected, protected, CONST, TYPE)
+#endif
+#ifndef SWIG_INTRUSIVE_PTR_TYPEMAPS
+#define SWIG_INTRUSIVE_PTR_TYPEMAPS(CONST, TYPE...) SWIG_INTRUSIVE_PTR_TYPEMAPS_IMPLEMENTATION(protected, protected, CONST, TYPE)
+#endif
+
+
+%include <intrusive_ptr.i>
+
+// Language specific macro implementing all the customisations for handling the smart pointer
+%define SWIG_INTRUSIVE_PTR_TYPEMAPS_IMPLEMENTATION(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, CONST, TYPE...)
+
+// %naturalvar is as documented for member variables
+%naturalvar TYPE;
+%naturalvar SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >;
+
+// destructor wrapper customisation
+%feature("unref") TYPE "(void)arg1; delete smartarg1;"
+
+// Typemap customisations...
+
+%typemap(in) CONST TYPE ($&1_type argp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ // plain value
+ argp = (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
+ return $null;
+ }
+ $1 = *argp;
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter") CONST TYPE %{
+ //plain value(out)
+ $1_ltype* resultp = new $1_ltype($1);
+ intrusive_ptr_add_ref(resultp);
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >());
+%}
+
+%typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ // plain pointer
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input;
+ $1 = (TYPE *)(smartarg ? smartarg->get() : 0);
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE * %{
+ //plain pointer(out)
+ #if ($owner)
+ if ($1) {
+ intrusive_ptr_add_ref($1);
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+ #else
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0;
+ #endif
+%}
+
+%typemap(in) CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ // plain reference
+ $1 = ($1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0);
+ if(!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
+ return $null;
+ }
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") CONST TYPE & %{
+ //plain reference(out)
+ #if ($owner)
+ if ($1) {
+ intrusive_ptr_add_ref($1);
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1, SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+ #else
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0;
+ #endif
+%}
+
+%typemap(in) TYPE *CONST& ($*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ // plain pointer by reference
+ temp = ($*1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0);
+ $1 = &temp;
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter,SWIG_null_deleter") TYPE *CONST& %{
+ // plain pointer by reference(out)
+ #if ($owner)
+ if (*$1) {
+ intrusive_ptr_add_ref(*$1);
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1, SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+ #else
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_0);
+ #endif
+%}
+
+%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > ($&1_type argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{
+ // intrusive_ptr by value
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input;
+ if (smartarg) {
+ $1 = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true);
+ }
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > %{
+ if ($1) {
+ intrusive_ptr_add_ref(result.get());
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(result.get(), SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+%}
+
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast ($&1_type smartarg) %{
+ // shared_ptr by value
+ smartarg = *($&1_ltype*)&$input;
+ if (smartarg) $1 = *smartarg;
+%}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{
+ *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0;
+%}
+
+%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{
+ // intrusive_ptr by reference
+ if ( $input ) {
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input;
+ temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true);
+ $1 = &temp;
+ } else {
+ $1 = &tempnull;
+ }
+%}
+%typemap(memberin) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & %{
+ delete &($1);
+ if ($self) {
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * temp = new SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(*$input);
+ $1 = *temp;
+ }
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & %{
+ if (*$1) {
+ intrusive_ptr_add_ref($1->get());
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1->get(), SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+%}
+
+%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * ($*1_ltype tempnull, $*1_ltype temp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{
+ // intrusive_ptr by pointer
+ if ( $input ) {
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input;
+ temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true);
+ $1 = &temp;
+ } else {
+ $1 = &tempnull;
+ }
+%}
+%typemap(memberin) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * %{
+ delete $1;
+ if ($self) $1 = new SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(*$input);
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * %{
+ if ($1 && *$1) {
+ intrusive_ptr_add_ref($1->get());
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1->get(), SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+ if ($owner) delete $1;
+%}
+
+%typemap(in) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& (SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > temp, $*1_ltype tempp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * smartarg) %{
+ // intrusive_ptr by pointer reference
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >**)&$input;
+ if ($input) {
+ temp = SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >(smartarg->get(), true);
+ }
+ tempp = &temp;
+ $1 = &tempp;
+%}
+%typemap(memberin) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{
+ if ($self) $1 = *$input;
+%}
+%typemap(out, fragment="SWIG_intrusive_deleter") SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& %{
+ if (*$1 && **$1) {
+ intrusive_ptr_add_ref((*$1)->get());
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >((*$1)->get(), SWIG_intrusive_deleter< CONST TYPE >());
+ } else {
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = 0;
+ }
+%}
+
+// various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug
+%typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+%typemap(out) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+
+
+%typemap (jni) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& "jlong"
+%typemap (jtype) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& "long"
+%typemap (jstype) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& "$typemap(jstype, TYPE)"
+%typemap(javain) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > &,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *,
+ SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& "$typemap(jstype, TYPE).getCPtr($javainput)"
+
+%typemap(javaout) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > & {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > * {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE > *& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+
+%typemap(javaout) CONST TYPE {
+ return new $typemap(jstype, TYPE)($jnicall, true);
+ }
+%typemap(javaout) CONST TYPE & {
+ return new $typemap(jstype, TYPE)($jnicall, true);
+ }
+%typemap(javaout) CONST TYPE * {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) TYPE *CONST& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+// Base proxy classes
+%typemap(javabody) TYPE %{
+ private transient long swigCPtr;
+ private transient boolean swigCMemOwnBase;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ swigCMemOwnBase = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+%}
+
+// Derived proxy classes
+%typemap(javabody_derived) TYPE %{
+ private transient long swigCPtr;
+ private transient boolean swigCMemOwnDerived;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ super($imclassname.$javaclazznameSWIGSmartPtrUpcast(cPtr), true);
+ swigCMemOwnDerived = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+%}
+
+%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") TYPE {
+ if(swigCPtr != 0 && swigCMemOwnBase) {
+ swigCMemOwnBase = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+
+%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized") TYPE {
+ if(swigCPtr != 0 && swigCMemOwnDerived) {
+ swigCMemOwnDerived = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ super.delete();
+ }
+
+// CONST version needed ???? also for C#
+%typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "long"
+%typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "long"
+
+
+%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+%template() SWIG_INTRUSIVE_PTR_QNAMESPACE::intrusive_ptr< CONST TYPE >;
+%enddef
+
+
+/////////////////////////////////////////////////////////////////////
+
+
+%include <shared_ptr.i>
+
+%define SWIG_INTRUSIVE_PTR_TYPEMAPS_NO_WRAP_IMPLEMENTATION(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, CONST, TYPE...)
+
+%naturalvar TYPE;
+%naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+
+// destructor mods
+%feature("unref") TYPE "(void)arg1; delete smartarg1;"
+
+
+// plain value
+%typemap(in) CONST TYPE ($&1_type argp = 0) %{
+ argp = (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
+ return $null;
+ }
+ $1 = *argp; %}
+%typemap(out) CONST TYPE
+%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %}
+
+// plain pointer
+%typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input;
+ $1 = (TYPE *)(smartarg ? smartarg->get() : 0); %}
+%typemap(out, fragment="SWIG_null_deleter") CONST TYPE * %{
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0;
+%}
+
+// plain reference
+%typemap(in) CONST TYPE & %{
+ $1 = ($1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0);
+ if (!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
+ return $null;
+ } %}
+%typemap(out, fragment="SWIG_null_deleter") CONST TYPE &
+%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %}
+
+// plain pointer by reference
+%typemap(in) TYPE *CONST& ($*1_ltype temp = 0)
+%{ temp = ($*1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0);
+ $1 = &temp; %}
+%typemap(out, fragment="SWIG_null_deleter") TYPE *CONST&
+%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); %}
+
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast ($&1_type smartarg) %{
+ // shared_ptr by value
+ smartarg = *($&1_ltype*)&$input;
+ if (smartarg) $1 = *smartarg;
+%}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ANY_TYPE_SWIGSharedPtrUpcast %{
+ *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0;
+%}
+
+// various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug
+%typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+%typemap(out) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+
+
+%typemap (jni) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "jlong"
+%typemap (jtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "long"
+%typemap (jstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "$typemap(jstype, TYPE)"
+%typemap (javain) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "$typemap(jstype, TYPE).getCPtr($javainput)"
+%typemap(javaout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+%typemap(javaout) CONST TYPE {
+ return new $typemap(jstype, TYPE)($jnicall, true);
+ }
+%typemap(javaout) CONST TYPE & {
+ return new $typemap(jstype, TYPE)($jnicall, true);
+ }
+%typemap(javaout) CONST TYPE * {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) TYPE *CONST& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+// Base proxy classes
+%typemap(javabody) TYPE %{
+ private transient long swigCPtr;
+ private transient boolean swigCMemOwnBase;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ swigCMemOwnBase = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+%}
+
+// Derived proxy classes
+%typemap(javabody_derived) TYPE %{
+ private transient long swigCPtr;
+ private transient boolean swigCMemOwnDerived;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ super($imclassname.$javaclazznameSWIGSmartPtrUpcast(cPtr), true);
+ swigCMemOwnDerived = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+%}
+
+%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") TYPE {
+ if (swigCPtr != 0) {
+ if (swigCMemOwnBase) {
+ swigCMemOwnBase = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+ }
+
+%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized") TYPE {
+ if (swigCPtr != 0) {
+ if (swigCMemOwnDerived) {
+ swigCMemOwnDerived = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+ super.delete();
+ }
+
+// CONST version needed ???? also for C#
+%typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "long"
+%typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "long"
+
+// Typecheck typemaps
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
+ TYPE CONST,
+ TYPE CONST &,
+ TYPE CONST *,
+ TYPE *CONST&,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
+ ""
+
+%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+%enddef
+
diff --git a/contrib/tools/swig/Lib/java/boost_shared_ptr.i b/contrib/tools/swig/Lib/java/boost_shared_ptr.i
new file mode 100644
index 00000000000..ce00162da14
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/boost_shared_ptr.i
@@ -0,0 +1,337 @@
+// Users can provide their own SWIG_SHARED_PTR_TYPEMAPS macro before including this file to change the
+// visibility of the constructor and getCPtr method if desired to public if using multiple modules.
+#ifndef SWIG_SHARED_PTR_TYPEMAPS
+#define SWIG_SHARED_PTR_TYPEMAPS(CONST, TYPE...) SWIG_SHARED_PTR_TYPEMAPS_IMPLEMENTATION(protected, protected, CONST, TYPE)
+#endif
+
+%include <shared_ptr.i>
+
+// Language specific macro implementing all the customisations for handling the smart pointer
+%define SWIG_SHARED_PTR_TYPEMAPS_IMPLEMENTATION(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, CONST, TYPE...)
+
+// %naturalvar is as documented for member variables
+%naturalvar TYPE;
+%naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+
+// destructor wrapper customisation
+%feature("unref") TYPE
+//"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter<SWIG_null_deleter>(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n"
+ "(void)arg1; delete smartarg1;"
+
+// Typemap customisations...
+
+// plain value
+%typemap(in) CONST TYPE ($&1_type argp = 0) %{
+ argp = (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
+ return $null;
+ }
+ $1 = *argp; %}
+%typemap(out) CONST TYPE
+%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %}
+
+%typemap(directorin,descriptor="L$packagepath/$&javaclassname;") CONST TYPE
+%{ $input = 0;
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %}
+
+%typemap(directorout) CONST TYPE
+%{ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
+ return $null;
+ }
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input;
+ $result = *smartarg->get();
+ %}
+
+// plain pointer
+%typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input;
+ $1 = (TYPE *)(smartarg ? smartarg->get() : 0); %}
+%typemap(out, fragment="SWIG_null_deleter") CONST TYPE * %{
+ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0;
+%}
+
+%typemap(directorin,descriptor="L$packagepath/$javaclassname;") CONST TYPE *
+%{ $input = 0;
+ if ($1) {
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($1 SWIG_NO_NULL_DELETER_0);
+ } %}
+
+%typemap(directorout) CONST TYPE * %{
+#error "typemaps for $1_type not available"
+%}
+
+// plain reference
+%typemap(in) CONST TYPE & %{
+ $1 = ($1_ltype)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0);
+ if (!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
+ return $null;
+ } %}
+%typemap(out, fragment="SWIG_null_deleter") CONST TYPE &
+%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner); %}
+
+%typemap(directorin,descriptor="L$packagepath/$javaclassname;") CONST TYPE &
+%{ $input = 0;
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (&$1 SWIG_NO_NULL_DELETER_0); %}
+
+%typemap(directorout) CONST TYPE & %{
+#error "typemaps for $1_type not available"
+%}
+
+// plain pointer by reference
+%typemap(in) TYPE *CONST& ($*1_ltype temp = 0)
+%{ temp = (TYPE *)((*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) ? (*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input)->get() : 0);
+ $1 = &temp; %}
+%typemap(out, fragment="SWIG_null_deleter") TYPE *CONST&
+%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner); %}
+
+%typemap(directorin,descriptor="L$packagepath/$*javaclassname;") TYPE *CONST&
+%{ $input = 0;
+ if ($1) {
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($1 SWIG_NO_NULL_DELETER_0);
+ } %}
+
+%typemap(directorout) TYPE *CONST& %{
+#error "typemaps for $1_type not available"
+%}
+
+// shared_ptr by value
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > ($&1_type argp)
+%{ argp = *($&1_ltype*)&$input;
+ if (argp) $1 = *argp; %}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >
+%{ *($&1_ltype*)&$result = $1 ? new $1_ltype($1) : 0; %}
+
+%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >
+%{ $input = 0;
+ if ($1) {
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1);
+ } %}
+
+%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >
+%{ if ($input) {
+ $&1_type smartarg = *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input;
+ $result = *smartarg;
+ } %}
+
+// shared_ptr by reference
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & ($*1_ltype tempnull)
+%{ $1 = $input ? *($&1_ltype)&$input : &tempnull; %}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &
+%{ *($&1_ltype)&$result = *$1 ? new $*1_ltype(*$1) : 0; %}
+
+%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &
+%{ $input = 0;
+ if ($1) {
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1);
+ } %}
+
+%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{
+#error "typemaps for $1_type not available"
+%}
+
+// shared_ptr by pointer
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull)
+%{ $1 = $input ? *($&1_ltype)&$input : &tempnull; %}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *
+%{ *($&1_ltype)&$result = ($1 && *$1) ? new $*1_ltype(*$1) : 0;
+ if ($owner) delete $1; %}
+
+%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *
+%{ $input = 0;
+ if ($1 && *$1) {
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1);
+ } %}
+
+%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{
+#error "typemaps for $1_type not available"
+%}
+
+// shared_ptr by pointer reference
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempnull, $*1_ltype temp = 0)
+%{ temp = $input ? *($1_ltype)&$input : &tempnull;
+ $1 = &temp; %}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
+%{ *($1_ltype)&$result = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0; %}
+
+%typemap(directorin,descriptor="L$packagepath/$typemap(jstype, TYPE);") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
+%{ $input = 0;
+ if ($1 && *$1) {
+ *((SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$input) = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1);
+ } %}
+
+%typemap(directorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{
+#error "typemaps for $1_type not available"
+%}
+
+// various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug
+%typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+%typemap(out) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+
+
+%typemap (jni) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "jlong"
+%typemap (jtype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "long"
+%typemap (jstype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(jstype, TYPE)"
+
+%typemap(javain) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "$typemap(jstype, TYPE).getCPtr($javainput)"
+
+%typemap(javaout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+
+%typemap(javaout) CONST TYPE {
+ return new $typemap(jstype, TYPE)($jnicall, true);
+ }
+%typemap(javaout) CONST TYPE & {
+ return new $typemap(jstype, TYPE)($jnicall, true);
+ }
+%typemap(javaout) CONST TYPE * {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) TYPE *CONST& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+%typemap(javadirectorout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > "$typemap(jstype, TYPE).getCPtr($javacall)"
+
+%typemap(javadirectorin) CONST TYPE,
+ CONST TYPE *,
+ CONST TYPE &,
+ TYPE *CONST& "($jniinput == 0) ? null : new $typemap(jstype, TYPE)($jniinput, true)"
+
+%typemap(javadirectorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& "($jniinput == 0) ? null : new $typemap(jstype, TYPE)($jniinput, true)"
+
+// Base proxy classes
+%typemap(javabody) TYPE %{
+ private transient long swigCPtr;
+ private transient boolean swigCMemOwn;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ swigCMemOwn = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+
+ CPTR_VISIBILITY void swigSetCMemOwn(boolean own) {
+ swigCMemOwn = own;
+ }
+%}
+
+// Derived proxy classes
+%typemap(javabody_derived) TYPE %{
+ private transient long swigCPtr;
+ private transient boolean swigCMemOwnDerived;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ super($imclassname.$javaclazznameSWIGSmartPtrUpcast(cPtr), true);
+ swigCMemOwnDerived = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+
+ CPTR_VISIBILITY void swigSetCMemOwn(boolean own) {
+ swigCMemOwnDerived = own;
+ super.swigSetCMemOwn(own);
+ }
+%}
+
+%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") TYPE {
+ if (swigCPtr != 0) {
+ if (swigCMemOwn) {
+ swigCMemOwn = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+ }
+
+%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized") TYPE {
+ if (swigCPtr != 0) {
+ if (swigCMemOwnDerived) {
+ swigCMemOwnDerived = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+ super.delete();
+ }
+
+%typemap(directordisconnect, methodname="swigDirectorDisconnect") TYPE %{
+ protected void $methodname() {
+ swigSetCMemOwn(false);
+ $jnicall;
+ }
+%}
+
+%typemap(directorowner_release, methodname="swigReleaseOwnership") TYPE %{
+ public void $methodname() {
+ swigSetCMemOwn(false);
+ $jnicall;
+ }
+%}
+
+%typemap(directorowner_take, methodname="swigTakeOwnership") TYPE %{
+ public void $methodname() {
+ swigSetCMemOwn(true);
+ $jnicall;
+ }
+%}
+
+// Typecheck typemaps
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
+ TYPE CONST,
+ TYPE CONST &,
+ TYPE CONST *,
+ TYPE *CONST&,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
+ ""
+
+%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+%enddef
+
diff --git a/contrib/tools/swig/Lib/java/cdata.i b/contrib/tools/swig/Lib/java/cdata.i
new file mode 100644
index 00000000000..f1befcafe5f
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/cdata.i
@@ -0,0 +1,78 @@
+/* -----------------------------------------------------------------------------
+ * cdata.i
+ *
+ * SWIG library file containing macros for manipulating raw C data.
+ * ----------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------
+ * Typemap for passing bytes with length
+ * ------------------------------------------------------------ */
+
+/* String & length */
+%typemap(jni) (const void *BYTES, size_t LENGTH) "jbyteArray"
+%typemap(jtype) (const void *BYTES, size_t LENGTH) "byte[]"
+%typemap(jstype) (const void *BYTES, size_t LENGTH) "byte[]"
+%typemap(javain) (const void *BYTES, size_t LENGTH) "$javainput"
+%typemap(freearg) (const void *BYTES, size_t LENGTH) ""
+%typemap(in) (const void *BYTES, size_t LENGTH) {
+ if ($input) {
+ $1 = ($1_ltype) JCALL2(GetByteArrayElements, jenv, $input, 0);
+ $2 = ($2_type) JCALL1(GetArrayLength, jenv, $input);
+ } else {
+ $1 = 0;
+ $2 = 0;
+ }
+}
+%typemap(argout) (const void *BYTES, size_t LENGTH) {
+ if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, JNI_ABORT);
+}
+%typemap(directorin, descriptor="[B", noblock=1) (const void *BYTES, size_t LENGTH) {
+ $input = 0;
+ if ($1) {
+ $input = JCALL1(NewByteArray, jenv, (jsize)$2);
+ if (!$input) return $null;
+ JCALL4(SetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1);
+ }
+ Swig::LocalRefGuard $1_refguard(jenv, $input);
+}
+%typemap(javadirectorin, descriptor="[B") (const void *BYTES, size_t LENGTH) "$jniinput"
+%apply (const void *BYTES, size_t LENGTH) { (void *BYTES, size_t LENGTH) }
+/* Enable write-back for non-const version */
+%typemap(argout) (void *BYTES, size_t LENGTH) {
+ if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, 0);
+}
+%typemap(directorargout, noblock=1) (void *BYTES, size_t LENGTH)
+{ if ($input && $1) JCALL4(GetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1); }
+
+%include <typemaps/cdata_begin.swg>
+
+%typemap(jni) SWIGCDATA "jbyteArray"
+%typemap(jtype) SWIGCDATA "byte[]"
+%typemap(jstype) SWIGCDATA "byte[]"
+%fragment("SWIG_JavaArrayOutCDATA", "header") {
+static jbyteArray SWIG_JavaArrayOutCDATA(JNIEnv *jenv, char *result, jsize sz) {
+ jbyteArray jresult;
+ jbyte *arr;
+ int i;
+ jresult = JCALL1(NewByteArray, jenv, sz);
+ if (!jresult) {
+ return SWIG_NULLPTR;
+ }
+ arr = JCALL2(GetByteArrayElements, jenv, jresult, 0);
+ if (!arr) {
+ return SWIG_NULLPTR;
+ }
+ for (i=0; i<sz; i++) {
+ arr[i] = (jbyte)result[i];
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, jresult, arr, 0);
+ return jresult;
+}
+}
+%typemap(out, fragment="SWIG_JavaArrayOutCDATA") SWIGCDATA
+%{$result = SWIG_JavaArrayOutCDATA(jenv, (char *)$1.data, $1.len); %}
+%typemap(javaout) SWIGCDATA {
+ return $jnicall;
+ }
+
+%include <typemaps/cdata_end.swg>
diff --git a/contrib/tools/swig/Lib/java/director.swg b/contrib/tools/swig/Lib/java/director.swg
new file mode 100644
index 00000000000..630a98f3b07
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/director.swg
@@ -0,0 +1,541 @@
+/* -----------------------------------------------------------------------------
+ * director.swg
+ *
+ * This file contains support for director classes so that Java proxy
+ * methods can be called from C++.
+ * ----------------------------------------------------------------------------- */
+
+#if defined(DEBUG_DIRECTOR_OWNED) || defined(DEBUG_DIRECTOR_EXCEPTION) || defined(DEBUG_DIRECTOR_THREAD_NAME)
+#include <iostream>
+#endif
+
+#include <exception>
+
+#if defined(SWIG_JAVA_USE_THREAD_NAME)
+
+#if !defined(SWIG_JAVA_GET_THREAD_NAME)
+namespace Swig {
+ SWIGINTERN int GetThreadName(char *name, size_t len);
+}
+
+#if defined(__linux__)
+
+#include <sys/prctl.h>
+SWIGINTERN int Swig::GetThreadName(char *name, size_t len) {
+ (void)len;
+#if defined(PR_GET_NAME)
+ return prctl(PR_GET_NAME, (unsigned long)name, 0, 0, 0);
+#else
+ (void)name;
+ return 1;
+#endif
+}
+
+#elif defined(__unix__) || defined(__APPLE__)
+
+#include <pthread.h>
+SWIGINTERN int Swig::GetThreadName(char *name, size_t len) {
+ return pthread_getname_np(pthread_self(), name, len);
+}
+
+#else
+
+SWIGINTERN int Swig::GetThreadName(char *name, size_t len) {
+ (void)len;
+ (void)name;
+ return 1;
+}
+#endif
+
+#endif
+
+#endif
+
+#if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
+#include <pthread.h>
+#endif
+
+namespace Swig {
+
+ /* Java object wrapper */
+ class JObjectWrapper {
+ public:
+ JObjectWrapper() : jthis_(SWIG_NULLPTR), weak_global_(true) {
+ }
+
+ ~JObjectWrapper() {
+ jthis_ = SWIG_NULLPTR;
+ weak_global_ = true;
+ }
+
+ bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) {
+ if (!jthis_) {
+ weak_global_ = weak_global || !mem_own; // hold as weak global if explicitly requested or not owned
+ if (jobj)
+ jthis_ = weak_global_ ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj);
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl;
+#endif
+ return true;
+ } else {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl;
+#endif
+ return false;
+ }
+ }
+
+ jobject get(JNIEnv *jenv) const {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::get(";
+ if (jthis_)
+ std::cout << jthis_;
+ else
+ std::cout << "null";
+ std::cout << ") -> return new local ref" << std::endl;
+#endif
+ return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_);
+ }
+
+ void release(JNIEnv *jenv) {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "weak global ref" : "global ref") << std::endl;
+#endif
+ if (jthis_) {
+ if (weak_global_) {
+ if (jenv->IsSameObject(jthis_, SWIG_NULLPTR) == JNI_FALSE)
+ jenv->DeleteWeakGlobalRef((jweak)jthis_);
+ } else
+ jenv->DeleteGlobalRef(jthis_);
+ }
+
+ jthis_ = SWIG_NULLPTR;
+ weak_global_ = true;
+ }
+
+ /* Only call peek if you know what you are doing wrt to weak/global references */
+ jobject peek() {
+ return jthis_;
+ }
+
+ /* Java proxy releases ownership of C++ object, C++ object is now
+ responsible for destruction (creates NewGlobalRef to pin Java proxy) */
+ void java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
+ if (take_or_release) { /* Java takes ownership of C++ object's lifetime. */
+ if (!weak_global_) {
+ jenv->DeleteGlobalRef(jthis_);
+ jthis_ = jenv->NewWeakGlobalRef(jself);
+ weak_global_ = true;
+ }
+ } else {
+ /* Java releases ownership of C++ object's lifetime */
+ if (weak_global_) {
+ jenv->DeleteWeakGlobalRef((jweak)jthis_);
+ jthis_ = jenv->NewGlobalRef(jself);
+ weak_global_ = false;
+ }
+ }
+ }
+
+#if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
+ static void detach(void *jvm) {
+ static_cast<JavaVM *>(jvm)->DetachCurrentThread();
+ }
+
+ static void make_detach_key() {
+ pthread_key_create(&detach_key_, detach);
+ }
+
+ /* thread-local key to register a destructor */
+ static pthread_key_t detach_key_;
+#endif
+
+ private:
+ /* pointer to Java object */
+ jobject jthis_;
+ /* Local or global reference flag */
+ bool weak_global_;
+ };
+
+#if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
+ pthread_key_t JObjectWrapper::detach_key_;
+#endif
+
+ /* Local JNI reference deleter */
+ class LocalRefGuard {
+ JNIEnv *jenv_;
+ jobject jobj_;
+
+ // non-copyable
+ LocalRefGuard(const LocalRefGuard &);
+ LocalRefGuard &operator=(const LocalRefGuard &);
+ public:
+ LocalRefGuard(JNIEnv *jenv, jobject jobj): jenv_(jenv), jobj_(jobj) {}
+ ~LocalRefGuard() {
+ if (jobj_)
+ jenv_->DeleteLocalRef(jobj_);
+ }
+ };
+
+ /* director base class */
+ class Director {
+ /* pointer to Java virtual machine */
+ JavaVM *swig_jvm_;
+
+ protected:
+#if defined (_MSC_VER) && (_MSC_VER<1300)
+ class JNIEnvWrapper;
+ friend class JNIEnvWrapper;
+#endif
+ /* Utility class for managing the JNI environment */
+ class JNIEnvWrapper {
+ const Director *director_;
+ JNIEnv *jenv_;
+ int env_status;
+ public:
+ JNIEnvWrapper(const Director *director) : director_(director), jenv_(SWIG_NULLPTR), env_status(0) {
+#if defined(__ANDROID__)
+ JNIEnv **jenv = &jenv_;
+#else
+ void **jenv = (void **)&jenv_;
+#endif
+ env_status = director_->swig_jvm_->GetEnv((void **)&jenv_, JNI_VERSION_1_2);
+ JavaVMAttachArgs args;
+ args.version = JNI_VERSION_1_2;
+ args.group = SWIG_NULLPTR;
+ args.name = SWIG_NULLPTR;
+#if defined(SWIG_JAVA_USE_THREAD_NAME)
+ char thread_name[64]; // MAX_TASK_COMM_LEN=16 is hard-coded in the Linux kernel and MacOS has MAXTHREADNAMESIZE=64.
+ if (Swig::GetThreadName(thread_name, sizeof(thread_name)) == 0) {
+ args.name = thread_name;
+#if defined(DEBUG_DIRECTOR_THREAD_NAME)
+ std::cout << "JNIEnvWrapper: thread name: " << thread_name << std::endl;
+ } else {
+ std::cout << "JNIEnvWrapper: Couldn't set Java thread name" << std::endl;
+#endif
+ }
+#endif
+#if defined(SWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON)
+ // Attach a daemon thread to the JVM. Useful when the JVM should not wait for
+ // the thread to exit upon shutdown. Only for jdk-1.4 and later.
+ director_->swig_jvm_->AttachCurrentThreadAsDaemon(jenv, &args);
+#else
+ director_->swig_jvm_->AttachCurrentThread(jenv, &args);
+#endif
+
+#if defined(SWIG_JAVA_DETACH_ON_THREAD_END)
+ // At least on Android 6, detaching after every call causes a memory leak.
+ // Instead, register a thread desructor and detach only when the thread ends.
+ // See https://developer.android.com/training/articles/perf-jni#threads
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+ pthread_once(&once, JObjectWrapper::make_detach_key);
+ pthread_setspecific(JObjectWrapper::detach_key_, director->swig_jvm_);
+#endif
+ }
+ ~JNIEnvWrapper() {
+#if !defined(SWIG_JAVA_DETACH_ON_THREAD_END) && !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
+ // Some JVMs, eg jdk-1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call.
+ // However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak.
+ if (env_status == JNI_EDETACHED)
+ director_->swig_jvm_->DetachCurrentThread();
+#endif
+ }
+ JNIEnv *getJNIEnv() const {
+ return jenv_;
+ }
+ };
+
+ struct SwigDirectorMethod {
+ const char *name;
+ const char *desc;
+ jmethodID methid;
+ SwigDirectorMethod(JNIEnv *jenv, jclass baseclass, const char *name, const char *desc) : name(name), desc(desc) {
+ methid = jenv->GetMethodID(baseclass, name, desc);
+ }
+ };
+
+ /* Java object wrapper */
+ JObjectWrapper swig_self_;
+
+ /* Disconnect director from Java object */
+ void swig_disconnect_director_self(const char *disconn_method) {
+ JNIEnvWrapper jnienv(this) ;
+ JNIEnv *jenv = jnienv.getJNIEnv() ;
+ jobject jobj = swig_self_.get(jenv);
+ LocalRefGuard ref_deleter(jenv, jobj);
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl;
+#endif
+ if (jobj && jenv->IsSameObject(jobj, SWIG_NULLPTR) == JNI_FALSE) {
+ jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V");
+ if (disconn_meth) {
+#if defined(DEBUG_DIRECTOR_OWNED)
+ std::cout << "Swig::Director::disconnect_director_self upcall to " << disconn_method << std::endl;
+#endif
+ jenv->CallVoidMethod(jobj, disconn_meth);
+ }
+ }
+ }
+
+ jclass swig_new_global_ref(JNIEnv *jenv, const char *classname) {
+ jclass clz = jenv->FindClass(classname);
+ return clz ? (jclass)jenv->NewGlobalRef(clz) : SWIG_NULLPTR;
+ }
+
+ public:
+ Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) SWIG_NULLPTR), swig_self_() {
+ /* Acquire the Java VM pointer */
+ jenv->GetJavaVM(&swig_jvm_);
+ }
+
+ virtual ~Director() {
+ JNIEnvWrapper jnienv(this) ;
+ JNIEnv *jenv = jnienv.getJNIEnv() ;
+ swig_self_.release(jenv);
+ }
+
+ bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) {
+ return swig_self_.set(jenv, jself, mem_own, weak_global);
+ }
+
+ jobject swig_get_self(JNIEnv *jenv) const {
+ return swig_self_.get(jenv);
+ }
+
+ // Change C++ object's ownership, relative to Java
+ void swig_java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
+ swig_self_.java_change_ownership(jenv, jself, take_or_release);
+ }
+ };
+
+ // Zero initialized bool array
+ template<size_t N> class BoolArray {
+ bool array_[N];
+ public:
+ BoolArray() {
+ memset(array_, 0, sizeof(array_));
+ }
+ bool& operator[](size_t n) {
+ return array_[n];
+ }
+ bool operator[](size_t n) const {
+ return array_[n];
+ }
+ };
+
+ // Utility classes and functions for exception handling.
+
+ // Simple holder for a Java string during exception handling, providing access to a c-style string
+ class JavaString {
+ public:
+ JavaString(JNIEnv *jenv, jstring jstr) : jenv_(jenv), jstr_(jstr), cstr_(SWIG_NULLPTR) {
+ if (jenv_ && jstr_)
+ cstr_ = (const char *) jenv_->GetStringUTFChars(jstr_, SWIG_NULLPTR);
+ }
+
+ ~JavaString() {
+ if (jenv_ && jstr_ && cstr_)
+ jenv_->ReleaseStringUTFChars(jstr_, cstr_);
+ }
+
+ const char *c_str(const char *null_string = "null JavaString") const {
+ return cstr_ ? cstr_ : null_string;
+ }
+
+ private:
+ // non-copyable
+ JavaString(const JavaString &);
+ JavaString &operator=(const JavaString &);
+
+ JNIEnv *jenv_;
+ jstring jstr_;
+ const char *cstr_;
+ };
+
+ // Helper class to extract the exception message from a Java throwable
+ class JavaExceptionMessage {
+ public:
+ JavaExceptionMessage(JNIEnv *jenv, jthrowable throwable) : message_(jenv, exceptionMessageFromThrowable(jenv, throwable)) {
+ }
+
+ // Return a C string of the exception message in the jthrowable passed in the constructor
+ // If no message is available, null_string is return instead
+ const char *message(const char *null_string = "Could not get exception message in JavaExceptionMessage") const {
+ return message_.c_str(null_string);
+ }
+
+ private:
+ // non-copyable
+ JavaExceptionMessage(const JavaExceptionMessage &);
+ JavaExceptionMessage &operator=(const JavaExceptionMessage &);
+
+ // Get exception message by calling Java method Throwable.getMessage()
+ static jstring exceptionMessageFromThrowable(JNIEnv *jenv, jthrowable throwable) {
+ jstring jmsg = SWIG_NULLPTR;
+ if (jenv && throwable) {
+ jenv->ExceptionClear(); // Cannot invoke methods with any pending exceptions
+ jclass throwclz = jenv->GetObjectClass(throwable);
+ if (throwclz) {
+ // All Throwable classes have a getMessage() method, so call it to extract the exception message
+ jmethodID getMessageMethodID = jenv->GetMethodID(throwclz, "getMessage", "()Ljava/lang/String;");
+ if (getMessageMethodID)
+ jmsg = (jstring)jenv->CallObjectMethod(throwable, getMessageMethodID);
+ }
+ if (jmsg == SWIG_NULLPTR && jenv->ExceptionCheck())
+ jenv->ExceptionClear();
+ }
+ return jmsg;
+ }
+
+ JavaString message_;
+ };
+
+ // C++ Exception class for handling Java exceptions thrown during a director method Java upcall
+ class DirectorException : public std::exception {
+ public:
+
+ // Construct exception from a Java throwable
+ DirectorException(JNIEnv *jenv, jthrowable throwable) : jenv_(jenv), throwable_(throwable), classname_(SWIG_NULLPTR), msg_(SWIG_NULLPTR) {
+
+ // Call Java method Object.getClass().getName() to obtain the throwable's class name (delimited by '/')
+ if (jenv && throwable) {
+ jenv->ExceptionClear(); // Cannot invoke methods with any pending exceptions
+ jclass throwclz = jenv->GetObjectClass(throwable);
+ if (throwclz) {
+ jclass clzclz = jenv->GetObjectClass(throwclz);
+ if (clzclz) {
+ jmethodID getNameMethodID = jenv->GetMethodID(clzclz, "getName", "()Ljava/lang/String;");
+ if (getNameMethodID) {
+ jstring jstr_classname = (jstring)(jenv->CallObjectMethod(throwclz, getNameMethodID));
+ // Copy strings, since there is no guarantee that jenv will be active when handled
+ if (jstr_classname) {
+ JavaString jsclassname(jenv, jstr_classname);
+ const char *classname = jsclassname.c_str(SWIG_NULLPTR);
+ if (classname)
+ classname_ = copypath(classname);
+ }
+ }
+ }
+ }
+ }
+
+ JavaExceptionMessage exceptionmsg(jenv, throwable);
+ msg_ = copystr(exceptionmsg.message(SWIG_NULLPTR));
+ }
+
+ // More general constructor for handling as a java.lang.RuntimeException
+ DirectorException(const char *msg) : jenv_(SWIG_NULLPTR), throwable_(SWIG_NULLPTR), classname_(SWIG_NULLPTR), msg_(msg ? copystr(msg) : SWIG_NULLPTR) {
+ }
+
+ ~DirectorException() throw() {
+ delete[] classname_;
+ delete[] msg_;
+ }
+
+ const char *what() const throw() {
+ return msg_ ? msg_ : "Unspecified DirectorException message";
+ }
+
+ // Reconstruct and raise/throw the Java Exception that caused the DirectorException
+ // Note that any error in the JNI exception handling results in a Java RuntimeException
+ void throwException(JNIEnv *jenv) const {
+ if (jenv) {
+ if (jenv == jenv_ && throwable_) {
+ // Throw original exception if not already pending
+ jthrowable throwable = jenv->ExceptionOccurred();
+ if (throwable && jenv->IsSameObject(throwable, throwable_) == JNI_FALSE) {
+ jenv->ExceptionClear();
+ throwable = SWIG_NULLPTR;
+ }
+ if (!throwable)
+ jenv->Throw(throwable_);
+ } else {
+ // Try and reconstruct original exception, but original stacktrace is not reconstructed
+ jenv->ExceptionClear();
+
+ jmethodID ctorMethodID = SWIG_NULLPTR;
+ jclass throwableclass = SWIG_NULLPTR;
+ if (classname_) {
+ throwableclass = jenv->FindClass(classname_);
+ if (throwableclass)
+ ctorMethodID = jenv->GetMethodID(throwableclass, "<init>", "(Ljava/lang/String;)V");
+ }
+
+ if (ctorMethodID) {
+ jenv->ThrowNew(throwableclass, what());
+ } else {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, what());
+ }
+ }
+ }
+ }
+
+ // Deprecated - use throwException
+ void raiseJavaException(JNIEnv *jenv) const {
+ throwException(jenv);
+ }
+
+ // Create and throw the DirectorException
+ static void raise(JNIEnv *jenv, jthrowable throwable) {
+ throw DirectorException(jenv, throwable);
+ }
+
+ private:
+ static char *copypath(const char *srcmsg) {
+ char *target = copystr(srcmsg);
+ for (char *c=target; *c; ++c) {
+ if ('.' == *c)
+ *c = '/';
+ }
+ return target;
+ }
+
+ static char *copystr(const char *srcmsg) {
+ char *target = SWIG_NULLPTR;
+ if (srcmsg) {
+ size_t msglen = strlen(srcmsg) + 1;
+ target = new char[msglen];
+ strncpy(target, srcmsg, msglen);
+ }
+ return target;
+ }
+
+ JNIEnv *jenv_;
+ jthrowable throwable_;
+ const char *classname_;
+ const char *msg_;
+ };
+
+ // Helper method to determine if a Java throwable matches a particular Java class type
+ // Note side effect of clearing any pending exceptions
+ SWIGINTERN bool ExceptionMatches(JNIEnv *jenv, jthrowable throwable, const char *classname) {
+ bool matches = false;
+
+ if (throwable && jenv && classname) {
+ // Exceptions need to be cleared for correct behavior.
+ // The caller of ExceptionMatches should restore pending exceptions if desired -
+ // the caller already has the throwable.
+ jenv->ExceptionClear();
+
+ jclass clz = jenv->FindClass(classname);
+ if (clz) {
+ jclass classclz = jenv->GetObjectClass(clz);
+ jmethodID isInstanceMethodID = jenv->GetMethodID(classclz, "isInstance", "(Ljava/lang/Object;)Z");
+ if (isInstanceMethodID) {
+ matches = jenv->CallBooleanMethod(clz, isInstanceMethodID, throwable) != 0;
+ }
+ }
+
+#if defined(DEBUG_DIRECTOR_EXCEPTION)
+ if (jenv->ExceptionCheck()) {
+ // Typically occurs when an invalid classname argument is passed resulting in a ClassNotFoundException
+ JavaExceptionMessage exc(jenv, jenv->ExceptionOccurred());
+ std::cout << "Error: ExceptionMatches: class '" << classname << "' : " << exc.message() << std::endl;
+ }
+#endif
+ }
+ return matches;
+ }
+}
+
diff --git a/contrib/tools/swig/Lib/java/enums.swg b/contrib/tools/swig/Lib/java/enums.swg
new file mode 100644
index 00000000000..81fe57872f4
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/enums.swg
@@ -0,0 +1,116 @@
+/* -----------------------------------------------------------------------------
+ * enums.swg
+ *
+ * Include this file in order for C/C++ enums to be wrapped by proper Java enums.
+ * Note that the JNI layer handles the enum as an int. The Java enum has extra
+ * code generated to store the C++ int value. This is required for C++ enums that
+ * specify a value for the enum item, as native Java enums do not support this.
+ * ----------------------------------------------------------------------------- */
+
+// const enum SWIGTYPE & typemaps
+%typemap(jni) const enum SWIGTYPE & "jint"
+%typemap(jtype) const enum SWIGTYPE & "int"
+%typemap(jstype) const enum SWIGTYPE & "$*javaclassname"
+
+%typemap(in) const enum SWIGTYPE & ($*1_ltype temp)
+%{ temp = ($*1_ltype)$input;
+ $1 = &temp; %}
+%typemap(out) const enum SWIGTYPE & %{ $result = (jint)*$1; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
+%{ static $*1_ltype temp = ($*1_ltype)$input;
+ $result = &temp; %}
+%typemap(directorin, descriptor="L$packagepath/$*javaclassname;") const enum SWIGTYPE & "$input = (jint)$1;"
+%typemap(javadirectorin) const enum SWIGTYPE & "$*javaclassname.swigToEnum($jniinput)"
+%typemap(javadirectorout) const enum SWIGTYPE & "($javacall).swigValue()"
+
+%typecheck(SWIG_TYPECHECK_POINTER) const enum SWIGTYPE & ""
+
+%typemap(throws) const enum SWIGTYPE &
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) const enum SWIGTYPE & "$javainput.swigValue()"
+%typemap(javaout) const enum SWIGTYPE & {
+ return $*javaclassname.swigToEnum($jnicall);
+ }
+
+
+// enum SWIGTYPE typemaps
+%typemap(jni) enum SWIGTYPE "jint"
+%typemap(jtype) enum SWIGTYPE "int"
+%typemap(jstype) enum SWIGTYPE "$javaclassname"
+
+%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
+%typemap(out) enum SWIGTYPE %{ $result = (jint)$1; %}
+
+%typemap(directorout) enum SWIGTYPE %{ $result = ($1_ltype)$input; %}
+%typemap(directorin, descriptor="L$packagepath/$javaclassname;") enum SWIGTYPE "$input = (jint) $1;"
+%typemap(javadirectorin) enum SWIGTYPE "$javaclassname.swigToEnum($jniinput)"
+%typemap(javadirectorout) enum SWIGTYPE "($javacall).swigValue()"
+
+%typecheck(SWIG_TYPECHECK_POINTER) enum SWIGTYPE ""
+
+%typemap(throws) enum SWIGTYPE
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) enum SWIGTYPE "$javainput.swigValue()"
+%typemap(javaout) enum SWIGTYPE {
+ return $javaclassname.swigToEnum($jnicall);
+ }
+
+%typemap(javaclassmodifiers) enum SWIGTYPE "public enum"
+%typemap(javabase) enum SWIGTYPE ""
+%typemap(javacode) enum SWIGTYPE ""
+%typemap(javaimports) enum SWIGTYPE ""
+%typemap(javainterfaces) enum SWIGTYPE ""
+
+/*
+ * SwigNext static inner class used instead of a static int as static fields cannot be accessed from enum initialisers.
+ * The swigToEnum method is used to find the Java enum from a C++ enum integer value. The default one here takes
+ * advantage of the fact that most enums do not have initial values specified, so the lookup is fast. If initial
+ * values are specified then a lengthy linear search through all possible enums might occur. Specific typemaps could be
+ * written to possibly optimise this lookup by taking advantage of characteristics peculiar to the targeted enum.
+ */
+%typemap(javabody) enum SWIGTYPE %{
+ public final int swigValue() {
+ return swigValue;
+ }
+
+ public static $javaclassname swigToEnum(int swigValue) {
+ $javaclassname[] swigValues = $javaclassname.class.getEnumConstants();
+ if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue)
+ return swigValues[swigValue];
+ for ($javaclassname swigEnum : swigValues)
+ if (swigEnum.swigValue == swigValue)
+ return swigEnum;
+ throw new IllegalArgumentException("No enum " + $javaclassname.class + " with value " + swigValue);
+ }
+
+ @SuppressWarnings("unused")
+ private $javaclassname() {
+ this.swigValue = SwigNext.next++;
+ }
+
+ @SuppressWarnings("unused")
+ private $javaclassname(int swigValue) {
+ this.swigValue = swigValue;
+ SwigNext.next = swigValue+1;
+ }
+
+ @SuppressWarnings("unused")
+ private $javaclassname($javaclassname swigEnum) {
+ this.swigValue = swigEnum.swigValue;
+ SwigNext.next = this.swigValue+1;
+ }
+
+ private final int swigValue;
+
+ private static class SwigNext {
+ private static int next = 0;
+ }
+%}
+
+%javaenum(proper);
+
diff --git a/contrib/tools/swig/Lib/java/enumsimple.swg b/contrib/tools/swig/Lib/java/enumsimple.swg
new file mode 100644
index 00000000000..c270149bd6e
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/enumsimple.swg
@@ -0,0 +1,71 @@
+/* -----------------------------------------------------------------------------
+ * enumsimple.swg
+ *
+ * This file provides backwards compatible enum wrapping. SWIG versions 1.3.21
+ * and earlier wrapped global enums with constant integers in the module class
+ * or Constants interface. Enums declared within a C++ class were wrapped by
+ * constant integers in the Java proxy class.
+ * ----------------------------------------------------------------------------- */
+
+// const enum SWIGTYPE & typemaps
+%typemap(jni) const enum SWIGTYPE & "jint"
+%typemap(jtype) const enum SWIGTYPE & "int"
+%typemap(jstype) const enum SWIGTYPE & "int"
+
+%typemap(in) const enum SWIGTYPE & ($*1_ltype temp)
+%{ temp = ($*1_ltype)$input;
+ $1 = &temp; %}
+%typemap(out) const enum SWIGTYPE & %{ $result = (jint)*$1; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
+%{ static $*1_ltype temp = ($*1_ltype)$input;
+ $result = &temp; %}
+%typemap(directorin, descriptor="I") const enum SWIGTYPE & "$input = (jint)$1;"
+%typemap(javadirectorin) const enum SWIGTYPE & "$jniinput"
+%typemap(javadirectorout) const enum SWIGTYPE & "$javacall"
+
+%typecheck(SWIG_TYPECHECK_INT32) const enum SWIGTYPE & ""
+
+%typemap(throws) const enum SWIGTYPE &
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) const enum SWIGTYPE & "$javainput"
+%typemap(javaout) const enum SWIGTYPE & {
+ return $jnicall;
+ }
+
+
+// enum SWIGTYPE typemaps
+%typemap(jni) enum SWIGTYPE "jint"
+%typemap(jtype) enum SWIGTYPE "int"
+%typemap(jstype) enum SWIGTYPE "int"
+
+%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
+%typemap(out) enum SWIGTYPE %{ $result = (jint)$1; %}
+
+%typemap(directorout) enum SWIGTYPE %{ $result = ($1_ltype)$input; %}
+%typemap(directorin, descriptor="I") enum SWIGTYPE "$input = (jint) $1;"
+%typemap(javadirectorin) enum SWIGTYPE "$jniinput"
+%typemap(javadirectorout) enum SWIGTYPE "$javacall"
+
+%typecheck(SWIG_TYPECHECK_INT32) enum SWIGTYPE ""
+
+%typemap(throws) enum SWIGTYPE
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) enum SWIGTYPE "$javainput"
+%typemap(javaout) enum SWIGTYPE {
+ return $jnicall;
+ }
+
+%typemap(javaclassmodifiers) enum SWIGTYPE ""
+%typemap(javabase) enum SWIGTYPE ""
+%typemap(javacode) enum SWIGTYPE ""
+%typemap(javaimports) enum SWIGTYPE ""
+%typemap(javainterfaces) enum SWIGTYPE ""
+%typemap(javabody) enum SWIGTYPE ""
+
+%javaenum(simple);
+
diff --git a/contrib/tools/swig/Lib/java/enumtypesafe.swg b/contrib/tools/swig/Lib/java/enumtypesafe.swg
new file mode 100644
index 00000000000..c2012f568b6
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/enumtypesafe.swg
@@ -0,0 +1,117 @@
+/* -----------------------------------------------------------------------------
+ * enumtypesafe.swg
+ *
+ * Include this file in order for C/C++ enums to be wrapped by the so called
+ * typesafe enum pattern. Each enum has an equivalent Java class named after the
+ * enum and each enum item is a static instance of this class.
+ * ----------------------------------------------------------------------------- */
+
+// const enum SWIGTYPE & typemaps
+%typemap(jni) const enum SWIGTYPE & "jint"
+%typemap(jtype) const enum SWIGTYPE & "int"
+%typemap(jstype) const enum SWIGTYPE & "$*javaclassname"
+
+%typemap(in) const enum SWIGTYPE & ($*1_ltype temp)
+%{ temp = ($*1_ltype)$input;
+ $1 = &temp; %}
+%typemap(out) const enum SWIGTYPE & %{ $result = (jint)*$1; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
+%{ static $*1_ltype temp = ($*1_ltype)$input;
+ $result = &temp; %}
+%typemap(directorin, descriptor="L$packagepath/$*javaclassname;") const enum SWIGTYPE & "$input = (jint)$1;"
+%typemap(javadirectorin) const enum SWIGTYPE & "$*javaclassname.swigToEnum($jniinput)"
+%typemap(javadirectorout) const enum SWIGTYPE & "($javacall).swigValue()"
+
+%typecheck(SWIG_TYPECHECK_POINTER) const enum SWIGTYPE & ""
+
+%typemap(throws) const enum SWIGTYPE &
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) const enum SWIGTYPE & "$javainput.swigValue()"
+%typemap(javaout) const enum SWIGTYPE & {
+ return $*javaclassname.swigToEnum($jnicall);
+ }
+
+// enum SWIGTYPE typemaps
+%typemap(jni) enum SWIGTYPE "jint"
+%typemap(jtype) enum SWIGTYPE "int"
+%typemap(jstype) enum SWIGTYPE "$javaclassname"
+
+%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
+%typemap(out) enum SWIGTYPE %{ $result = (jint)$1; %}
+
+%typemap(directorout) enum SWIGTYPE %{ $result = ($1_ltype)$input; %}
+%typemap(directorin, descriptor="L$packagepath/$javaclassname;") enum SWIGTYPE "$input = (jint) $1;"
+%typemap(javadirectorin) enum SWIGTYPE "$javaclassname.swigToEnum($jniinput)"
+%typemap(javadirectorout) enum SWIGTYPE "($javacall).swigValue()"
+
+%typecheck(SWIG_TYPECHECK_POINTER) enum SWIGTYPE ""
+
+%typemap(throws) enum SWIGTYPE
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) enum SWIGTYPE "$javainput.swigValue()"
+%typemap(javaout) enum SWIGTYPE {
+ return $javaclassname.swigToEnum($jnicall);
+ }
+
+// '$static' will be replaced with either 'static' or nothing depending on whether the enum is an inner Java class or not
+%typemap(javaclassmodifiers) enum SWIGTYPE "public final $static class"
+%typemap(javabase) enum SWIGTYPE ""
+%typemap(javacode) enum SWIGTYPE ""
+%typemap(javaimports) enum SWIGTYPE ""
+%typemap(javainterfaces) enum SWIGTYPE ""
+
+/*
+ * The swigToEnum method is used to find the Java enum from a C++ enum integer value. The default one here takes
+ * advantage of the fact that most enums do not have initial values specified, so the lookup is fast. If initial
+ * values are specified then a lengthy linear search through all possible enums might occur. Specific typemaps could be
+ * written to possibly optimise this lookup by taking advantage of characteristics peculiar to the targeted enum.
+ * The special variable, $enumvalues, is replaced with a comma separated list of all the enum values.
+ */
+%typemap(javabody) enum SWIGTYPE %{
+ public final int swigValue() {
+ return swigValue;
+ }
+
+ public String toString() {
+ return swigName;
+ }
+
+ public static $javaclassname swigToEnum(int swigValue) {
+ if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue)
+ return swigValues[swigValue];
+ for (int i = 0; i < swigValues.length; i++)
+ if (swigValues[i].swigValue == swigValue)
+ return swigValues[i];
+ throw new IllegalArgumentException("No enum " + $javaclassname.class + " with value " + swigValue);
+ }
+
+ private $javaclassname(String swigName) {
+ this.swigName = swigName;
+ this.swigValue = swigNext++;
+ }
+
+ private $javaclassname(String swigName, int swigValue) {
+ this.swigName = swigName;
+ this.swigValue = swigValue;
+ swigNext = swigValue+1;
+ }
+
+ private $javaclassname(String swigName, $javaclassname swigEnum) {
+ this.swigName = swigName;
+ this.swigValue = swigEnum.swigValue;
+ swigNext = this.swigValue+1;
+ }
+
+ private static $javaclassname[] swigValues = { $enumvalues };
+ private static int swigNext = 0;
+ private final int swigValue;
+ private final String swigName;
+%}
+
+%javaenum(typesafe);
+
diff --git a/contrib/tools/swig/Lib/java/enumtypeunsafe.swg b/contrib/tools/swig/Lib/java/enumtypeunsafe.swg
new file mode 100644
index 00000000000..31fb8a79d62
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/enumtypeunsafe.swg
@@ -0,0 +1,72 @@
+/* -----------------------------------------------------------------------------
+ * enumtypeunsafe.swg
+ *
+ * Include this file in order for C/C++ enums to be wrapped by integers values.
+ * Each enum has an equivalent class named after the enum and the enum items are
+ * wrapped by constant integers within this class. The enum items are not
+ * typesafe as they are all integers.
+ * ----------------------------------------------------------------------------- */
+
+// const enum SWIGTYPE & typemaps
+%typemap(jni) const enum SWIGTYPE & "jint"
+%typemap(jtype) const enum SWIGTYPE & "int"
+%typemap(jstype) const enum SWIGTYPE & "int"
+
+%typemap(in) const enum SWIGTYPE & ($*1_ltype temp)
+%{ temp = ($*1_ltype)$input;
+ $1 = &temp; %}
+%typemap(out) const enum SWIGTYPE & %{ $result = (jint)*$1; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
+%{ static $*1_ltype temp = ($*1_ltype)$input;
+ $result = &temp; %}
+%typemap(directorin, descriptor="I") const enum SWIGTYPE & "$input = (jint)$1;"
+%typemap(javadirectorin) const enum SWIGTYPE & "$jniinput"
+%typemap(javadirectorout) const enum SWIGTYPE & "$javacall"
+
+%typecheck(SWIG_TYPECHECK_INT32) const enum SWIGTYPE & ""
+
+%typemap(throws) const enum SWIGTYPE &
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) const enum SWIGTYPE & "$javainput"
+%typemap(javaout) const enum SWIGTYPE & {
+ return $jnicall;
+ }
+
+
+// enum SWIGTYPE typemaps
+%typemap(jni) enum SWIGTYPE "jint"
+%typemap(jtype) enum SWIGTYPE "int"
+%typemap(jstype) enum SWIGTYPE "int"
+
+%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
+%typemap(out) enum SWIGTYPE %{ $result = (jint)$1; %}
+
+%typemap(directorout) enum SWIGTYPE %{ $result = ($1_ltype)$input; %}
+%typemap(directorin, descriptor="I") enum SWIGTYPE "$input = (jint) $1;"
+%typemap(javadirectorin) enum SWIGTYPE "$jniinput"
+%typemap(javadirectorout) enum SWIGTYPE "$javacall"
+
+%typecheck(SWIG_TYPECHECK_INT32) enum SWIGTYPE ""
+
+%typemap(throws) enum SWIGTYPE
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown"); %}
+
+%typemap(javain) enum SWIGTYPE "$javainput"
+%typemap(javaout) enum SWIGTYPE {
+ return $jnicall;
+ }
+
+// '$static' will be replaced with either 'static' or nothing depending on whether the enum is an inner Java class or not
+%typemap(javaclassmodifiers) enum SWIGTYPE "public final $static class"
+%typemap(javabase) enum SWIGTYPE ""
+%typemap(javacode) enum SWIGTYPE ""
+%typemap(javaimports) enum SWIGTYPE ""
+%typemap(javainterfaces) enum SWIGTYPE ""
+%typemap(javabody) enum SWIGTYPE ""
+
+%javaenum(typeunsafe);
+
diff --git a/contrib/tools/swig/Lib/java/java.swg b/contrib/tools/swig/Lib/java/java.swg
new file mode 100644
index 00000000000..dd5b0358cd7
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/java.swg
@@ -0,0 +1,1466 @@
+/* -----------------------------------------------------------------------------
+ * java.swg
+ *
+ * Java typemaps
+ * ----------------------------------------------------------------------------- */
+
+%include <javahead.swg>
+
+/* The jni, jtype and jstype typemaps work together and so there should be one of each.
+ * The jni typemap contains the JNI type used in the JNI (C/C++) code.
+ * The jtype typemap contains the Java type used in the JNI intermediary class.
+ * The jstype typemap contains the Java type used in the Java proxy classes, type wrapper classes and module class. */
+
+/* Fragments */
+%fragment("SWIG_PackData", "header") {
+/* Pack binary data into a string */
+SWIGINTERN char * SWIG_PackData(char *c, void *ptr, size_t sz) {
+ static const char hex[17] = "0123456789abcdef";
+ const unsigned char *u = (unsigned char *) ptr;
+ const unsigned char *eu = u + sz;
+ for (; u != eu; ++u) {
+ unsigned char uu = *u;
+ *(c++) = hex[(uu & 0xf0) >> 4];
+ *(c++) = hex[uu & 0xf];
+ }
+ return c;
+}
+}
+
+%fragment("SWIG_UnPackData", "header") {
+/* Unpack binary data from a string */
+SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
+ unsigned char *u = (unsigned char *) ptr;
+ const unsigned char *eu = u + sz;
+ for (; u != eu; ++u) {
+ char d = *(c++);
+ unsigned char uu;
+ if ((d >= '0') && (d <= '9'))
+ uu = ((d - '0') << 4);
+ else if ((d >= 'a') && (d <= 'f'))
+ uu = ((d - ('a'-10)) << 4);
+ else
+ return (char *) 0;
+ d = *(c++);
+ if ((d >= '0') && (d <= '9'))
+ uu |= (d - '0');
+ else if ((d >= 'a') && (d <= 'f'))
+ uu |= (d - ('a'-10));
+ else
+ return (char *) 0;
+ *u = uu;
+ }
+ return c;
+}
+}
+
+%fragment("SWIG_JavaIntFromSize_t", "header") {
+/* Check for overflow converting to Java int (always signed 32-bit) from (unsigned variable-bit) size_t */
+SWIGINTERN jint SWIG_JavaIntFromSize_t(size_t size) {
+ static const jint JINT_MAX = 0x7FFFFFFF;
+ return (size > (size_t)JINT_MAX) ? -1 : (jint)size;
+}
+}
+
+/* Primitive types */
+%typemap(jni) bool, const bool & "jboolean"
+%typemap(jni) char, const char & "jchar"
+%typemap(jni) signed char, const signed char & "jbyte"
+%typemap(jni) unsigned char, const unsigned char & "jshort"
+%typemap(jni) short, const short & "jshort"
+%typemap(jni) unsigned short, const unsigned short & "jint"
+%typemap(jni) int, const int & "jint"
+%typemap(jni) unsigned int, const unsigned int & "jlong"
+%typemap(jni) long, const long & "jint"
+%typemap(jni) unsigned long, const unsigned long & "jlong"
+%typemap(jni) long long, const long long & "jlong"
+%typemap(jni) unsigned long long, const unsigned long long & "jobject"
+%typemap(jni) float, const float & "jfloat"
+%typemap(jni) double, const double & "jdouble"
+%typemap(jni) void "void"
+
+%typemap(jtype) bool, const bool & "boolean"
+%typemap(jtype) char, const char & "char"
+%typemap(jtype) signed char, const signed char & "byte"
+%typemap(jtype) unsigned char, const unsigned char & "short"
+%typemap(jtype) short, const short & "short"
+%typemap(jtype) unsigned short, const unsigned short & "int"
+%typemap(jtype) int, const int & "int"
+%typemap(jtype) unsigned int, const unsigned int & "long"
+%typemap(jtype) long, const long & "int"
+%typemap(jtype) unsigned long, const unsigned long & "long"
+%typemap(jtype) long long, const long long & "long"
+%typemap(jtype) unsigned long long, const unsigned long long & "java.math.BigInteger"
+%typemap(jtype) float, const float & "float"
+%typemap(jtype) double, const double & "double"
+%typemap(jtype) void "void"
+
+%typemap(jstype) bool, const bool & "boolean"
+%typemap(jstype) char, const char & "char"
+%typemap(jstype) signed char, const signed char & "byte"
+%typemap(jstype) unsigned char, const unsigned char & "short"
+%typemap(jstype) short, const short & "short"
+%typemap(jstype) unsigned short, const unsigned short & "int"
+%typemap(jstype) int, const int & "int"
+%typemap(jstype) unsigned int, const unsigned int & "long"
+%typemap(jstype) long, const long & "int"
+%typemap(jstype) unsigned long, const unsigned long & "long"
+%typemap(jstype) long long, const long long & "long"
+%typemap(jstype) unsigned long long, const unsigned long long & "java.math.BigInteger"
+%typemap(jstype) float, const float & "float"
+%typemap(jstype) double, const double & "double"
+%typemap(jstype) void "void"
+
+%typemap(jboxtype) bool, const bool & "Boolean"
+%typemap(jboxtype) char, const char & "Character"
+%typemap(jboxtype) signed char, const signed char & "Byte"
+%typemap(jboxtype) unsigned char, const unsigned char & "Short"
+%typemap(jboxtype) short, const short & "Short"
+%typemap(jboxtype) unsigned short, const unsigned short & "Integer"
+%typemap(jboxtype) int, const int & "Integer"
+%typemap(jboxtype) unsigned int, const unsigned int & "Long"
+%typemap(jboxtype) long, const long & "Integer"
+%typemap(jboxtype) unsigned long, const unsigned long & "Long"
+%typemap(jboxtype) long long, const long long & "Long"
+%typemap(jboxtype) unsigned long long, const unsigned long long & "java.math.BigInteger"
+%typemap(jboxtype) float, const float & "Float"
+%typemap(jboxtype) double, const double & "Double"
+
+%typemap(jni) char *, char *&, char[ANY], char[] "jstring"
+%typemap(jtype) char *, char *&, char[ANY], char[] "String"
+%typemap(jstype) char *, char *&, char[ANY], char[] "String"
+
+/* JNI types */
+%typemap(jni) jboolean "jboolean"
+%typemap(jni) jchar "jchar"
+%typemap(jni) jbyte "jbyte"
+%typemap(jni) jshort "jshort"
+%typemap(jni) jint "jint"
+%typemap(jni) jlong "jlong"
+%typemap(jni) jfloat "jfloat"
+%typemap(jni) jdouble "jdouble"
+%typemap(jni) jstring "jstring"
+%typemap(jni) jobject "jobject"
+%typemap(jni) jbooleanArray "jbooleanArray"
+%typemap(jni) jcharArray "jcharArray"
+%typemap(jni) jbyteArray "jbyteArray"
+%typemap(jni) jshortArray "jshortArray"
+%typemap(jni) jintArray "jintArray"
+%typemap(jni) jlongArray "jlongArray"
+%typemap(jni) jfloatArray "jfloatArray"
+%typemap(jni) jdoubleArray "jdoubleArray"
+%typemap(jni) jobjectArray "jobjectArray"
+
+%typemap(jtype) jboolean "boolean"
+%typemap(jtype) jchar "char"
+%typemap(jtype) jbyte "byte"
+%typemap(jtype) jshort "short"
+%typemap(jtype) jint "int"
+%typemap(jtype) jlong "long"
+%typemap(jtype) jfloat "float"
+%typemap(jtype) jdouble "double"
+%typemap(jtype) jstring "String"
+%typemap(jtype) jobject "java.lang.Object"
+%typemap(jtype) jbooleanArray "boolean[]"
+%typemap(jtype) jcharArray "char[]"
+%typemap(jtype) jbyteArray "byte[]"
+%typemap(jtype) jshortArray "short[]"
+%typemap(jtype) jintArray "int[]"
+%typemap(jtype) jlongArray "long[]"
+%typemap(jtype) jfloatArray "float[]"
+%typemap(jtype) jdoubleArray "double[]"
+%typemap(jtype) jobjectArray "java.lang.Object[]"
+
+%typemap(jstype) jboolean "boolean"
+%typemap(jstype) jchar "char"
+%typemap(jstype) jbyte "byte"
+%typemap(jstype) jshort "short"
+%typemap(jstype) jint "int"
+%typemap(jstype) jlong "long"
+%typemap(jstype) jfloat "float"
+%typemap(jstype) jdouble "double"
+%typemap(jstype) jstring "String"
+%typemap(jstype) jobject "java.lang.Object"
+%typemap(jstype) jbooleanArray "boolean[]"
+%typemap(jstype) jcharArray "char[]"
+%typemap(jstype) jbyteArray "byte[]"
+%typemap(jstype) jshortArray "short[]"
+%typemap(jstype) jintArray "int[]"
+%typemap(jstype) jlongArray "long[]"
+%typemap(jstype) jfloatArray "float[]"
+%typemap(jstype) jdoubleArray "double[]"
+%typemap(jstype) jobjectArray "java.lang.Object[]"
+
+/* Non primitive types */
+%typemap(jni) SWIGTYPE "jlong"
+%typemap(jtype) SWIGTYPE "long"
+%typemap(jstype) SWIGTYPE "$&javaclassname"
+%typemap(jboxtype) SWIGTYPE "$typemap(jstype, $1_type)"
+
+%typemap(jni) SWIGTYPE [] "jlong"
+%typemap(jtype) SWIGTYPE [] "long"
+%typemap(jstype) SWIGTYPE [] "$javaclassname"
+
+%typemap(jni) SWIGTYPE * "jlong"
+%typemap(jtype) SWIGTYPE * "long"
+%typemap(jstype) SWIGTYPE * "$javaclassname"
+
+%typemap(jni) SWIGTYPE & "jlong"
+%typemap(jtype) SWIGTYPE & "long"
+%typemap(jstype) SWIGTYPE & "$javaclassname"
+
+%typemap(jni) SWIGTYPE && "jlong"
+%typemap(jtype) SWIGTYPE && "long"
+%typemap(jstype) SWIGTYPE && "$javaclassname"
+
+/* pointer to a class member */
+%typemap(jni) SWIGTYPE (CLASS::*) "jstring"
+%typemap(jtype) SWIGTYPE (CLASS::*) "String"
+%typemap(jstype) SWIGTYPE (CLASS::*) "$javaclassname"
+
+/* The following are the in, out, freearg, argout typemaps. These are the JNI code generating typemaps for converting from Java to C and visa versa. */
+
+/* primitive types */
+%typemap(in) bool
+%{ $1 = $input ? true : false; %}
+
+%typemap(directorout) bool
+%{ $result = $input ? true : false; %}
+
+%typemap(javadirectorin) bool "$jniinput"
+%typemap(javadirectorout) bool "$javacall"
+
+%typemap(in) char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ float,
+ double
+%{ $1 = ($1_ltype)$input; %}
+
+%typemap(directorout) char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ float,
+ double
+%{ $result = ($1_ltype)$input; %}
+
+%typemap(directorin, descriptor="Z") bool "$input = (jboolean) $1;"
+%typemap(directorin, descriptor="C") char "$input = (jint) $1;"
+%typemap(directorin, descriptor="B") signed char "$input = (jbyte) $1;"
+%typemap(directorin, descriptor="S") unsigned char "$input = (jshort) $1;"
+%typemap(directorin, descriptor="S") short "$input = (jshort) $1;"
+%typemap(directorin, descriptor="I") unsigned short "$input = (jint) $1;"
+%typemap(directorin, descriptor="I") int "$input = (jint) $1;"
+%typemap(directorin, descriptor="J") unsigned int "$input = (jlong) $1;"
+%typemap(directorin, descriptor="I") long "$input = (jint) $1;"
+%typemap(directorin, descriptor="J") unsigned long "$input = (jlong) $1;"
+%typemap(directorin, descriptor="J") long long "$input = (jlong) $1;"
+%typemap(directorin, descriptor="F") float "$input = (jfloat) $1;"
+%typemap(directorin, descriptor="D") double "$input = (jdouble) $1;"
+
+%typemap(javadirectorin) char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ float,
+ double
+ "$jniinput"
+
+%typemap(javadirectorout) char,
+ signed char,
+ unsigned char,
+ short,
+ unsigned short,
+ int,
+ unsigned int,
+ long,
+ unsigned long,
+ long long,
+ float,
+ double
+ "$javacall"
+
+%typemap(out) bool %{ $result = (jboolean)$1; %}
+%typemap(out) char %{ $result = (jchar)$1; %}
+%typemap(out) signed char %{ $result = (jbyte)$1; %}
+%typemap(out) unsigned char %{ $result = (jshort)$1; %}
+%typemap(out) short %{ $result = (jshort)$1; %}
+%typemap(out) unsigned short %{ $result = (jint)$1; %}
+%typemap(out) int %{ $result = (jint)$1; %}
+%typemap(out) unsigned int %{ $result = (jlong)$1; %}
+%typemap(out) long %{ $result = (jint)$1; %}
+%typemap(out) unsigned long %{ $result = (jlong)$1; %}
+%typemap(out) long long %{ $result = (jlong)$1; %}
+%typemap(out) float %{ $result = (jfloat)$1; %}
+%typemap(out) double %{ $result = (jdouble)$1; %}
+
+/* unsigned long long */
+/* Convert from BigInteger using the toByteArray member function */
+%typemap(in) unsigned long long {
+ jclass clazz;
+ jmethodID mid;
+ jbyteArray ba;
+ jbyte* bae;
+ jsize sz;
+ int i;
+
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "BigInteger null");
+ return $null;
+ }
+ clazz = JCALL1(GetObjectClass, jenv, $input);
+ mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
+ ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, $input, mid);
+ bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ sz = JCALL1(GetArrayLength, jenv, ba);
+ $1 = 0;
+ if (sz > 0) {
+ $1 = ($1_type)(signed char)bae[0];
+ for(i=1; i<sz; i++) {
+ $1 = ($1 << 8) | ($1_type)(unsigned char)bae[i];
+ }
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+}
+
+%typemap(directorout) unsigned long long {
+ jclass clazz;
+ jmethodID mid;
+ jbyteArray ba;
+ jbyte* bae;
+ jsize sz;
+ int i;
+
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "BigInteger null");
+ return $null;
+ }
+ clazz = JCALL1(GetObjectClass, jenv, $input);
+ mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
+ ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, $input, mid);
+ bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ sz = JCALL1(GetArrayLength, jenv, ba);
+ $result = 0;
+ if (sz > 0) {
+ $result = ($1_type)(signed char)bae[0];
+ for(i=1; i<sz; i++) {
+ $result = ($result << 8) | ($1_type)(unsigned char)bae[i];
+ }
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+}
+
+
+/* Convert to BigInteger - byte array holds number in 2's complement big endian format */
+%typemap(out) unsigned long long {
+ jbyteArray ba = JCALL1(NewByteArray, jenv, 9);
+ jbyte* bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ jclass clazz = JCALL1(FindClass, jenv, "java/math/BigInteger");
+ jmethodID mid = JCALL3(GetMethodID, jenv, clazz, "<init>", "([B)V");
+ jobject bigint;
+ int i;
+
+ bae[0] = 0;
+ for(i=1; i<9; i++ ) {
+ bae[i] = (jbyte)($1>>8*(8-i));
+ }
+
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+ bigint = JCALL3(NewObject, jenv, clazz, mid, ba);
+ JCALL1(DeleteLocalRef, jenv, ba);
+ $result = bigint;
+}
+
+/* Convert to BigInteger (see out typemap) */
+%typemap(directorin, descriptor="Ljava/math/BigInteger;", noblock=1) unsigned long long, const unsigned long long & {
+{
+ jbyteArray ba = JCALL1(NewByteArray, jenv, 9);
+ jbyte* bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ jclass clazz = JCALL1(FindClass, jenv, "java/math/BigInteger");
+ jmethodID mid = JCALL3(GetMethodID, jenv, clazz, "<init>", "([B)V");
+ jobject bigint;
+ int swig_i;
+
+ bae[0] = 0;
+ for(swig_i=1; swig_i<9; swig_i++ ) {
+ bae[swig_i] = (jbyte)($1>>8*(8-swig_i));
+ }
+
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+ bigint = JCALL3(NewObject, jenv, clazz, mid, ba);
+ JCALL1(DeleteLocalRef, jenv, ba);
+ $input = bigint;
+}
+Swig::LocalRefGuard $1_refguard(jenv, $input); }
+
+%typemap(javadirectorin) unsigned long long "$jniinput"
+%typemap(javadirectorout) unsigned long long "$javacall"
+
+/* char * - treat as String */
+%typemap(in, noblock=1) char * {
+ $1 = 0;
+ if ($input) {
+ $1 = ($1_ltype)JCALL2(GetStringUTFChars, jenv, $input, 0);
+ if (!$1) return $null;
+ }
+}
+
+%typemap(directorout, noblock=1, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) char * {
+ $1 = 0;
+ if ($input) {
+ $result = ($1_ltype)JCALL2(GetStringUTFChars, jenv, $input, 0);
+ if (!$result) return $null;
+ }
+}
+
+%typemap(directorin, descriptor="Ljava/lang/String;", noblock=1) char * {
+ $input = 0;
+ if ($1) {
+ $input = JCALL1(NewStringUTF, jenv, (const char *)$1);
+ if (!$input) return $null;
+ }
+ Swig::LocalRefGuard $1_refguard(jenv, $input);
+}
+
+%typemap(freearg, noblock=1) char * { if ($1) JCALL2(ReleaseStringUTFChars, jenv, $input, (const char *)$1); }
+%typemap(out, noblock=1) char * { if ($1) $result = JCALL1(NewStringUTF, jenv, (const char *)$1); }
+%typemap(javadirectorin) char * "$jniinput"
+%typemap(javadirectorout) char * "$javacall"
+
+/* char *& - treat as String */
+%typemap(in, noblock=1) char *& ($*1_ltype temp = 0) {
+ $1 = 0;
+ if ($input) {
+ temp = ($*1_ltype)JCALL2(GetStringUTFChars, jenv, $input, 0);
+ if (!temp) return $null;
+ }
+ $1 = &temp;
+}
+%typemap(freearg, noblock=1) char *& { if ($1 && *$1) JCALL2(ReleaseStringUTFChars, jenv, $input, (const char *)*$1); }
+%typemap(out, noblock=1) char *& { if (*$1) $result = JCALL1(NewStringUTF, jenv, (const char *)*$1); }
+
+%typemap(out) void ""
+%typemap(javadirectorin) void "$jniinput"
+%typemap(javadirectorout) void "$javacall"
+%typemap(directorin, descriptor="V") void ""
+
+/* primitive types by reference */
+%typemap(in) const bool & ($*1_ltype temp)
+%{ temp = $input ? true : false;
+ $1 = &temp; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const bool &
+%{ static $*1_ltype temp;
+ temp = $input ? true : false;
+ $result = &temp; %}
+
+%typemap(javadirectorin) const bool & "$jniinput"
+%typemap(javadirectorout) const bool & "$javacall"
+
+%typemap(in) const char & ($*1_ltype temp),
+ const signed char & ($*1_ltype temp),
+ const unsigned char & ($*1_ltype temp),
+ const short & ($*1_ltype temp),
+ const unsigned short & ($*1_ltype temp),
+ const int & ($*1_ltype temp),
+ const unsigned int & ($*1_ltype temp),
+ const long & ($*1_ltype temp),
+ const unsigned long & ($*1_ltype temp),
+ const long long & ($*1_ltype temp),
+ const float & ($*1_ltype temp),
+ const double & ($*1_ltype temp)
+%{ temp = ($*1_ltype)$input;
+ $1 = &temp; %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const char &,
+ const signed char &,
+ const unsigned char &,
+ const short &,
+ const unsigned short &,
+ const int &,
+ const unsigned int &,
+ const long &,
+ const unsigned long &,
+ const long long &,
+ const float &,
+ const double &
+%{ static $*1_ltype temp;
+ temp = ($*1_ltype)$input;
+ $result = &temp; %}
+
+%typemap(directorin, descriptor="Z") const bool & "$input = (jboolean)$1;"
+%typemap(directorin, descriptor="C") const char & "$input = (jchar)$1;"
+%typemap(directorin, descriptor="B") const signed char & "$input = (jbyte)$1;"
+%typemap(directorin, descriptor="S") const unsigned char & "$input = (jshort)$1;"
+%typemap(directorin, descriptor="S") const short & "$input = (jshort)$1;"
+%typemap(directorin, descriptor="I") const unsigned short & "$input = (jint)$1;"
+%typemap(directorin, descriptor="I") const int & "$input = (jint)$1;"
+%typemap(directorin, descriptor="J") const unsigned int & "$input = (jlong)$1;"
+%typemap(directorin, descriptor="I") const long & "$input = (jint)$1;"
+%typemap(directorin, descriptor="J") const unsigned long & "$input = (jlong)$1;"
+%typemap(directorin, descriptor="J") const long long & "$input = (jlong)$1;"
+%typemap(directorin, descriptor="F") const float & "$input = (jfloat)$1;"
+%typemap(directorin, descriptor="D") const double & "$input = (jdouble)$1;"
+
+%typemap(javadirectorin) const char & ($*1_ltype temp),
+ const signed char & ($*1_ltype temp),
+ const unsigned char & ($*1_ltype temp),
+ const short & ($*1_ltype temp),
+ const unsigned short & ($*1_ltype temp),
+ const int & ($*1_ltype temp),
+ const unsigned int & ($*1_ltype temp),
+ const long & ($*1_ltype temp),
+ const unsigned long & ($*1_ltype temp),
+ const long long & ($*1_ltype temp),
+ const float & ($*1_ltype temp),
+ const double & ($*1_ltype temp)
+ "$jniinput"
+
+%typemap(javadirectorout) const char & ($*1_ltype temp),
+ const signed char & ($*1_ltype temp),
+ const unsigned char & ($*1_ltype temp),
+ const short & ($*1_ltype temp),
+ const unsigned short & ($*1_ltype temp),
+ const int & ($*1_ltype temp),
+ const unsigned int & ($*1_ltype temp),
+ const long & ($*1_ltype temp),
+ const unsigned long & ($*1_ltype temp),
+ const long long & ($*1_ltype temp),
+ const float & ($*1_ltype temp),
+ const double & ($*1_ltype temp)
+ "$javacall"
+
+
+%typemap(out) const bool & %{ $result = (jboolean)*$1; %}
+%typemap(out) const char & %{ $result = (jchar)*$1; %}
+%typemap(out) const signed char & %{ $result = (jbyte)*$1; %}
+%typemap(out) const unsigned char & %{ $result = (jshort)*$1; %}
+%typemap(out) const short & %{ $result = (jshort)*$1; %}
+%typemap(out) const unsigned short & %{ $result = (jint)*$1; %}
+%typemap(out) const int & %{ $result = (jint)*$1; %}
+%typemap(out) const unsigned int & %{ $result = (jlong)*$1; %}
+%typemap(out) const long & %{ $result = (jint)*$1; %}
+%typemap(out) const unsigned long & %{ $result = (jlong)*$1; %}
+%typemap(out) const long long & %{ $result = (jlong)*$1; %}
+%typemap(out) const float & %{ $result = (jfloat)*$1; %}
+%typemap(out) const double & %{ $result = (jdouble)*$1; %}
+
+/* const unsigned long long & */
+/* Similar to unsigned long long */
+%typemap(in) const unsigned long long & ($*1_ltype temp) {
+ jclass clazz;
+ jmethodID mid;
+ jbyteArray ba;
+ jbyte* bae;
+ jsize sz;
+ int i;
+
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "BigInteger null");
+ return $null;
+ }
+ clazz = JCALL1(GetObjectClass, jenv, $input);
+ mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
+ ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, $input, mid);
+ bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ sz = JCALL1(GetArrayLength, jenv, ba);
+ $1 = &temp;
+ temp = 0;
+ if (sz > 0) {
+ temp = ($*1_ltype)(signed char)bae[0];
+ for(i=1; i<sz; i++) {
+ temp = (temp << 8) | ($*1_ltype)(unsigned char)bae[i];
+ }
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const unsigned long long & {
+ static $*1_ltype temp;
+ jclass clazz;
+ jmethodID mid;
+ jbyteArray ba;
+ jbyte* bae;
+ jsize sz;
+ int i;
+
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "BigInteger null");
+ return $null;
+ }
+ clazz = JCALL1(GetObjectClass, jenv, $input);
+ mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
+ ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, $input, mid);
+ bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ sz = JCALL1(GetArrayLength, jenv, ba);
+ $result = &temp;
+ temp = 0;
+ if (sz > 0) {
+ temp = ($*1_ltype)(signed char)bae[0];
+ for(i=1; i<sz; i++) {
+ temp = (temp << 8) | ($*1_ltype)(unsigned char)bae[i];
+ }
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+}
+
+%typemap(out) const unsigned long long & {
+ jbyteArray ba = JCALL1(NewByteArray, jenv, 9);
+ jbyte* bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ jclass clazz = JCALL1(FindClass, jenv, "java/math/BigInteger");
+ jmethodID mid = JCALL3(GetMethodID, jenv, clazz, "<init>", "([B)V");
+ jobject bigint;
+ int i;
+
+ bae[0] = 0;
+ for(i=1; i<9; i++ ) {
+ bae[i] = (jbyte)(*$1>>8*(8-i));
+ }
+
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+ bigint = JCALL3(NewObject, jenv, clazz, mid, ba);
+ JCALL1(DeleteLocalRef, jenv, ba);
+ $result = bigint;
+}
+
+%typemap(javadirectorin) const unsigned long long & "$jniinput"
+%typemap(javadirectorout) const unsigned long long & "$javacall"
+
+/* Default handling. Object passed by value. Convert to a pointer */
+%typemap(in) SWIGTYPE ($&1_type argp)
+%{ argp = *($&1_ltype*)&$input;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
+ return $null;
+ }
+ $1 = *argp; %}
+
+%typemap(directorout) SWIGTYPE ($&1_type argp)
+%{ argp = *($&1_ltype*)&$input;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Unexpected null return for type $1_type");
+ return $null;
+ }
+ $result = *argp; %}
+
+%typemap(out) SWIGTYPE
+#ifdef __cplusplus
+%{ *($&1_ltype*)&$result = new $1_ltype($1); %}
+#else
+{
+ $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));
+ memmove($1ptr, &$1, sizeof($1_type));
+ *($&1_ltype*)&$result = $1ptr;
+}
+#endif
+
+%typemap(directorin,descriptor="L$packagepath/$&javaclassname;") SWIGTYPE
+%{ $input = 0;
+ *(($&1_ltype*)&$input) = new $1_ltype(SWIG_STD_MOVE($1)); %}
+%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, true)"
+%typemap(javadirectorout) SWIGTYPE "$&javaclassname.getCPtr($javacall)"
+
+/* Generic pointers and references */
+%typemap(in) SWIGTYPE * %{ $1 = *($&1_ltype)&$input; %}
+%typemap(in, fragment="SWIG_UnPackData") SWIGTYPE (CLASS::*) {
+ const char *temp = 0;
+ if ($input) {
+ temp = JCALL2(GetStringUTFChars, jenv, $input, 0);
+ if (!temp) return $null;
+ }
+ SWIG_UnpackData(temp, (void *)&$1, sizeof($1));
+}
+%typemap(in) SWIGTYPE & %{ $1 = *($&1_ltype)&$input;
+ if (!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type is null");
+ return $null;
+ } %}
+%typemap(in, fragment="<memory>") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{ $1 = *($&1_ltype)&$input;
+ if (!$1) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type is null");
+ return $null;
+ }
+ rvrdeleter.reset($1); %}
+%typemap(out) SWIGTYPE *
+%{ *($&1_ltype)&$result = $1; %}
+%typemap(out, fragment="SWIG_PackData", noblock=1) SWIGTYPE (CLASS::*) {
+ char buf[128];
+ char *data = SWIG_PackData(buf, (void *)&$1, sizeof($1));
+ *data = '\0';
+ $result = JCALL1(NewStringUTF, jenv, buf);
+}
+%typemap(out) SWIGTYPE &
+%{ *($&1_ltype)&$result = $1; %}
+%typemap(out) SWIGTYPE &&
+%{ *($&1_ltype)&$result = $1; %}
+
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE *
+%{ $result = *($&1_ltype)&$input; %}
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE (CLASS::*)
+%{ $result = *($&1_ltype)&$input; %}
+
+%typemap(directorin,descriptor="L$packagepath/$javaclassname;") SWIGTYPE *
+%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
+%typemap(directorin,descriptor="L$packagepath/$javaclassname;") SWIGTYPE (CLASS::*)
+%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
+
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE &
+%{ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Unexpected null return for type $1_type");
+ return $null;
+ }
+ $result = *($&1_ltype)&$input; %}
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) SWIGTYPE &&
+%{ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Unexpected null return for type $1_type");
+ return $null;
+ }
+ $result = *($&1_ltype)&$input; %}
+%typemap(directorin,descriptor="L$packagepath/$javaclassname;") SWIGTYPE &
+%{ *($&1_ltype)&$input = ($1_ltype) &$1; %}
+%typemap(directorin,descriptor="L$packagepath/$javaclassname;") SWIGTYPE &&
+%{ *($&1_ltype)&$input = ($1_ltype) &$1; %}
+
+%typemap(javadirectorin) SWIGTYPE *, SWIGTYPE (CLASS::*) "($jniinput == 0) ? null : new $javaclassname($jniinput, false)"
+%typemap(javadirectorin) SWIGTYPE & "new $javaclassname($jniinput, false)"
+%typemap(javadirectorin) SWIGTYPE && "new $javaclassname($jniinput, false)"
+%typemap(javadirectorout) SWIGTYPE *, SWIGTYPE (CLASS::*), SWIGTYPE &, SWIGTYPE && "$javaclassname.getCPtr($javacall)"
+
+/* Default array handling */
+%typemap(in) SWIGTYPE [] %{ $1 = *($&1_ltype)&$input; %}
+%typemap(out) SWIGTYPE [] %{ *($&1_ltype)&$result = $1; %}
+%typemap(freearg) SWIGTYPE [ANY], SWIGTYPE [] ""
+
+/* char arrays - treat as String */
+%typemap(in, noblock=1) char[ANY], char[] {
+ $1 = 0;
+ if ($input) {
+ $1 = ($1_ltype)JCALL2(GetStringUTFChars, jenv, $input, 0);
+ if (!$1) return $null;
+ }
+}
+
+%typemap(directorout, noblock=1) char[ANY], char[] {
+ $1 = 0;
+ if ($input) {
+ $result = ($1_ltype)JCALL2(GetStringUTFChars, jenv, $input, 0);
+ if (!$result) return $null;
+ }
+}
+
+%typemap(directorin, descriptor="Ljava/lang/String;", noblock=1) char[ANY], char[] {
+ $input = 0;
+ if ($1) {
+ $input = JCALL1(NewStringUTF, jenv, (const char *)$1);
+ if (!$input) return $null;
+ }
+ Swig::LocalRefGuard $1_refguard(jenv, $input);
+}
+
+%typemap(argout) char[ANY], char[] ""
+%typemap(freearg, noblock=1) char[ANY], char[] { if ($1) JCALL2(ReleaseStringUTFChars, jenv, $input, (const char *)$1); }
+%typemap(out, noblock=1) char[ANY], char[] { if ($1) $result = JCALL1(NewStringUTF, jenv, (const char *)$1); }
+%typemap(javadirectorin) char[ANY], char[] "$jniinput"
+%typemap(javadirectorout) char[ANY], char[] "$javacall"
+
+/* JNI types */
+%typemap(in) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray
+%{ $1 = $input; %}
+
+%typemap(directorout) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray
+%{ $result = $input; %}
+
+%typemap(out) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray
+%{ $result = $1; %}
+
+%typemap(directorin,descriptor="Z") jboolean "$input = $1;"
+%typemap(directorin,descriptor="C") jchar "$input = $1;"
+%typemap(directorin,descriptor="B") jbyte "$input = $1;"
+%typemap(directorin,descriptor="S") jshort "$input = $1;"
+%typemap(directorin,descriptor="I") jint "$input = $1;"
+%typemap(directorin,descriptor="J") jlong "$input = $1;"
+%typemap(directorin,descriptor="F") jfloat "$input = $1;"
+%typemap(directorin,descriptor="D") jdouble "$input = $1;"
+%typemap(directorin,descriptor="Ljava/lang/String;") jstring "$input = $1;"
+%typemap(directorin,descriptor="Ljava/lang/Object;",nouse="1") jobject "$input = $1;"
+%typemap(directorin,descriptor="[Z") jbooleanArray "$input = $1;"
+%typemap(directorin,descriptor="[C") jcharArray "$input = $1;"
+%typemap(directorin,descriptor="[B") jbyteArray "$input = $1;"
+%typemap(directorin,descriptor="[S") jshortArray "$input = $1;"
+%typemap(directorin,descriptor="[I") jintArray "$input = $1;"
+%typemap(directorin,descriptor="[J") jlongArray "$input = $1;"
+%typemap(directorin,descriptor="[F") jfloatArray "$input = $1;"
+%typemap(directorin,descriptor="[D") jdoubleArray "$input = $1;"
+%typemap(directorin,descriptor="[Ljava/lang/Object;",nouse="1") jobjectArray "$input = $1;"
+
+%typemap(javadirectorin) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray
+ "$jniinput"
+
+%typemap(javadirectorout) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray
+ "$javacall"
+
+/* Typecheck typemaps - The purpose of these is merely to issue a warning for overloaded C++ functions
+ * that cannot be overloaded in Java as more than one C++ type maps to a single Java type */
+
+%typecheck(SWIG_TYPECHECK_BOOL) /* Java boolean */
+ jboolean,
+ bool,
+ const bool &
+ ""
+
+%typecheck(SWIG_TYPECHECK_CHAR) /* Java char */
+ jchar,
+ char,
+ const char &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT8) /* Java byte */
+ jbyte,
+ signed char,
+ const signed char &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT16) /* Java short */
+ jshort,
+ unsigned char,
+ short,
+ const unsigned char &,
+ const short &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT32) /* Java int */
+ jint,
+ unsigned short,
+ int,
+ long,
+ const unsigned short &,
+ const int &,
+ const long &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT64) /* Java long */
+ jlong,
+ unsigned int,
+ unsigned long,
+ long long,
+ const unsigned int &,
+ const unsigned long &,
+ const long long &
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT128) /* Java BigInteger */
+ unsigned long long,
+ const unsigned long long &
+ ""
+
+%typecheck(SWIG_TYPECHECK_FLOAT) /* Java float */
+ jfloat,
+ float,
+ const float &
+ ""
+
+%typecheck(SWIG_TYPECHECK_DOUBLE) /* Java double */
+ jdouble,
+ double,
+ const double &
+ ""
+
+%typecheck(SWIG_TYPECHECK_STRING) /* Java String */
+ jstring,
+ char *,
+ char *&,
+ char[ANY],
+ char []
+ ""
+
+%typecheck(SWIG_TYPECHECK_BOOL_ARRAY) /* Java boolean[] */
+ jbooleanArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_CHAR_ARRAY) /* Java char[] */
+ jcharArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT8_ARRAY) /* Java byte[] */
+ jbyteArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT16_ARRAY) /* Java short[] */
+ jshortArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT32_ARRAY) /* Java int[] */
+ jintArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_INT64_ARRAY) /* Java long[] */
+ jlongArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_FLOAT_ARRAY) /* Java float[] */
+ jfloatArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY) /* Java double[] */
+ jdoubleArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_OBJECT_ARRAY) /* Java jobject[] */
+ jobjectArray
+ ""
+
+%typecheck(SWIG_TYPECHECK_POINTER) /* Default */
+ SWIGTYPE,
+ SWIGTYPE *,
+ SWIGTYPE &,
+ SWIGTYPE &&,
+ SWIGTYPE *const&,
+ SWIGTYPE [],
+ SWIGTYPE (CLASS::*)
+ ""
+
+
+/* Exception handling */
+
+%typemap(throws) int,
+ long,
+ short,
+ unsigned int,
+ unsigned long,
+ unsigned short
+%{ char error_msg[256];
+ SWIG_snprintf(error_msg, sizeof(error_msg), "C++ $1_type exception thrown, value: %d", $1);
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, error_msg);
+ return $null; %}
+
+%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY]
+%{ (void)$1;
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "C++ $1_type exception thrown");
+ return $null; %}
+
+%typemap(throws) char *
+%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1);
+ return $null; %}
+
+/* For methods to raise/throw the original Java exception thrown in a director method */
+%typemap(throws) Swig::DirectorException
+%{ $1.throwException(jenv);
+ return $null; %}
+
+/* Java to C++ DirectorException should already be handled. Suppress warning and do nothing in the
+ event a user specifies a global: %catches(Swig::DirectorException); */
+%typemap(directorthrows) Swig::DirectorException ""
+
+/* Typemaps for code generation in proxy classes and Java type wrapper classes */
+
+/* The javain typemap is used for converting function parameter types from the type
+ * used in the proxy, module or type wrapper class to the type used in the JNI class. */
+%typemap(javain) bool, const bool &,
+ char, const char &,
+ signed char, const signed char &,
+ unsigned char, const unsigned char &,
+ short, const short &,
+ unsigned short, const unsigned short &,
+ int, const int &,
+ unsigned int, const unsigned int &,
+ long, const long &,
+ unsigned long, const unsigned long &,
+ long long, const long long &,
+ unsigned long long, const unsigned long long &,
+ float, const float &,
+ double, const double &
+ "$javainput"
+%typemap(javain) char *, char *&, char[ANY], char[] "$javainput"
+%typemap(javain) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray
+ "$javainput"
+%typemap(javain) SWIGTYPE "$&javaclassname.getCPtr($javainput)"
+%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "$javaclassname.getCPtr($javainput)"
+%typemap(javain) SWIGTYPE && "$javaclassname.swigRelease($javainput)"
+%typemap(javain) SWIGTYPE (CLASS::*) "$javaclassname.getCMemberPtr($javainput)"
+
+/* The javaout typemap is used for converting function return types from the return type
+ * used in the JNI class to the type returned by the proxy, module or type wrapper class. */
+%typemap(javaout) bool, const bool &,
+ char, const char &,
+ signed char, const signed char &,
+ unsigned char, const unsigned char &,
+ short, const short &,
+ unsigned short, const unsigned short &,
+ int, const int &,
+ unsigned int, const unsigned int &,
+ long, const long &,
+ unsigned long, const unsigned long &,
+ long long, const long long &,
+ unsigned long long, const unsigned long long &,
+ float, const float &,
+ double, const double & {
+ return $jnicall;
+ }
+%typemap(javaout) char *, char *&, char[ANY], char[] {
+ return $jnicall;
+ }
+%typemap(javaout) jboolean,
+ jchar,
+ jbyte,
+ jshort,
+ jint,
+ jlong,
+ jfloat,
+ jdouble,
+ jstring,
+ jobject,
+ jbooleanArray,
+ jcharArray,
+ jbyteArray,
+ jshortArray,
+ jintArray,
+ jlongArray,
+ jfloatArray,
+ jdoubleArray,
+ jobjectArray {
+ return $jnicall;
+ }
+%typemap(javaout) void {
+ $jnicall;
+ }
+%typemap(javaout) SWIGTYPE {
+ return new $&javaclassname($jnicall, true);
+ }
+%typemap(javaout) SWIGTYPE & {
+ return new $javaclassname($jnicall, $owner);
+ }
+%typemap(javaout) SWIGTYPE && {
+ return new $javaclassname($jnicall, $owner);
+ }
+%typemap(javaout) SWIGTYPE *, SWIGTYPE [] {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $javaclassname(cPtr, $owner);
+ }
+%typemap(javaout) SWIGTYPE (CLASS::*) {
+ String cMemberPtr = $jnicall;
+ return (cMemberPtr == null) ? null : new $javaclassname(cMemberPtr, $owner);
+ }
+
+/* Pointer reference typemaps */
+%typemap(jni) SWIGTYPE *const& "jlong"
+%typemap(jtype) SWIGTYPE *const& "long"
+%typemap(jstype) SWIGTYPE *const& "$*javaclassname"
+%typemap(javain) SWIGTYPE *const& "$*javaclassname.getCPtr($javainput)"
+%typemap(javaout) SWIGTYPE *const& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $*javaclassname(cPtr, $owner);
+ }
+%typemap(in) SWIGTYPE *const& ($*1_ltype temp = 0)
+%{ temp = *($1_ltype)&$input;
+ $1 = ($1_ltype)&temp; %}
+%typemap(out) SWIGTYPE *const&
+%{ *($1_ltype)&$result = *$1; %}
+%typemap(directorin,descriptor="L$packagepath/$*javaclassname;") SWIGTYPE *const&
+%{ *(($1_ltype)&$input) = ($*1_ltype) $1; %}
+%typemap(directorout, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) SWIGTYPE *const&
+%{ static $*1_ltype swig_temp;
+ swig_temp = *($1_ltype)&$input;
+ $result = &swig_temp; %}
+%typemap(javadirectorin) SWIGTYPE *const& "($jniinput == 0) ? null : new $*javaclassname($jniinput, false)"
+%typemap(javadirectorout) SWIGTYPE *const& "$*javaclassname.getCPtr($javacall)"
+
+/* Typemaps used for the generation of proxy and type wrapper class code */
+%typemap(javabase) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
+%typemap(javaclassmodifiers) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "public class"
+%typemap(javacode) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
+%typemap(javaimports) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
+%typemap(javainterfaces) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
+%typemap(javainterfacemodifiers) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "public interface"
+
+/* javabody typemaps */
+
+%define SWIG_JAVABODY_METHODS(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, TYPE...) SWIG_JAVABODY_PROXY(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, TYPE) %enddef // legacy name
+
+%define SWIG_JAVABODY_PROXY(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, TYPE...)
+// Base proxy classes
+%typemap(javabody) TYPE %{
+ private transient long swigCPtr;
+ protected transient boolean swigCMemOwn;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ swigCMemOwn = cMemoryOwn;
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+
+ CPTR_VISIBILITY static long swigRelease($javaclassname obj) {
+ long ptr = 0;
+ if (obj != null) {
+ if (!obj.swigCMemOwn)
+ throw new RuntimeException("Cannot release ownership as memory is not owned");
+ ptr = obj.swigCPtr;
+ obj.swigCMemOwn = false;
+ obj.delete();
+ }
+ return ptr;
+ }
+%}
+
+// Derived proxy classes
+%typemap(javabody_derived) TYPE %{
+ private transient long swigCPtr;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
+ super($imclassname.$javaclazznameSWIGUpcast(cPtr), cMemoryOwn);
+ swigCPtr = cPtr;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+
+ CPTR_VISIBILITY static long swigRelease($javaclassname obj) {
+ long ptr = 0;
+ if (obj != null) {
+ if (!obj.swigCMemOwn)
+ throw new RuntimeException("Cannot release ownership as memory is not owned");
+ ptr = obj.swigCPtr;
+ obj.swigCMemOwn = false;
+ obj.delete();
+ }
+ return ptr;
+ }
+%}
+%enddef
+
+%define SWIG_JAVABODY_TYPEWRAPPER(PTRCTOR_VISIBILITY, DEFAULTCTOR_VISIBILITY, CPTR_VISIBILITY, TYPE...)
+// Typewrapper classes
+%typemap(javabody) TYPE *, TYPE &, TYPE &&, TYPE [] %{
+ private transient long swigCPtr;
+
+ PTRCTOR_VISIBILITY $javaclassname(long cPtr, @SuppressWarnings("unused") boolean futureUse) {
+ swigCPtr = cPtr;
+ }
+
+ DEFAULTCTOR_VISIBILITY $javaclassname() {
+ swigCPtr = 0;
+ }
+
+ CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+
+ CPTR_VISIBILITY static long swigRelease($javaclassname obj) {
+ return (obj == null) ? 0 : obj.swigCPtr;
+ }
+%}
+
+%typemap(javabody) TYPE (CLASS::*) %{
+ private transient String swigCMemberPtr;
+
+ PTRCTOR_VISIBILITY $javaclassname(String cMemberPtr, @SuppressWarnings("unused") boolean futureUse) {
+ swigCMemberPtr = cMemberPtr;
+ }
+
+ DEFAULTCTOR_VISIBILITY $javaclassname() {
+ swigCMemberPtr = null;
+ }
+
+ CPTR_VISIBILITY static String getCMemberPtr($javaclassname obj) {
+ return obj.swigCMemberPtr;
+ }
+%}
+%enddef
+
+/* Set the default javabody typemaps to use protected visibility.
+ Use the macros to change to public if using multiple modules. */
+SWIG_JAVABODY_PROXY(protected, protected, SWIGTYPE)
+SWIG_JAVABODY_TYPEWRAPPER(protected, protected, protected, SWIGTYPE)
+
+%typemap(javafinalize) SWIGTYPE %{
+ @SuppressWarnings({"deprecation", "removal"})
+ protected void finalize() {
+ delete();
+ }
+%}
+
+/*
+ * Java constructor typemaps:
+ *
+ * The javaconstruct typemap is inserted when a proxy class's constructor is generated.
+ * This typemap allows control over what code is executed in the constructor as
+ * well as specifying who owns the underlying C/C++ object. Normally, Java has
+ * ownership and the underlying C/C++ object is deallocated when the Java object
+ * is finalized (swigCMemOwn is true.) If swigCMemOwn is false, C/C++ is
+ * ultimately responsible for deallocating the underlying object's memory.
+ *
+ * The SWIG_PROXY_CONSTRUCTOR macro defines the javaconstruct typemap for a proxy
+ * class for a particular TYPENAME. OWNERSHIP is passed as the value of
+ * swigCMemOwn to the pointer constructor method. WEAKREF determines which kind
+ * of Java object reference will be used by the C++ director class (WeakGlobalRef
+ * vs. GlobalRef.)
+ *
+ * The SWIG_DIRECTOR_OWNED macro sets the ownership of director-based proxy
+ * classes and the weak reference flag to false, meaning that the underlying C++
+ * object will be reclaimed by C++.
+ */
+
+%define SWIG_PROXY_CONSTRUCTOR(OWNERSHIP, WEAKREF, TYPENAME...)
+%typemap(javaconstruct,directorconnect="\n $imclassname.$javaclazznamedirector_connect(this, swigCPtr, OWNERSHIP, WEAKREF);") TYPENAME {
+ this($imcall, OWNERSHIP);$directorconnect
+ }
+%enddef
+
+%define SWIG_DIRECTOR_OWNED(TYPENAME...)
+SWIG_PROXY_CONSTRUCTOR(true, false, TYPENAME)
+%enddef
+
+// Set the default for SWIGTYPE: Java owns the C/C++ object.
+SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE)
+
+%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized", parameters="") SWIGTYPE {
+ if (swigCPtr != 0) {
+ if (swigCMemOwn) {
+ swigCMemOwn = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+ }
+
+%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized", parameters="") SWIGTYPE {
+ if (swigCPtr != 0) {
+ if (swigCMemOwn) {
+ swigCMemOwn = false;
+ $jnicall;
+ }
+ swigCPtr = 0;
+ }
+ super.delete();
+ }
+
+%typemap(directordisconnect, methodname="swigDirectorDisconnect") SWIGTYPE %{
+ protected void $methodname() {
+ swigCMemOwn = false;
+ $jnicall;
+ }
+%}
+
+%typemap(directorowner_release, methodname="swigReleaseOwnership") SWIGTYPE %{
+ public void $methodname() {
+ swigCMemOwn = false;
+ $jnicall;
+ }
+%}
+
+%typemap(directorowner_take, methodname="swigTakeOwnership") SWIGTYPE %{
+ public void $methodname() {
+ swigCMemOwn = true;
+ $jnicall;
+ }
+%}
+
+/* Java specific directives */
+#define %javaconst(flag) %feature("java:const","flag")
+#define %javaconstvalue(value) %feature("java:constvalue",value)
+#define %javaenum(wrapapproach) %feature("java:enum","wrapapproach")
+#define %javamethodmodifiers %feature("java:methodmodifiers")
+#define %javaexception(exceptionclasses) %feature("except",throws=exceptionclasses)
+#define %nojavaexception %feature("except","0",throws="")
+#define %clearjavaexception %feature("except","",throws="")
+#define %proxycode %insert("proxycode")
+
+%pragma(java) jniclassclassmodifiers="public class"
+%pragma(java) moduleclassmodifiers="public class"
+%pragma(java) constantsmodifiers="public interface"
+
+/* 64-bit architecture specific typemaps */
+#if defined(SWIGWORDSIZE64)
+%apply long long { long };
+%apply unsigned long long { unsigned long };
+%apply const long long & { const long & };
+%apply const unsigned long long & { const unsigned long & };
+#endif
+
+/* size_t maps to Java 64-bit (signed) long type */
+%apply unsigned int { size_t };
+%apply const unsigned int & { const size_t & };
+
+/* Array reference typemaps */
+%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) }
+%apply SWIGTYPE && { SWIGTYPE ((&&)[ANY]) }
+
+/* const pointers */
+%apply SWIGTYPE * { SWIGTYPE *const }
+%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) }
+%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) }
+
+/* String & length */
+%typemap(jni) (const char *STRING, size_t LENGTH) "jbyteArray"
+%typemap(jtype) (const char *STRING, size_t LENGTH) "byte[]"
+%typemap(jstype) (const char *STRING, size_t LENGTH) "String"
+%typemap(javain) (const char *STRING, size_t LENGTH) %{($javainput == null) ? null : $javainput.getBytes()%}
+%typemap(freearg) (const char *STRING, size_t LENGTH) ""
+%typemap(in) (const char *STRING, size_t LENGTH) {
+ if ($input) {
+ $1 = ($1_ltype) JCALL2(GetByteArrayElements, jenv, $input, 0);
+ $2 = ($2_type) JCALL1(GetArrayLength, jenv, $input);
+ } else {
+ $1 = 0;
+ $2 = 0;
+ }
+}
+%typemap(argout) (const char *STRING, size_t LENGTH) {
+ if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, JNI_ABORT);
+}
+%typemap(directorin, descriptor="Ljava/lang/String;", noblock=1) (const char *STRING, size_t LENGTH) {
+ $input = 0;
+ if ($1) {
+ $input = JCALL1(NewByteArray, jenv, (jsize)$2);
+ if (!$input) return $null;
+ JCALL4(SetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1);
+ }
+ Swig::LocalRefGuard $1_refguard(jenv, $input);
+}
+%typemap(javadirectorin, descriptor="[B") (const char *STRING, size_t LENGTH) "($jniinput == null) ? null : new String($jniinput)"
+%apply (const char *STRING, size_t LENGTH) { (char *STRING, size_t LENGTH) }
+/* Enable write-back for non-const version */
+%typemap(argout) (char *STRING, size_t LENGTH) {
+ if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, 0);
+}
+%typemap(directorargout, noblock=1) (char *STRING, size_t LENGTH)
+{ if ($input && $1) JCALL4(GetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1); }
+%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
+
+/* java keywords */
+%include <javakw.swg>
+
+// Default enum handling
+%include <enumtypesafe.swg>
+
diff --git a/contrib/tools/swig/Lib/java/javahead.swg b/contrib/tools/swig/Lib/java/javahead.swg
new file mode 100644
index 00000000000..758a037d171
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/javahead.swg
@@ -0,0 +1,91 @@
+/* -----------------------------------------------------------------------------
+ * javahead.swg
+ *
+ * Java support code
+ * ----------------------------------------------------------------------------- */
+
+
+/* JNI function calls require different calling conventions for C and C++. These JCALL macros are used so
+ * that the same typemaps can be used for generating code for both C and C++. The SWIG preprocessor can expand
+ * the macros thereby generating the correct calling convention. It is thus essential that all typemaps that
+ * use the macros are not within %{ %} brackets as they won't be run through the SWIG preprocessor. */
+#ifdef __cplusplus
+# define JCALL0(func, jenv) jenv->func()
+# define JCALL1(func, jenv, ar1) jenv->func(ar1)
+# define JCALL2(func, jenv, ar1, ar2) jenv->func(ar1, ar2)
+# define JCALL3(func, jenv, ar1, ar2, ar3) jenv->func(ar1, ar2, ar3)
+# define JCALL4(func, jenv, ar1, ar2, ar3, ar4) jenv->func(ar1, ar2, ar3, ar4)
+# define JCALL5(func, jenv, ar1, ar2, ar3, ar4, ar5) jenv->func(ar1, ar2, ar3, ar4, ar5)
+# define JCALL6(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6)
+# define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7)
+#else
+# define JCALL0(func, jenv) (*jenv)->func(jenv)
+# define JCALL1(func, jenv, ar1) (*jenv)->func(jenv, ar1)
+# define JCALL2(func, jenv, ar1, ar2) (*jenv)->func(jenv, ar1, ar2)
+# define JCALL3(func, jenv, ar1, ar2, ar3) (*jenv)->func(jenv, ar1, ar2, ar3)
+# define JCALL4(func, jenv, ar1, ar2, ar3, ar4) (*jenv)->func(jenv, ar1, ar2, ar3, ar4)
+# define JCALL5(func, jenv, ar1, ar2, ar3, ar4, ar5) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5)
+# define JCALL6(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6)
+# define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7)
+#endif
+
+%insert(runtime) %{
+#include <jni.h>
+#include <stdlib.h>
+#include <string.h>
+%}
+
+%insert(runtime) %{
+/* Support for throwing Java exceptions */
+typedef enum {
+ SWIG_JavaOutOfMemoryError = 1,
+ SWIG_JavaIOException,
+ SWIG_JavaRuntimeException,
+ SWIG_JavaIndexOutOfBoundsException,
+ SWIG_JavaArithmeticException,
+ SWIG_JavaIllegalArgumentException,
+ SWIG_JavaNullPointerException,
+ SWIG_JavaDirectorPureVirtual,
+ SWIG_JavaUnknownError,
+ SWIG_JavaIllegalStateException,
+} SWIG_JavaExceptionCodes;
+
+typedef struct {
+ SWIG_JavaExceptionCodes code;
+ const char *java_exception;
+} SWIG_JavaExceptions_t;
+%}
+
+%insert(runtime) {
+static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) {
+ jclass excep;
+ static const SWIG_JavaExceptions_t java_exceptions[] = {
+ { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" },
+ { SWIG_JavaIOException, "java/io/IOException" },
+ { SWIG_JavaRuntimeException, "java/lang/RuntimeException" },
+ { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" },
+ { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" },
+ { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" },
+ { SWIG_JavaNullPointerException, "java/lang/NullPointerException" },
+ { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" },
+ { SWIG_JavaUnknownError, "java/lang/UnknownError" },
+ { SWIG_JavaIllegalStateException, "java/lang/IllegalStateException" },
+ { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" }
+ };
+ const SWIG_JavaExceptions_t *except_ptr = java_exceptions;
+
+ while (except_ptr->code != code && except_ptr->code)
+ except_ptr++;
+
+ JCALL0(ExceptionClear, jenv);
+ excep = JCALL1(FindClass, jenv, except_ptr->java_exception);
+ if (excep)
+ JCALL2(ThrowNew, jenv, excep, msg);
+}
+}
+
+%insert(runtime) %{
+/* Contract support */
+
+#define SWIG_contract_assert(nullreturn, expr, msg) do { if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } } while (0)
+%}
diff --git a/contrib/tools/swig/Lib/java/javakw.swg b/contrib/tools/swig/Lib/java/javakw.swg
new file mode 100644
index 00000000000..8a5b76eef2c
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/javakw.swg
@@ -0,0 +1,70 @@
+#ifndef JAVA_JAVAKW_SWG_
+#define JAVA_JAVAKW_SWG_
+
+/* Warnings for Java keywords */
+#define JAVAKW(x) %keywordwarn("'" `x` "' is a java keyword",rename="_%s") `x`
+
+/*
+ from
+ http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html
+*/
+
+JAVAKW(abstract);
+JAVAKW(double);
+JAVAKW(int);
+JAVAKW(strictfp);
+JAVAKW(boolean);
+JAVAKW(else);
+JAVAKW(interface);
+JAVAKW(super);
+JAVAKW(break);
+JAVAKW(extends);
+JAVAKW(long);
+JAVAKW(switch);
+JAVAKW(byte);
+JAVAKW(final);
+JAVAKW(native);
+JAVAKW(synchronized);
+JAVAKW(case);
+JAVAKW(finally);
+JAVAKW(new);
+JAVAKW(this);
+JAVAKW(catch);
+JAVAKW(float);
+JAVAKW(package);
+JAVAKW(throw);
+JAVAKW(char);
+JAVAKW(for);
+JAVAKW(private);
+JAVAKW(throws);
+JAVAKW(class);
+JAVAKW(goto);
+JAVAKW(protected);
+JAVAKW(transient);
+JAVAKW(const);
+JAVAKW(if);
+JAVAKW(public);
+JAVAKW(try);
+JAVAKW(continue);
+JAVAKW(implements);
+JAVAKW(return);
+JAVAKW(void);
+JAVAKW(default);
+JAVAKW(import);
+JAVAKW(short);
+JAVAKW(volatile);
+JAVAKW(do);
+JAVAKW(instanceof);
+JAVAKW(static);
+JAVAKW(while);
+
+
+/* others bad names */
+
+/* Note here that only *::clone() is bad, and *::clone(int) is ok */
+%namewarn("321:clone() is a java bad method name") *::clone();
+
+
+#undef JAVAKW
+
+#endif //JAVA_JAVAKW_SWG_
diff --git a/contrib/tools/swig/Lib/java/std_array.i b/contrib/tools/swig/Lib/java/std_array.i
new file mode 100644
index 00000000000..b5012dee038
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_array.i
@@ -0,0 +1,62 @@
+/* -----------------------------------------------------------------------------
+ * std_array.i
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+%fragment("SWIG_ArraySize", "header", fragment="SWIG_JavaIntFromSize_t") {
+ SWIGINTERN jint SWIG_ArraySize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1) {
+ throw std::out_of_range("array size is too large to fit into a Java int");
+ }
+
+ return sz;
+ }
+}
+
+%javamethodmodifiers std::array::sizeImpl "private";
+
+namespace std {
+
+ template<class T, size_t N> class array {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ array();
+ array(const array& other);
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void fill(const T& u);
+ %extend {
+ %fragment("SWIG_ArraySize");
+
+ jint size() const throw (std::out_of_range) {
+ return SWIG_ArraySize(self->size());
+ }
+
+ const_reference get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("array index out of range");
+ }
+ void set(int i, const value_type& val) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = val;
+ else
+ throw std::out_of_range("array index out of range");
+ }
+ }
+ };
+}
+
diff --git a/contrib/tools/swig/Lib/java/std_auto_ptr.i b/contrib/tools/swig/Lib/java/std_auto_ptr.i
new file mode 100644
index 00000000000..aee9b4828af
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_auto_ptr.i
@@ -0,0 +1,41 @@
+/* -----------------------------------------------------------------------------
+ * std_auto_ptr.i
+ *
+ * SWIG library file for handling std::auto_ptr.
+ * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
+ * class when returning a std::auto_ptr from a function.
+ * Memory ownership is passed from the proxy class to the std::auto_ptr in the
+ * C++ layer when passed as a parameter to a wrapped function.
+ * ----------------------------------------------------------------------------- */
+
+%define %auto_ptr(TYPE)
+
+%typemap (jni) std::auto_ptr< TYPE > "jlong"
+%typemap (jtype) std::auto_ptr< TYPE > "long"
+%typemap (jstype) std::auto_ptr< TYPE > "$typemap(jstype, TYPE)"
+
+%typemap(in) std::auto_ptr< TYPE > (TYPE *auto_temp)
+%{ auto_temp = *(TYPE **)&$input;
+ $1.reset(auto_temp); %}
+
+%typemap(javain) std::auto_ptr< TYPE > "$typemap(jstype, TYPE).swigRelease($javainput)"
+
+%typemap (out) std::auto_ptr< TYPE > %{
+ jlong lpp = 0;
+ *(TYPE **) &lpp = $1.release();
+ $result = lpp;
+%}
+
+%typemap(javaout) std::auto_ptr< TYPE > {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::auto_ptr< TYPE > ""
+
+%template() std::auto_ptr< TYPE >;
+%enddef
+
+namespace std {
+ template <class T> class auto_ptr {};
+}
diff --git a/contrib/tools/swig/Lib/java/std_common.i b/contrib/tools/swig/Lib/java/std_common.i
new file mode 100644
index 00000000000..cee11e8caa5
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_common.i
@@ -0,0 +1,5 @@
+%include <std_except.i>
+
+%apply size_t { std::size_t };
+%apply const size_t& { const std::size_t& };
+
diff --git a/contrib/tools/swig/Lib/java/std_deque.i b/contrib/tools/swig/Lib/java/std_deque.i
new file mode 100644
index 00000000000..cb98f6c2fb3
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_deque.i
@@ -0,0 +1 @@
+%include <std/_std_deque.i>
diff --git a/contrib/tools/swig/Lib/java/std_except.i b/contrib/tools/swig/Lib/java/std_except.i
new file mode 100644
index 00000000000..91d2f92cf14
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_except.i
@@ -0,0 +1,32 @@
+/* -----------------------------------------------------------------------------
+ * std_except.i
+ *
+ * Typemaps used by the STL wrappers that throw exceptions.
+ * These typemaps are used when methods are declared with an STL exception specification, such as
+ * size_t at() const throw (std::out_of_range);
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <typeinfo>
+#include <stdexcept>
+%}
+
+namespace std
+{
+ %ignore exception;
+ struct exception {};
+}
+
+%typemap(throws) std::bad_cast "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;"
+%typemap(throws) std::bad_exception "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;"
+%typemap(throws) std::domain_error "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;"
+%typemap(throws) std::exception "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;"
+%typemap(throws) std::invalid_argument "SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, $1.what());\n return $null;"
+%typemap(throws) std::length_error "SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, $1.what());\n return $null;"
+%typemap(throws) std::logic_error "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;"
+%typemap(throws) std::out_of_range "SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, $1.what());\n return $null;"
+%typemap(throws) std::overflow_error "SWIG_JavaThrowException(jenv, SWIG_JavaArithmeticException, $1.what());\n return $null;"
+%typemap(throws) std::range_error "SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, $1.what());\n return $null;"
+%typemap(throws) std::runtime_error "SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.what());\n return $null;"
+%typemap(throws) std::underflow_error "SWIG_JavaThrowException(jenv, SWIG_JavaArithmeticException, $1.what());\n return $null;"
+
diff --git a/contrib/tools/swig/Lib/java/std_list.i b/contrib/tools/swig/Lib/java/std_list.i
new file mode 100644
index 00000000000..896df30c0ed
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_list.i
@@ -0,0 +1,225 @@
+/* -----------------------------------------------------------------------------
+ * std_list.i
+ *
+ * SWIG typemaps for std::list.
+ * The Java proxy class extends java.util.AbstractSequentialList. The std::list
+ * container looks and feels much like a java.util.LinkedList from Java.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+%{
+#include <list>
+#include <stdexcept>
+%}
+
+%fragment("SWIG_ListSize", "header", fragment="SWIG_JavaIntFromSize_t") {
+SWIGINTERN jint SWIG_ListSize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1)
+ throw std::out_of_range("list size is too large to fit into a Java int");
+ return sz;
+}
+}
+
+%javamethodmodifiers std::list::begin "private";
+%javamethodmodifiers std::list::insert "private";
+%javamethodmodifiers std::list::doSize "private";
+%javamethodmodifiers std::list::doPreviousIndex "private";
+%javamethodmodifiers std::list::doNextIndex "private";
+%javamethodmodifiers std::list::doHasNext "private";
+
+// Match Java style better:
+%rename(Iterator) std::list::iterator;
+
+%nodefaultctor std::list::iterator;
+
+namespace std {
+ template <typename T> class list {
+
+%typemap(javabase) std::list<T> "java.util.AbstractSequentialList<$typemap(jboxtype, T)>"
+%proxycode %{
+ public $javaclassname(java.util.Collection c) {
+ this();
+ java.util.ListIterator<$typemap(jboxtype, T)> it = listIterator(0);
+ // Special case the "copy constructor" here to avoid lots of cross-language calls
+ for (java.lang.Object o : c) {
+ it.add(($typemap(jboxtype, T))o);
+ }
+ }
+
+ public int size() {
+ return doSize();
+ }
+
+ public boolean add($typemap(jboxtype, T) value) {
+ addLast(value);
+ return true;
+ }
+
+ public java.util.ListIterator<$typemap(jboxtype, T)> listIterator(int index) {
+ return new java.util.ListIterator<$typemap(jboxtype, T)>() {
+ private Iterator pos;
+ private Iterator last;
+
+ private java.util.ListIterator<$typemap(jboxtype, T)> init(int index) {
+ if (index < 0 || index > $javaclassname.this.size())
+ throw new IndexOutOfBoundsException("Index: " + index);
+ pos = $javaclassname.this.begin();
+ pos = pos.advance_unchecked(index);
+ return this;
+ }
+
+ public void add($typemap(jboxtype, T) v) {
+ // Technically we can invalidate last here, but this makes more sense
+ last = $javaclassname.this.insert(pos, v);
+ }
+
+ public void set($typemap(jboxtype, T) v) {
+ if (null == last) {
+ throw new IllegalStateException();
+ }
+ last.set_unchecked(v);
+ }
+
+ public void remove() {
+ if (null == last) {
+ throw new IllegalStateException();
+ }
+ $javaclassname.this.remove(last);
+ last = null;
+ }
+
+ public int previousIndex() {
+ return $javaclassname.this.doPreviousIndex(pos);
+ }
+
+ public int nextIndex() {
+ return $javaclassname.this.doNextIndex(pos);
+ }
+
+ public $typemap(jboxtype, T) previous() {
+ if (previousIndex() < 0) {
+ throw new java.util.NoSuchElementException();
+ }
+ last = pos;
+ pos = pos.previous_unchecked();
+ return last.deref_unchecked();
+ }
+
+ public $typemap(jboxtype, T) next() {
+ if (!hasNext()) {
+ throw new java.util.NoSuchElementException();
+ }
+ last = pos;
+ pos = pos.next_unchecked();
+ return last.deref_unchecked();
+ }
+
+ public boolean hasPrevious() {
+ // This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators
+ return previousIndex() != -1;
+ }
+
+ public boolean hasNext() {
+ return $javaclassname.this.doHasNext(pos);
+ }
+ }.init(index);
+ }
+%}
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ /*
+ * We'd actually be better off having the nested class *not* be static in the wrapper
+ * output, but this doesn't actually remove the $static from the nested class still.
+ * (This would allow us to somewhat simplify the implementation of the ListIterator
+ * interface and give "natural" semantics to Java users of the C++ iterator)
+ */
+ //%typemap(javaclassmodifiers) iterator "public class"
+ //%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, T)>"
+
+ struct iterator {
+ %extend {
+ void set_unchecked(const T &v) {
+ **$self = v;
+ }
+
+ iterator next_unchecked() const {
+ std::list<T>::iterator ret = *$self;
+ ++ret;
+ return ret;
+ }
+
+ iterator previous_unchecked() const {
+ std::list<T>::iterator ret = *$self;
+ --ret;
+ return ret;
+ }
+
+ T deref_unchecked() const {
+ return **$self;
+ }
+
+ iterator advance_unchecked(int index) const {
+ std::list<T>::iterator ret = *$self;
+ std::advance(ret, index);
+ return ret;
+ }
+ }
+ };
+
+ list();
+ list(const list& other);
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ %rename(remove) erase;
+ iterator erase(iterator pos);
+ %rename(removeLast) pop_back;
+ void pop_back();
+ %rename(removeFirst) pop_front;
+ void pop_front();
+ %rename(addLast) push_back;
+ void push_back(const T &value);
+ %rename(addFirst) push_front;
+ void push_front(const T &value);
+ iterator begin();
+ iterator end();
+ iterator insert(iterator pos, const T &value);
+
+ %extend {
+ %fragment("SWIG_ListSize");
+
+ list(jint count, const T &value) throw (std::out_of_range) {
+ if (count < 0)
+ throw std::out_of_range("list count must be positive");
+ return new std::list<T>(static_cast<std::list<T>::size_type>(count), value);
+ }
+
+ jint doSize() const throw (std::out_of_range) {
+ return SWIG_ListSize(self->size());
+ }
+
+ jint doPreviousIndex(const iterator &pos) const throw (std::out_of_range) {
+ return pos == self->begin() ? -1 : SWIG_ListSize(std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos)));
+ }
+
+ jint doNextIndex(const iterator &pos) const throw (std::out_of_range) {
+ return pos == self->end() ? SWIG_ListSize(self->size()) : SWIG_ListSize(std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos)));
+ }
+
+ bool doHasNext(const iterator &pos) const {
+ return pos != $self->end();
+ }
+ }
+ };
+}
diff --git a/contrib/tools/swig/Lib/java/std_map.i b/contrib/tools/swig/Lib/java/std_map.i
new file mode 100644
index 00000000000..5461c20429e
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_map.i
@@ -0,0 +1,215 @@
+/* -----------------------------------------------------------------------------
+ * std_map.i
+ *
+ * SWIG typemaps for std::map
+ * The Java proxy class extends java.util.AbstractMap. The std::map
+ * container looks and feels much like a java.util.HashMap from Java.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::map
+// ------------------------------------------------------------------------
+
+%{
+#include <map>
+#include <stdexcept>
+%}
+
+%fragment("SWIG_MapSize", "header", fragment="SWIG_JavaIntFromSize_t") {
+ SWIGINTERN jint SWIG_MapSize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1) {
+ throw std::out_of_range("map size is too large to fit into a Java int");
+ }
+
+ return sz;
+ }
+}
+
+%javamethodmodifiers std::map::sizeImpl "private";
+%javamethodmodifiers std::map::containsImpl "private";
+%javamethodmodifiers std::map::putUnchecked "private";
+%javamethodmodifiers std::map::removeUnchecked "private";
+%javamethodmodifiers std::map::find "private";
+%javamethodmodifiers std::map::begin "private";
+%javamethodmodifiers std::map::end "private";
+
+%rename(Iterator) std::map::iterator;
+%nodefaultctor std::map::iterator;
+%javamethodmodifiers std::map::iterator::getNextUnchecked "private";
+%javamethodmodifiers std::map::iterator::isNot "private";
+%javamethodmodifiers std::map::iterator::getKey "private";
+%javamethodmodifiers std::map::iterator::getValue "private";
+%javamethodmodifiers std::map::iterator::setValue "private";
+
+namespace std {
+
+template<class K, class T, class C = std::less< K> > class map {
+
+%typemap(javabase) std::map< K, T, C >
+ "java.util.AbstractMap<$typemap(jboxtype, K), $typemap(jboxtype, T)>"
+
+%proxycode %{
+
+ public int size() {
+ return sizeImpl();
+ }
+
+ public boolean containsKey(java.lang.Object key) {
+ if (!(key instanceof $typemap(jboxtype, K))) {
+ return false;
+ }
+
+ return containsImpl(($typemap(jboxtype, K))key);
+ }
+
+ public $typemap(jboxtype, T) get(java.lang.Object key) {
+ if (!(key instanceof $typemap(jboxtype, K))) {
+ return null;
+ }
+
+ Iterator itr = find(($typemap(jboxtype, K)) key);
+ if (itr.isNot(end())) {
+ return itr.getValue();
+ }
+
+ return null;
+ }
+
+ public $typemap(jboxtype, T) put($typemap(jboxtype, K) key, $typemap(jboxtype, T) value) {
+ Iterator itr = find(key);
+ if (itr.isNot(end())) {
+ $typemap(jboxtype, T) oldValue = itr.getValue();
+ itr.setValue(value);
+ return oldValue;
+ } else {
+ putUnchecked(key, value);
+ return null;
+ }
+ }
+
+ public $typemap(jboxtype, T) remove(java.lang.Object key) {
+ if (!(key instanceof $typemap(jboxtype, K))) {
+ return null;
+ }
+
+ Iterator itr = find(($typemap(jboxtype, K)) key);
+ if (itr.isNot(end())) {
+ $typemap(jboxtype, T) oldValue = itr.getValue();
+ removeUnchecked(itr);
+ return oldValue;
+ } else {
+ return null;
+ }
+ }
+
+ public java.util.Set<Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>> entrySet() {
+ java.util.Set<Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>> setToReturn =
+ new java.util.HashSet<Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>>();
+
+ Iterator itr = begin();
+ final Iterator end = end();
+ while (itr.isNot(end)) {
+ setToReturn.add(new Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>() {
+ private Iterator iterator;
+
+ private Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)> init(Iterator iterator) {
+ this.iterator = iterator;
+ return this;
+ }
+
+ public $typemap(jboxtype, K) getKey() {
+ return iterator.getKey();
+ }
+
+ public $typemap(jboxtype, T) getValue() {
+ return iterator.getValue();
+ }
+
+ public $typemap(jboxtype, T) setValue($typemap(jboxtype, T) newValue) {
+ $typemap(jboxtype, T) oldValue = iterator.getValue();
+ iterator.setValue(newValue);
+ return oldValue;
+ }
+ }.init(itr));
+ itr = itr.getNextUnchecked();
+ }
+
+ return setToReturn;
+ }
+%}
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef K key_type;
+ typedef T mapped_type;
+ typedef std::pair< const K, T > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ map();
+ map(const map& other);
+
+ struct iterator {
+ %typemap(javaclassmodifiers) iterator "public class"
+ %extend {
+ std::map< K, T, C >::iterator getNextUnchecked() {
+ std::map< K, T, C >::iterator copy = (*$self);
+ return ++copy;
+ }
+
+ bool isNot(iterator other) const {
+ return (*$self != other);
+ }
+
+ K getKey() const {
+ return (*$self)->first;
+ }
+
+ T getValue() const {
+ return (*$self)->second;
+ }
+
+ void setValue(const T& newValue) {
+ (*$self)->second = newValue;
+ }
+ }
+ };
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ iterator find(const K& key);
+ iterator begin();
+ iterator end();
+ %extend {
+ %fragment("SWIG_MapSize");
+
+ jint sizeImpl() const throw (std::out_of_range) {
+ return SWIG_MapSize(self->size());
+ }
+
+ bool containsImpl(const K& key) {
+ return (self->count(key) > 0);
+ }
+
+ void putUnchecked(const K& key, const T& value) {
+%#ifdef __cpp_lib_map_try_emplace
+ (*self).insert_or_assign(key, value);
+%#else
+ (*self)[key] = value;
+%#endif
+ }
+
+ void removeUnchecked(const std::map< K, T, C >::iterator itr) {
+ self->erase(itr);
+ }
+ }
+};
+
+}
diff --git a/contrib/tools/swig/Lib/java/std_pair.i b/contrib/tools/swig/Lib/java/std_pair.i
new file mode 100644
index 00000000000..75ad30315dd
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_pair.i
@@ -0,0 +1,37 @@
+/* -----------------------------------------------------------------------------
+ * std_pair.i
+ *
+ * SWIG typemaps for std::pair
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <exception.i>
+
+// ------------------------------------------------------------------------
+// std::pair
+// ------------------------------------------------------------------------
+
+%{
+#include <utility>
+%}
+
+namespace std {
+
+ template<class T, class U> struct pair {
+ typedef T first_type;
+ typedef U second_type;
+
+
+ pair();
+ pair(T first, U second);
+ pair(const pair& other);
+
+ template <class U1, class U2> pair(const pair<U1, U2> &other);
+
+ T first;
+ U second;
+ };
+
+ // add specializations here
+
+}
diff --git a/contrib/tools/swig/Lib/java/std_set.i b/contrib/tools/swig/Lib/java/std_set.i
new file mode 100644
index 00000000000..6752d4755d7
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_set.i
@@ -0,0 +1,207 @@
+/* -----------------------------------------------------------------------------
+ * std_set.i
+ *
+ * SWIG typemaps for std::set
+ * The Java proxy class extends java.util.AbstractSet. The std::set
+ * container looks and feels much like a java.util.HashSet from Java.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::set
+// ------------------------------------------------------------------------
+
+%{
+#include <set>
+#include <stdexcept>
+%}
+
+%fragment("SWIG_SetSize", "header", fragment="SWIG_JavaIntFromSize_t") {
+ SWIGINTERN jint SWIG_SetSize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1) {
+ throw std::out_of_range("set size is too large to fit into a Java int");
+ }
+
+ return sz;
+ }
+}
+
+%javamethodmodifiers std::set::sizeImpl "private";
+%javamethodmodifiers std::set::containsImpl "private";
+%javamethodmodifiers std::set::removeImpl "private";
+%javamethodmodifiers std::set::hasNextImpl "private";
+%javamethodmodifiers std::set::begin "private";
+%javamethodmodifiers std::set::end "private";
+
+%rename(Iterator) std::set::iterator;
+%nodefaultctor std::set::iterator;
+%javamethodmodifiers std::set::iterator::incrementUnchecked "private";
+%javamethodmodifiers std::set::iterator::derefUnchecked "private";
+%javamethodmodifiers std::set::iterator::isNot "private";
+
+namespace std {
+
+template <class T>
+class set {
+
+%typemap(javabase) std::set<T> "java.util.AbstractSet<$typemap(jboxtype, T)>"
+%proxycode %{
+ public $javaclassname(java.util.Collection<? extends $typemap(jboxtype, T)> collection) {
+ this();
+ addAll(collection);
+ }
+
+ public int size() {
+ return sizeImpl();
+ }
+
+ public boolean add($typemap(jboxtype, T) key) {
+ return addImpl(key);
+ }
+
+ public boolean addAll(java.util.Collection<? extends $typemap(jboxtype, T)> collection) {
+ boolean didAddElement = false;
+ for (java.lang.Object object : collection) {
+ didAddElement |= add(($typemap(jboxtype, T))object);
+ }
+
+ return didAddElement;
+ }
+
+ public java.util.Iterator<$typemap(jboxtype, T)> iterator() {
+ return new java.util.Iterator<$typemap(jboxtype, T)>() {
+ private Iterator curr;
+ private Iterator end;
+
+ private java.util.Iterator<$typemap(jboxtype, T)> init() {
+ curr = $javaclassname.this.begin();
+ end = $javaclassname.this.end();
+ return this;
+ }
+
+ public $typemap(jboxtype, T) next() {
+ if (!hasNext()) {
+ throw new java.util.NoSuchElementException();
+ }
+
+ // Save the current position, increment it,
+ // then return the value at the position before the increment.
+ final $typemap(jboxtype, T) currValue = curr.derefUnchecked();
+ curr.incrementUnchecked();
+ return currValue;
+ }
+
+ public boolean hasNext() {
+ return curr.isNot(end);
+ }
+
+ public void remove() {
+ throw new java.lang.UnsupportedOperationException();
+ }
+ }.init();
+ }
+
+ public boolean containsAll(java.util.Collection<?> collection) {
+ for (java.lang.Object object : collection) {
+ if (!contains(object)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean contains(java.lang.Object object) {
+ if (!(object instanceof $typemap(jboxtype, T))) {
+ return false;
+ }
+
+ return containsImpl(($typemap(jboxtype, T))object);
+ }
+
+ public boolean removeAll(java.util.Collection<?> collection) {
+ boolean didRemoveElement = false;
+ for (java.lang.Object object : collection) {
+ didRemoveElement |= remove(object);
+ }
+
+ return didRemoveElement;
+ }
+
+ public boolean remove(java.lang.Object object) {
+ if (!(object instanceof $typemap(jboxtype, T))) {
+ return false;
+ }
+
+ return removeImpl(($typemap(jboxtype, T))object);
+ }
+%}
+
+ public:
+
+ struct iterator {
+ %typemap(javaclassmodifiers) iterator "public class"
+ %extend {
+ void incrementUnchecked() {
+ ++(*$self);
+ }
+
+ T derefUnchecked() const {
+ return **$self;
+ }
+
+ bool isNot(iterator other) const {
+ return (*$self != other);
+ }
+ }
+ };
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T key_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ set();
+ set(const set& other);
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ iterator begin();
+ iterator end();
+
+ %extend {
+ %fragment("SWIG_SetSize");
+
+ // Returns whether item was inserted.
+ bool addImpl(const T& key) {
+ return self->insert(key).second;
+ }
+
+ // Returns whether set contains key.
+ bool containsImpl(const T& key) {
+ return (self->count(key) > 0);
+ }
+
+ // Returns whether the item was erased.
+ bool removeImpl(const T& key) {
+ return (self->erase(key) > 0);
+ }
+
+ jint sizeImpl() const throw (std::out_of_range) {
+ return SWIG_SetSize(self->size());
+ }
+
+ bool hasNextImpl(const iterator& itr) const {
+ return (itr != $self->end());
+ }
+ }
+};
+
+}
diff --git a/contrib/tools/swig/Lib/java/std_shared_ptr.i b/contrib/tools/swig/Lib/java/std_shared_ptr.i
new file mode 100644
index 00000000000..df873679c62
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_shared_ptr.i
@@ -0,0 +1,2 @@
+#define SWIG_SHARED_PTR_NAMESPACE std
+%include <boost_shared_ptr.i>
diff --git a/contrib/tools/swig/Lib/java/std_string.i b/contrib/tools/swig/Lib/java/std_string.i
new file mode 100644
index 00000000000..830a8961198
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_string.i
@@ -0,0 +1,121 @@
+/* -----------------------------------------------------------------------------
+ * std_string.i
+ *
+ * Typemaps for std::string and const std::string&
+ * These are mapped to a Java String and are passed around by value.
+ *
+ * To use non-const std::string references use the following %apply. Note
+ * that they are passed by value.
+ * %apply const std::string & {std::string &};
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <string>
+%}
+
+namespace std {
+
+%naturalvar string;
+
+class string;
+
+// string
+%typemap(jni) string "jstring"
+%typemap(jtype) string "String"
+%typemap(jstype) string "String"
+%typemap(javadirectorin) string "$jniinput"
+%typemap(javadirectorout) string "$javacall"
+
+%typemap(in) string
+%{ if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ $1.assign($1_pstr);
+ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorout) string
+%{ if(!$input) {
+ if (!jenv->ExceptionCheck()) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ }
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ $result.assign($1_pstr);
+ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorin,descriptor="Ljava/lang/String;") string
+%{ $input = jenv->NewStringUTF($1.c_str());
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(out) string
+%{ $result = jenv->NewStringUTF($1.c_str()); %}
+
+%typemap(javain) string "$javainput"
+
+%typemap(javaout) string {
+ return $jnicall;
+ }
+
+%typemap(typecheck) string = char *;
+
+%typemap(throws) string
+%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.c_str());
+ return $null; %}
+
+// const string &
+%typemap(jni) const string & "jstring"
+%typemap(jtype) const string & "String"
+%typemap(jstype) const string & "String"
+%typemap(javadirectorin) const string & "$jniinput"
+%typemap(javadirectorout) const string & "$javacall"
+
+%typemap(in) const string &
+%{ if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ $*1_ltype $1_str($1_pstr);
+ $1 = &$1_str;
+ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string &
+%{ if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ /* possible thread/reentrant code problem */
+ static $*1_ltype $1_str;
+ $1_str = $1_pstr;
+ $result = &$1_str;
+ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorin,descriptor="Ljava/lang/String;") const string &
+%{ $input = jenv->NewStringUTF($1.c_str());
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(out) const string &
+%{ $result = jenv->NewStringUTF($1->c_str()); %}
+
+%typemap(javain) const string & "$javainput"
+
+%typemap(javaout) const string & {
+ return $jnicall;
+ }
+
+%typemap(typecheck) const string & = char *;
+
+%typemap(throws) const string &
+%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, $1.c_str());
+ return $null; %}
+
+}
+
diff --git a/contrib/tools/swig/Lib/java/std_string_view.i b/contrib/tools/swig/Lib/java/std_string_view.i
new file mode 100644
index 00000000000..c89f79979d5
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_string_view.i
@@ -0,0 +1,138 @@
+/* -----------------------------------------------------------------------------
+ * std_string_view.i
+ *
+ * Typemaps for std::string_view and const std::string_view&
+ * These are mapped to a Java String and are passed around by value.
+ *
+ * To use non-const std::string_view references use the following %apply. Note
+ * that they are passed by value.
+ * %apply const std::string_view & {std::string_view &};
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <string_view>
+#include <string>
+%}
+
+namespace std {
+
+%naturalvar string_view;
+
+class string_view;
+
+// string_view
+%typemap(jni) string_view "jstring"
+%typemap(jtype) string_view "String"
+%typemap(jstype) string_view "String"
+%typemap(javadirectorin) string_view "$jniinput"
+%typemap(javadirectorout) string_view "$javacall"
+
+%typemap(in) string_view
+%{ if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ $1 = std::string_view($1_pstr); %}
+
+/* std::string_view requires the string data to remain valid while the
+ * string_view is in use. */
+%typemap(freearg) string_view
+%{ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) string_view
+%{ if(!$input) {
+ if (!jenv->ExceptionCheck()) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ }
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ /* possible thread/reentrant code problem */
+ static std::string $1_str;
+ $1_str = $1_pstr;
+ $result = std::string_view($1_str);
+ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+/* std::string_view::data() isn't zero-byte terminated, but NewStringUTF()
+ * requires a zero byte so it seems we have to make a copy (ick). The
+ * cleanest way to do that seems to be via a temporary std::string.
+ */
+%typemap(directorin,descriptor="Ljava/lang/String;") string_view
+%{ $input = jenv->NewStringUTF(std::string($1).c_str());
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(out) string_view
+%{ $result = jenv->NewStringUTF(std::string($1).c_str()); %}
+
+%typemap(javain) string_view "$javainput"
+
+%typemap(javaout) string_view {
+ return $jnicall;
+ }
+
+%typemap(typecheck) string_view = char *;
+
+%typemap(throws) string_view
+%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, std::string($1).c_str());
+ return $null; %}
+
+// const string_view &
+%typemap(jni) const string_view & "jstring"
+%typemap(jtype) const string_view & "String"
+%typemap(jstype) const string_view & "String"
+%typemap(javadirectorin) const string_view & "$jniinput"
+%typemap(javadirectorout) const string_view & "$javacall"
+
+%typemap(in) const string_view &
+%{ if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ $*1_ltype $1_str($1_pstr);
+ $1 = &$1_str; %}
+
+/* std::string_view requires the string data to remain valid while the
+ * string_view is in use. */
+%typemap(freearg) const string_view &
+%{ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string_view &
+%{ if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string");
+ return $null;
+ }
+ const char *$1_pstr = (const char *)jenv->GetStringUTFChars($input, 0);
+ if (!$1_pstr) return $null;
+ /* possible thread/reentrant code problem */
+ static std::string $1_str;
+ $1_str = $1_pstr;
+ static $*1_ltype $1_strview;
+ $1_strview = $1_str;
+ $result = &$1_strview;
+ jenv->ReleaseStringUTFChars($input, $1_pstr); %}
+
+%typemap(directorin,descriptor="Ljava/lang/String;") const string_view &
+%{ $input = jenv->NewStringUTF(std::string($1).c_str());
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(out) const string_view &
+%{ $result = jenv->NewStringUTF(std::string(*$1).c_str()); %}
+
+%typemap(javain) const string_view & "$javainput"
+
+%typemap(javaout) const string_view & {
+ return $jnicall;
+ }
+
+%typemap(typecheck) const string_view & = char *;
+
+%typemap(throws) const string_view &
+%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, std::string($1).c_str());
+ return $null; %}
+
+}
diff --git a/contrib/tools/swig/Lib/java/std_unique_ptr.i b/contrib/tools/swig/Lib/java/std_unique_ptr.i
new file mode 100644
index 00000000000..ded7b80bbc0
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_unique_ptr.i
@@ -0,0 +1,63 @@
+/* -----------------------------------------------------------------------------
+ * std_unique_ptr.i
+ *
+ * SWIG library file for handling std::unique_ptr.
+ *
+ * Returning a std::unique_ptr from a wrapped function:
+ * Memory ownership is passed (moved) from the std::unique_ptr in the C++ layer
+ * to the proxy class when returning a std::unique_ptr by value from a function.
+ * Memory ownership is not moved when returning by any sort of reference.
+ *
+ * Passing a std::unique_ptr as a parameter to a wrapped function:
+ * Memory ownership is passed from the proxy class to the std::unique_ptr in the
+ * C++ layer when passed as a parameter by value, rvalue reference or non-const
+ * lvalue reference. Memory ownership is not transferred when passing by const
+ * lvalue reference.
+ * ----------------------------------------------------------------------------- */
+
+%include <unique_ptr.swg>
+
+%define %unique_ptr(TYPE)
+
+%typemap (jni) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && "jlong"
+%typemap (jtype) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && "long"
+%typemap (jstype) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && "$typemap(jstype, TYPE)"
+
+%typemap(in) std::unique_ptr< TYPE > (TYPE *unique_temp)
+%{ unique_temp = *(TYPE **)&$input;
+ $1.reset(unique_temp); %}
+%typemap(in) std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > &&
+%{ $*1_ltype $1_uptr((TYPE *)$input);
+ $1 = &$1_uptr; %}
+%typemap(in, fragment="SwigNoDeleteUniquePtr") const std::unique_ptr< TYPE > &
+%{ swig::NoDeleteUniquePtr< TYPE > $1_ndup((TYPE *)$input);
+$1 = &$1_ndup.uptr; %}
+
+%typemap(javain) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && "$typemap(jstype, TYPE).swigRelease($javainput)"
+%typemap(javain) const std::unique_ptr< TYPE > & "$typemap(jstype, TYPE).getCPtr($javainput)"
+
+%typemap (out) std::unique_ptr< TYPE > %{
+ jlong lpp = 0;
+ *(TYPE **) &lpp = $1.release();
+ $result = lpp;
+%}
+%typemap (out) std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && %{
+ jlong lpp = 0;
+ *(TYPE **) &lpp = $1->get();
+ $result = lpp;
+%}
+
+
+%typemap(javaout) std::unique_ptr< TYPE > {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
+ }
+%typemap(javaout) std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, false);
+ }
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && ""
+
+%template() std::unique_ptr< TYPE >;
+%enddef
diff --git a/contrib/tools/swig/Lib/java/std_unordered_map.i b/contrib/tools/swig/Lib/java/std_unordered_map.i
new file mode 100644
index 00000000000..f3fdb34ae61
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_unordered_map.i
@@ -0,0 +1,215 @@
+/* -----------------------------------------------------------------------------
+ * std_unordered_map.i
+ *
+ * SWIG typemaps for std::unordered_map
+ * The Java proxy class extends java.util.AbstractMap. The std::unordered_map
+ * container looks and feels much like a java.util.HashMap from Java.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::unordered_map
+// ------------------------------------------------------------------------
+
+%{
+#include <unordered_map>
+#include <stdexcept>
+%}
+
+%fragment("SWIG_MapSize", "header", fragment="SWIG_JavaIntFromSize_t") {
+ SWIGINTERN jint SWIG_MapSize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1) {
+ throw std::out_of_range("map size is too large to fit into a Java int");
+ }
+
+ return sz;
+ }
+}
+
+%javamethodmodifiers std::unordered_map::sizeImpl "private";
+%javamethodmodifiers std::unordered_map::containsImpl "private";
+%javamethodmodifiers std::unordered_map::putUnchecked "private";
+%javamethodmodifiers std::unordered_map::removeUnchecked "private";
+%javamethodmodifiers std::unordered_map::find "private";
+%javamethodmodifiers std::unordered_map::begin "private";
+%javamethodmodifiers std::unordered_map::end "private";
+
+%rename(Iterator) std::unordered_map::iterator;
+%nodefaultctor std::unordered_map::iterator;
+%javamethodmodifiers std::unordered_map::iterator::getNextUnchecked "private";
+%javamethodmodifiers std::unordered_map::iterator::isNot "private";
+%javamethodmodifiers std::unordered_map::iterator::getKey "private";
+%javamethodmodifiers std::unordered_map::iterator::getValue "private";
+%javamethodmodifiers std::unordered_map::iterator::setValue "private";
+
+namespace std {
+
+template<class K, class T> class unordered_map {
+
+%typemap(javabase) std::unordered_map<K, T>
+ "java.util.AbstractMap<$typemap(jboxtype, K), $typemap(jboxtype, T)>"
+
+%proxycode %{
+
+ public int size() {
+ return sizeImpl();
+ }
+
+ public boolean containsKey(java.lang.Object key) {
+ if (!(key instanceof $typemap(jboxtype, K))) {
+ return false;
+ }
+
+ return containsImpl(($typemap(jboxtype, K))key);
+ }
+
+ public $typemap(jboxtype, T) get(java.lang.Object key) {
+ if (!(key instanceof $typemap(jboxtype, K))) {
+ return null;
+ }
+
+ Iterator itr = find(($typemap(jboxtype, K)) key);
+ if (itr.isNot(end())) {
+ return itr.getValue();
+ }
+
+ return null;
+ }
+
+ public $typemap(jboxtype, T) put($typemap(jboxtype, K) key, $typemap(jboxtype, T) value) {
+ Iterator itr = find(($typemap(jboxtype, K)) key);
+ if (itr.isNot(end())) {
+ $typemap(jboxtype, T) oldValue = itr.getValue();
+ itr.setValue(value);
+ return oldValue;
+ } else {
+ putUnchecked(key, value);
+ return null;
+ }
+ }
+
+ public $typemap(jboxtype, T) remove(java.lang.Object key) {
+ if (!(key instanceof $typemap(jboxtype, K))) {
+ return null;
+ }
+
+ Iterator itr = find(($typemap(jboxtype, K)) key);
+ if (itr.isNot(end())) {
+ $typemap(jboxtype, T) oldValue = itr.getValue();
+ removeUnchecked(itr);
+ return oldValue;
+ } else {
+ return null;
+ }
+ }
+
+ public java.util.Set<Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>> entrySet() {
+ java.util.Set<Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>> setToReturn =
+ new java.util.HashSet<Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>>();
+
+ Iterator itr = begin();
+ final Iterator end = end();
+ while (itr.isNot(end)) {
+ setToReturn.add(new Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)>() {
+ private Iterator iterator;
+
+ private Entry<$typemap(jboxtype, K), $typemap(jboxtype, T)> init(Iterator iterator) {
+ this.iterator = iterator;
+ return this;
+ }
+
+ public $typemap(jboxtype, K) getKey() {
+ return iterator.getKey();
+ }
+
+ public $typemap(jboxtype, T) getValue() {
+ return iterator.getValue();
+ }
+
+ public $typemap(jboxtype, T) setValue($typemap(jboxtype, T) newValue) {
+ $typemap(jboxtype, T) oldValue = iterator.getValue();
+ iterator.setValue(newValue);
+ return oldValue;
+ }
+ }.init(itr));
+ itr = itr.getNextUnchecked();
+ }
+
+ return setToReturn;
+ }
+%}
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef K key_type;
+ typedef T mapped_type;
+ typedef std::pair< const K, T > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ unordered_map();
+ unordered_map(const unordered_map& other);
+
+ struct iterator {
+ %typemap(javaclassmodifiers) iterator "public class"
+ %extend {
+ std::unordered_map< K, T >::iterator getNextUnchecked() {
+ std::unordered_map< K, T >::iterator copy = (*$self);
+ return ++copy;
+ }
+
+ bool isNot(iterator other) const {
+ return (*$self != other);
+ }
+
+ K getKey() const {
+ return (*$self)->first;
+ }
+
+ T getValue() const {
+ return (*$self)->second;
+ }
+
+ void setValue(const T& newValue) {
+ (*$self)->second = newValue;
+ }
+ }
+ };
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ iterator find(const K& key);
+ iterator begin();
+ iterator end();
+ %extend {
+ %fragment("SWIG_MapSize");
+
+ jint sizeImpl() const throw (std::out_of_range) {
+ return SWIG_MapSize(self->size());
+ }
+
+ bool containsImpl(const K& key) {
+ return (self->count(key) > 0);
+ }
+
+ void putUnchecked(const K& key, const T& value) {
+%#ifdef __cpp_lib_map_try_emplace
+ (*self).insert_or_assign(key, value);
+%#else
+ (*self)[key] = value;
+%#endif
+ }
+
+ void removeUnchecked(const std::unordered_map< K, T >::iterator itr) {
+ self->erase(itr);
+ }
+ }
+};
+
+}
diff --git a/contrib/tools/swig/Lib/java/std_unordered_set.i b/contrib/tools/swig/Lib/java/std_unordered_set.i
new file mode 100644
index 00000000000..a66fe9a94b2
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_unordered_set.i
@@ -0,0 +1,203 @@
+/* -----------------------------------------------------------------------------
+ * std_unordered_set.i
+ *
+ * SWIG typemaps for std::unordered_set
+ * The Java proxy class extends java.util.AbstractSet. The std::unordered_set
+ * container looks and feels much like a java.util.HashSet from Java.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::unordered_set
+// ------------------------------------------------------------------------
+
+%{
+#include <unordered_set>
+#include <stdexcept>
+%}
+
+%fragment("SWIG_UnorderedSetSize", "header", fragment="SWIG_JavaIntFromSize_t") {
+ SWIGINTERN jint SWIG_UnorderedSetSize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1) {
+ throw std::out_of_range("unordered_set size is too large to fit into a Java int");
+ }
+
+ return sz;
+ }
+}
+
+%javamethodmodifiers std::unordered_set::sizeImpl "private";
+%javamethodmodifiers std::unordered_set::containsImpl "private";
+%javamethodmodifiers std::unordered_set::removeImpl "private";
+%javamethodmodifiers std::unordered_set::hasNextImpl "private";
+%javamethodmodifiers std::unordered_set::begin "private";
+%javamethodmodifiers std::unordered_set::end "private";
+
+%rename(Iterator) std::unordered_set::iterator;
+%nodefaultctor std::unordered_set::iterator;
+%javamethodmodifiers std::unordered_set::iterator::incrementUnchecked "private";
+%javamethodmodifiers std::unordered_set::iterator::derefUnchecked "private";
+%javamethodmodifiers std::unordered_set::iterator::isNot "private";
+
+namespace std {
+
+template <class Key>
+class unordered_set {
+
+%typemap(javabase) std::unordered_set<Key> "java.util.AbstractSet<$typemap(jboxtype, Key)>"
+%proxycode %{
+ public $javaclassname(java.util.Collection<? extends $typemap(jboxtype, Key)> collection) {
+ this();
+ addAll(collection);
+ }
+
+ public int size() {
+ return sizeImpl();
+ }
+
+ public boolean addAll(java.util.Collection<? extends $typemap(jboxtype, Key)> collection) {
+ boolean didAddElement = false;
+ for (java.lang.Object object : collection) {
+ didAddElement |= add(($typemap(jboxtype, Key))object);
+ }
+
+ return didAddElement;
+ }
+
+ public java.util.Iterator<$typemap(jboxtype, Key)> iterator() {
+ return new java.util.Iterator<$typemap(jboxtype, Key)>() {
+ private Iterator curr;
+ private Iterator end;
+
+ private java.util.Iterator<$typemap(jboxtype, Key)> init() {
+ curr = $javaclassname.this.begin();
+ end = $javaclassname.this.end();
+ return this;
+ }
+
+ public $typemap(jboxtype, Key) next() {
+ if (!hasNext()) {
+ throw new java.util.NoSuchElementException();
+ }
+
+ // Save the current position, increment it,
+ // then return the value at the position before the increment.
+ final $typemap(jboxtype, Key) currValue = curr.derefUnchecked();
+ curr.incrementUnchecked();
+ return currValue;
+ }
+
+ public boolean hasNext() {
+ return curr.isNot(end);
+ }
+
+ public void remove() {
+ throw new java.lang.UnsupportedOperationException();
+ }
+ }.init();
+ }
+
+ public boolean containsAll(java.util.Collection<?> collection) {
+ for (java.lang.Object object : collection) {
+ if (!contains(object)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public boolean contains(java.lang.Object object) {
+ if (!(object instanceof $typemap(jboxtype, Key))) {
+ return false;
+ }
+
+ return containsImpl(($typemap(jboxtype, Key))object);
+ }
+
+ public boolean removeAll(java.util.Collection<?> collection) {
+ boolean didRemoveElement = false;
+ for (java.lang.Object object : collection) {
+ didRemoveElement |= remove(object);
+ }
+
+ return didRemoveElement;
+ }
+
+ public boolean remove(java.lang.Object object) {
+ if (!(object instanceof $typemap(jboxtype, Key))) {
+ return false;
+ }
+
+ return removeImpl(($typemap(jboxtype, Key))object);
+ }
+%}
+
+ public:
+
+ struct iterator {
+ %typemap(javaclassmodifiers) iterator "public class"
+ %extend {
+ void incrementUnchecked() {
+ ++(*$self);
+ }
+
+ Key derefUnchecked() const {
+ return **$self;
+ }
+
+ bool isNot(iterator other) const {
+ return (*$self != other);
+ }
+ }
+ };
+
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef Key value_type;
+ typedef Key key_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ unordered_set();
+ unordered_set(const unordered_set& other);
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ iterator begin();
+ iterator end();
+
+ %extend {
+ %fragment("SWIG_UnorderedSetSize");
+
+ // Returns whether item was inserted.
+ bool add(const Key& key) {
+ return self->insert(key).second;
+ }
+
+ // Returns whether set contains key.
+ bool containsImpl(const Key& key) {
+ return (self->count(key) > 0);
+ }
+
+ // Returns whether the item was erased.
+ bool removeImpl(const Key& key) {
+ return (self->erase(key) > 0);
+ }
+
+ jint sizeImpl() const throw (std::out_of_range) {
+ return SWIG_UnorderedSetSize(self->size());
+ }
+
+ bool hasNextImpl(const iterator& itr) const {
+ return (itr != $self->end());
+ }
+ }
+};
+
+}
diff --git a/contrib/tools/swig/Lib/java/std_vector.i b/contrib/tools/swig/Lib/java/std_vector.i
new file mode 100644
index 00000000000..dee48fac554
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_vector.i
@@ -0,0 +1,203 @@
+/* -----------------------------------------------------------------------------
+ * std_vector.i
+ *
+ * SWIG typemaps for std::vector.
+ * The Java proxy class extends java.util.AbstractList and implements
+ * java.util.RandomAccess. The std::vector container looks and feels much like a
+ * java.util.ArrayList from Java.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+%{
+#include <vector>
+#include <stdexcept>
+%}
+
+%fragment("SWIG_VectorSize", "header", fragment="SWIG_JavaIntFromSize_t") {
+SWIGINTERN jint SWIG_VectorSize(size_t size) {
+ jint sz = SWIG_JavaIntFromSize_t(size);
+ if (sz == -1)
+ throw std::out_of_range("vector size is too large to fit into a Java int");
+ return sz;
+}
+}
+
+%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CTYPE, CONST_REFERENCE)
+%typemap(javabase) std::vector< CTYPE > "java.util.AbstractList<$typemap(jboxtype, CTYPE)>"
+%typemap(javainterfaces) std::vector< CTYPE > "java.util.RandomAccess"
+%proxycode %{
+ public $javaclassname($typemap(jstype, CTYPE)[] initialElements) {
+ this();
+ reserve(initialElements.length);
+
+ for ($typemap(jstype, CTYPE) element : initialElements) {
+ add(element);
+ }
+ }
+
+ public $javaclassname(Iterable<$typemap(jboxtype, CTYPE)> initialElements) {
+ this();
+ for ($typemap(jstype, CTYPE) element : initialElements) {
+ add(element);
+ }
+ }
+
+ public $typemap(jboxtype, CTYPE) get(int index) {
+ return doGet(index);
+ }
+
+ public $typemap(jboxtype, CTYPE) set(int index, $typemap(jboxtype, CTYPE) e) {
+ return doSet(index, e);
+ }
+
+ public boolean add($typemap(jboxtype, CTYPE) e) {
+ modCount++;
+ doAdd(e);
+ return true;
+ }
+
+ public void add(int index, $typemap(jboxtype, CTYPE) e) {
+ modCount++;
+ doAdd(index, e);
+ }
+
+ public $typemap(jboxtype, CTYPE) remove(int index) {
+ modCount++;
+ return doRemove(index);
+ }
+
+ protected void removeRange(int fromIndex, int toIndex) {
+ modCount++;
+ doRemoveRange(fromIndex, toIndex);
+ }
+
+ public int size() {
+ return doSize();
+ }
+
+ public int capacity() {
+ return doCapacity();
+ }
+
+ public void reserve(int n) {
+ doReserve(n);
+ }
+%}
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef CTYPE value_type;
+ typedef CTYPE *pointer;
+ typedef CTYPE const *const_pointer;
+ typedef CTYPE &reference;
+ typedef CONST_REFERENCE const_reference;
+
+ vector();
+ vector(const vector &other);
+
+ %rename(isEmpty) empty;
+ bool empty() const;
+ void clear();
+ %extend {
+ %fragment("SWIG_VectorSize");
+
+ vector(jint count, const CTYPE &value) throw (std::out_of_range) {
+ if (count < 0)
+ throw std::out_of_range("vector count must be positive");
+ return new std::vector< CTYPE >(static_cast<std::vector< CTYPE >::size_type>(count), value);
+ }
+
+ jint doCapacity() throw (std::out_of_range) {
+ return SWIG_VectorSize(self->capacity());
+ }
+
+ void doReserve(jint n) throw (std::length_error, std::out_of_range) {
+ if (n < 0)
+ throw std::out_of_range("vector reserve size must be positive");
+ self->reserve(n);
+ }
+
+ jint doSize() const throw (std::out_of_range) {
+ return SWIG_VectorSize(self->size());
+ }
+
+ void doAdd(const value_type& x) {
+ self->push_back(x);
+ }
+
+ void doAdd(jint index, const value_type& x) throw (std::out_of_range) {
+ jint size = static_cast<jint>(self->size());
+ if (0 <= index && index <= size) {
+ self->insert(self->begin() + index, x);
+ } else {
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+
+ value_type doRemove(jint index) throw (std::out_of_range) {
+ jint size = static_cast<jint>(self->size());
+ if (0 <= index && index < size) {
+ CTYPE const old_value = (*self)[index];
+ self->erase(self->begin() + index);
+ return old_value;
+ } else {
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+
+ CONST_REFERENCE doGet(jint index) throw (std::out_of_range) {
+ jint size = static_cast<jint>(self->size());
+ if (index >= 0 && index < size)
+ return (*self)[index];
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+
+ value_type doSet(jint index, const value_type& val) throw (std::out_of_range) {
+ jint size = static_cast<jint>(self->size());
+ if (index >= 0 && index < size) {
+ CTYPE const old_value = (*self)[index];
+ (*self)[index] = val;
+ return old_value;
+ }
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+
+ void doRemoveRange(jint fromIndex, jint toIndex) throw (std::out_of_range) {
+ jint size = static_cast<jint>(self->size());
+ if (0 <= fromIndex && fromIndex <= toIndex && toIndex <= size) {
+ self->erase(self->begin() + fromIndex, self->begin() + toIndex);
+ } else {
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+ }
+%enddef
+
+%javamethodmodifiers std::vector::doCapacity "private";
+%javamethodmodifiers std::vector::doReserve "private";
+%javamethodmodifiers std::vector::doSize "private";
+%javamethodmodifiers std::vector::doAdd "private";
+%javamethodmodifiers std::vector::doGet "private";
+%javamethodmodifiers std::vector::doSet "private";
+%javamethodmodifiers std::vector::doRemove "private";
+%javamethodmodifiers std::vector::doRemoveRange "private";
+
+namespace std {
+
+ template<class T> class vector {
+ SWIG_STD_VECTOR_MINIMUM_INTERNAL(T, const value_type&)
+ };
+
+ // bool specialization
+ template<> class vector<bool> {
+ SWIG_STD_VECTOR_MINIMUM_INTERNAL(bool, bool)
+ };
+}
+
+%define specialize_std_vector(T)
+#warning "specialize_std_vector - specialization for type T no longer needed"
+%enddef
diff --git a/contrib/tools/swig/Lib/java/std_wstring.i b/contrib/tools/swig/Lib/java/std_wstring.i
new file mode 100644
index 00000000000..efa9e63b88d
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/std_wstring.i
@@ -0,0 +1,180 @@
+/* -----------------------------------------------------------------------------
+ * std_wstring.i
+ *
+ * Typemaps for std::wstring and const std::wstring&
+ *
+ * These are mapped to a Java String and are passed around by value.
+ * Warning: Unicode / multibyte characters are handled differently on different
+ * OSs so the std::wstring typemaps may not always work as intended.
+ *
+ * To use non-const std::wstring references use the following %apply. Note
+ * that they are passed by value.
+ * %apply const std::wstring & {std::wstring &};
+ * ----------------------------------------------------------------------------- */
+
+namespace std {
+
+%naturalvar wstring;
+
+class wstring;
+
+// wstring
+%typemap(jni) wstring "jstring"
+%typemap(jtype) wstring "String"
+%typemap(jstype) wstring "String"
+%typemap(javadirectorin) wstring "$jniinput"
+%typemap(javadirectorout) wstring "$javacall"
+
+%typemap(in) wstring
+%{if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::wstring");
+ return $null;
+ }
+ const jchar *$1_pstr = jenv->GetStringChars($input, 0);
+ if (!$1_pstr) return $null;
+ jsize $1_len = jenv->GetStringLength($input);
+ if ($1_len) {
+ $1.reserve($1_len);
+ for (jsize i = 0; i < $1_len; ++i) {
+ $1.push_back((wchar_t)$1_pstr[i]);
+ }
+ }
+ jenv->ReleaseStringChars($input, $1_pstr);
+ %}
+
+%typemap(directorout) wstring
+%{if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::wstring");
+ return $null;
+ }
+ const jchar *$1_pstr = jenv->GetStringChars($input, 0);
+ if (!$1_pstr) return $null;
+ jsize $1_len = jenv->GetStringLength($input);
+ if ($1_len) {
+ $result.reserve($1_len);
+ for (jsize i = 0; i < $1_len; ++i) {
+ $result.push_back((wchar_t)$1_pstr[i]);
+ }
+ }
+ jenv->ReleaseStringChars($input, $1_pstr);
+ %}
+
+%typemap(directorin,descriptor="Ljava/lang/String;") wstring %{
+ jsize $1_len = (jsize)$1.length();
+ jchar *$1_conv_buf = new jchar[$1_len];
+ for (jsize i = 0; i < $1_len; ++i) {
+ $1_conv_buf[i] = (jchar)$1[i];
+ }
+ $input = jenv->NewString($1_conv_buf, $1_len);
+ Swig::LocalRefGuard $1_refguard(jenv, $input);
+ delete [] $1_conv_buf;
+%}
+
+%typemap(out) wstring
+%{jsize $1_len = (jsize)$1.length();
+ jchar *conv_buf = new jchar[$1_len];
+ for (jsize i = 0; i < $1_len; ++i) {
+ conv_buf[i] = (jchar)$1[i];
+ }
+ $result = jenv->NewString(conv_buf, $1_len);
+ delete [] conv_buf; %}
+
+%typemap(javain) wstring "$javainput"
+
+%typemap(javaout) wstring {
+ return $jnicall;
+ }
+
+//%typemap(typecheck) wstring = wchar_t *;
+
+%typemap(throws) wstring
+%{std::string message($1.size(), '\0');
+ for (size_t i = 0; i < $1.size(); ++i) {
+ message[i] = (char)$1[i];
+ }
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, message.c_str());
+ return $null; %}
+
+// const wstring &
+%typemap(jni) const wstring & "jstring"
+%typemap(jtype) const wstring & "String"
+%typemap(jstype) const wstring & "String"
+%typemap(javadirectorin) const wstring & "$jniinput"
+%typemap(javadirectorout) const wstring & "$javacall"
+
+%typemap(in) const wstring &
+%{if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::wstring");
+ return $null;
+ }
+ const jchar *$1_pstr = jenv->GetStringChars($input, 0);
+ if (!$1_pstr) return $null;
+ jsize $1_len = jenv->GetStringLength($input);
+ std::wstring $1_str;
+ if ($1_len) {
+ $1_str.reserve($1_len);
+ for (jsize i = 0; i < $1_len; ++i) {
+ $1_str.push_back((wchar_t)$1_pstr[i]);
+ }
+ }
+ $1 = &$1_str;
+ jenv->ReleaseStringChars($input, $1_pstr);
+ %}
+
+%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const wstring &
+%{if(!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null std::wstring");
+ return $null;
+ }
+ const jchar *$1_pstr = jenv->GetStringChars($input, 0);
+ if (!$1_pstr) return $null;
+ jsize $1_len = jenv->GetStringLength($input);
+ /* possible thread/reentrant code problem */
+ static std::wstring $1_str;
+ if ($1_len) {
+ $1_str.reserve($1_len);
+ for (jsize i = 0; i < $1_len; ++i) {
+ $1_str.push_back((wchar_t)$1_pstr[i]);
+ }
+ }
+ $result = &$1_str;
+ jenv->ReleaseStringChars($input, $1_pstr); %}
+
+%typemap(directorin,descriptor="Ljava/lang/String;") const wstring & %{
+ jsize $1_len = (jsize)$1.length();
+ jchar *$1_conv_buf = new jchar[$1_len];
+ for (jsize i = 0; i < $1_len; ++i) {
+ $1_conv_buf[i] = (jchar)($1)[i];
+ }
+ $input = jenv->NewString($1_conv_buf, $1_len);
+ Swig::LocalRefGuard $1_refguard(jenv, $input);
+ delete [] $1_conv_buf;
+%}
+
+%typemap(out) const wstring &
+%{jsize $1_len = (jsize)$1->length();
+ jchar *conv_buf = new jchar[$1_len];
+ for (jsize i = 0; i < $1_len; ++i) {
+ conv_buf[i] = (jchar)(*$1)[i];
+ }
+ $result = jenv->NewString(conv_buf, $1_len);
+ delete [] conv_buf; %}
+
+%typemap(javain) const wstring & "$javainput"
+
+%typemap(javaout) const wstring & {
+ return $jnicall;
+ }
+
+//%typemap(typecheck) const wstring & = wchar_t *;
+
+%typemap(throws) const wstring &
+%{std::string message($1.size(), '\0');
+ for (size_t i = 0; i < $1.size(); ++i) {
+ message[i] = (char)$1[i];
+ }
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, message.c_str());
+ return $null; %}
+
+}
+
diff --git a/contrib/tools/swig/Lib/java/stl.i b/contrib/tools/swig/Lib/java/stl.i
new file mode 100644
index 00000000000..04f86014f2c
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/stl.i
@@ -0,0 +1,10 @@
+/* -----------------------------------------------------------------------------
+ * stl.i
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <std_string.i>
+%include <std_vector.i>
+%include <std_map.i>
+%include <std_pair.i>
+
diff --git a/contrib/tools/swig/Lib/java/swiginterface.i b/contrib/tools/swig/Lib/java/swiginterface.i
new file mode 100644
index 00000000000..ce21d90cc02
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/swiginterface.i
@@ -0,0 +1,79 @@
+/* -----------------------------------------------------------------------------
+ * swiginterface.i
+ *
+ * SWIG interface feature and typemaps implementation providing:
+ * %interface
+ * %interface_impl
+ * %interface_custom
+ * ----------------------------------------------------------------------------- */
+
+%define INTERFACE_TYPEMAPS(CTYPE...)
+%typemap(jtype) CTYPE, CTYPE *, CTYPE *const&, CTYPE [], CTYPE & "long"
+%typemap(jstype) CTYPE "$&javainterfacename"
+%typemap(jstype) CTYPE *, CTYPE [], CTYPE & "$javainterfacename"
+%typemap(jstype) CTYPE *const& "$*javainterfacename"
+%typemap(javain) CTYPE "$javainput.$&interfacename_GetInterfaceCPtr()"
+%typemap(javain) CTYPE & "$javainput.$interfacename_GetInterfaceCPtr()"
+%typemap(javain) CTYPE *, CTYPE [] "($javainput == null) ? 0 : $javainput.$interfacename_GetInterfaceCPtr()"
+%typemap(javain) CTYPE *const& "($javainput == null) ? 0 : $javainput.$*interfacename_GetInterfaceCPtr()"
+%typemap(javaout) CTYPE {
+ return ($&javainterfacename)new $&javaclassname($jnicall, true);
+ }
+%typemap(javaout) CTYPE & {
+ return ($javainterfacename)new $javaclassname($jnicall, $owner);
+ }
+%typemap(javaout) CTYPE *, CTYPE [] {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : ($javainterfacename)new $javaclassname(cPtr, $owner);
+ }
+%typemap(javaout) CTYPE *const& {
+ long cPtr = $jnicall;
+ return (cPtr == 0) ? null : ($*javainterfacename)new $*javaclassname(cPtr, $owner);
+ }
+
+%typemap(javadirectorin) CTYPE "($&javainterfacename)new $&javaclassname($jniinput, true)"
+%typemap(javadirectorin) CTYPE & "($javainterfacename)new $javaclassname($jniinput, false)"
+%typemap(javadirectorin) CTYPE *, CTYPE [] "($jniinput == 0) ? null : ($javainterfacename)new $javaclassname($jniinput, false)"
+%typemap(javadirectorin) CTYPE *const& "($jniinput == 0) ? null : ($*javainterfacename)new $*javaclassname($jniinput, false)"
+%typemap(javadirectorout) CTYPE "$javacall.$&interfacename_GetInterfaceCPtr()"
+%typemap(javadirectorout) CTYPE *, CTYPE [], CTYPE & "$javacall.$interfacename_GetInterfaceCPtr()"
+%typemap(javadirectorout) CTYPE *const& "$javacall.$*interfacename_GetInterfaceCPtr()"
+%typemap(directorin,descriptor="L$packagepath/$&javainterfacename;") CTYPE
+%{ $input = 0;
+ *(($&1_ltype*)&$input) = new $1_ltype(SWIG_STD_MOVE($1)); %}
+%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE *, CTYPE []
+%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
+%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE &
+%{ *($&1_ltype)&$input = ($1_ltype) &$1; %}
+%typemap(directorin,descriptor="L$packagepath/$*javainterfacename;") CTYPE *const&
+%{ *($&1_ltype)&$input = ($1_ltype) &$1; %}
+
+%typemap(javainterfacecode, declaration=" long $interfacename_GetInterfaceCPtr();\n", cptrmethod="$interfacename_GetInterfaceCPtr") CTYPE %{
+ public long $interfacename_GetInterfaceCPtr() {
+ return $imclassname.$javaclazzname$interfacename_GetInterfaceCPtr(swigCPtr);
+ }
+%}
+%enddef
+
+%define %interface(CTYPE...)
+%feature("interface", name="%sSwigInterface") CTYPE;
+INTERFACE_TYPEMAPS(CTYPE)
+%enddef
+
+%define %interface_impl(CTYPE...)
+%rename("%sSwigImpl") CTYPE;
+%feature("interface", name="%(rstrip:[SwigImpl])s") CTYPE;
+INTERFACE_TYPEMAPS(CTYPE)
+%enddef
+
+%define %interface_custom(PROXY, INTERFACE, CTYPE...)
+%rename(PROXY) CTYPE;
+%feature("interface", name=INTERFACE) CTYPE;
+INTERFACE_TYPEMAPS(CTYPE)
+%enddef
+
+%define %interface_additional(PROXY, INTERFACE, ADDITIONAL, CTYPE...)
+%rename(PROXY) CTYPE;
+%feature("interface", name=INTERFACE, additional=ADDITIONAL) CTYPE;
+INTERFACE_TYPEMAPS(CTYPE)
+%enddef
diff --git a/contrib/tools/swig/Lib/java/swigmove.i b/contrib/tools/swig/Lib/java/swigmove.i
new file mode 100644
index 00000000000..671b988af6e
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/swigmove.i
@@ -0,0 +1,16 @@
+/* -----------------------------------------------------------------------------
+ * swigmove.i
+ *
+ * Input typemaps library for implementing full move semantics when passing
+ * parameters by value.
+ * ----------------------------------------------------------------------------- */
+
+%typemap(in) SWIGTYPE MOVE ($&1_type argp)
+%{ argp = *($&1_ltype*)&$input;
+ if (!argp) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
+ return $null;
+ }
+ SwigValueWrapper< $1_ltype >::reset($1, argp); %}
+
+%typemap(javain) SWIGTYPE MOVE "$&javaclassname.swigRelease($javainput)"
diff --git a/contrib/tools/swig/Lib/java/typemaps.i b/contrib/tools/swig/Lib/java/typemaps.i
new file mode 100644
index 00000000000..658a6b116c4
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/typemaps.i
@@ -0,0 +1,549 @@
+/* -----------------------------------------------------------------------------
+ * typemaps.i
+ *
+ * Pointer and reference handling typemap library
+ *
+ * These mappings provide support for input/output arguments and common
+ * uses for C/C++ pointers and C++ references.
+ * ----------------------------------------------------------------------------- */
+
+/*
+INPUT typemaps
+--------------
+
+These typemaps remap a C pointer or C++ reference to be an "INPUT" value which is
+passed by value instead of reference.
+
+The following typemaps can be applied to turn a pointer or reference into a simple
+input value. That is, instead of passing a pointer or reference to an object,
+you would use a real value instead.
+
+ bool *INPUT, bool &INPUT
+ signed char *INPUT, signed char &INPUT
+ unsigned char *INPUT, unsigned char &INPUT
+ short *INPUT, short &INPUT
+ unsigned short *INPUT, unsigned short &INPUT
+ int *INPUT, int &INPUT
+ unsigned int *INPUT, unsigned int &INPUT
+ long *INPUT, long &INPUT
+ unsigned long *INPUT, unsigned long &INPUT
+ long long *INPUT, long long &INPUT
+ unsigned long long *INPUT, unsigned long long &INPUT
+ float *INPUT, float &INPUT
+ double *INPUT, double &INPUT
+
+To use these, suppose you had a C function like this :
+
+ double fadd(double *a, double *b) {
+ return *a+*b;
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double fadd(double *INPUT, double *INPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INPUT { double *a, double *b };
+ double fadd(double *a, double *b);
+
+In Java you could then use it like this:
+ double answer = modulename.fadd(10.0, 20.0);
+
+There are no char *INPUT typemaps, however you can apply the signed char * typemaps instead:
+ %include <typemaps.i>
+ %apply signed char *INPUT {char *input};
+ void f(char *input);
+*/
+
+%define INPUT_TYPEMAP(TYPE, JNITYPE, JTYPE, JNIDESC)
+%typemap(jni) TYPE *INPUT, TYPE &INPUT "JNITYPE"
+%typemap(jtype) TYPE *INPUT, TYPE &INPUT "JTYPE"
+%typemap(jstype) TYPE *INPUT, TYPE &INPUT "JTYPE"
+%typemap(javain) TYPE *INPUT, TYPE &INPUT "$javainput"
+
+%typemap(in) TYPE *INPUT, TYPE &INPUT
+%{ $1 = ($1_ltype)&$input; %}
+
+%typemap(freearg) TYPE *INPUT, TYPE &INPUT ""
+
+%typemap(typecheck) TYPE *INPUT = TYPE;
+%typemap(typecheck) TYPE &INPUT = TYPE;
+%enddef
+
+INPUT_TYPEMAP(bool, jboolean, boolean, "Z");
+INPUT_TYPEMAP(signed char, jbyte, byte, "B");
+INPUT_TYPEMAP(unsigned char, jshort, short, "S");
+INPUT_TYPEMAP(short, jshort, short, "S");
+INPUT_TYPEMAP(unsigned short, jint, int, "I");
+INPUT_TYPEMAP(int, jint, int, "I");
+INPUT_TYPEMAP(unsigned int, jlong, long, "J");
+INPUT_TYPEMAP(long, jint, int, "I");
+INPUT_TYPEMAP(unsigned long, jlong, long, "J");
+INPUT_TYPEMAP(long long, jlong, long, "J");
+INPUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, "Ljava/math/BigInteger;");
+INPUT_TYPEMAP(float, jfloat, float, "F");
+INPUT_TYPEMAP(double, jdouble, double, "D");
+
+#undef INPUT_TYPEMAP
+
+/* Convert from BigInteger using the toByteArray member function */
+/* Overrides the typemap in the INPUT_TYPEMAP macro */
+%typemap(in) unsigned long long *INPUT($*1_ltype temp), unsigned long long &INPUT($*1_ltype temp) {
+ jclass clazz;
+ jmethodID mid;
+ jbyteArray ba;
+ jbyte* bae;
+ jsize sz;
+ int i;
+
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "BigInteger null");
+ return $null;
+ }
+ clazz = JCALL1(GetObjectClass, jenv, $input);
+ mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
+ ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, $input, mid);
+ bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ sz = JCALL1(GetArrayLength, jenv, ba);
+ temp = 0;
+ if (sz > 0) {
+ temp = ($*1_ltype)(signed char)bae[0];
+ for(i=1; i<sz; i++) {
+ temp = (temp << 8) | ($*1_ltype)(unsigned char)bae[i];
+ }
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+ $1 = &temp;
+}
+
+// OUTPUT typemaps. These typemaps are used for parameters that
+// are output only. An array replaces the c pointer or reference parameter.
+// The output value is returned in this array passed in.
+
+/*
+OUTPUT typemaps
+---------------
+
+The following typemaps can be applied to turn a pointer or reference into an "output"
+value. When calling a function, no input value would be given for
+a parameter, but an output value would be returned. This works by a
+Java array being passed as a parameter where a c pointer or reference is required.
+As with any Java function, the array is passed by reference so that
+any modifications to the array will be picked up in the calling function.
+Note that the array passed in MUST have at least one element, but as the
+c function does not require any input, the value can be set to anything.
+
+ bool *OUTPUT, bool &OUTPUT
+ signed char *OUTPUT, signed char &OUTPUT
+ unsigned char *OUTPUT, unsigned char &OUTPUT
+ short *OUTPUT, short &OUTPUT
+ unsigned short *OUTPUT, unsigned short &OUTPUT
+ int *OUTPUT, int &OUTPUT
+ unsigned int *OUTPUT, unsigned int &OUTPUT
+ long *OUTPUT, long &OUTPUT
+ unsigned long *OUTPUT, unsigned long &OUTPUT
+ long long *OUTPUT, long long &OUTPUT
+ unsigned long long *OUTPUT, unsigned long long &OUTPUT
+ float *OUTPUT, float &OUTPUT
+ double *OUTPUT, double &OUTPUT
+
+For example, suppose you were trying to wrap the modf() function in the
+C math library which splits x into integral and fractional parts (and
+returns the integer part in one of its parameters):
+
+ double modf(double x, double *ip);
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double modf(double x, double *OUTPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *OUTPUT { double *ip };
+ double modf(double x, double *ip);
+
+The Java output of the function would be the function return value and the
+value in the single element array. In Java you would use it like this:
+
+ double[] ptr = {0.0};
+ double fraction = modulename.modf(5.0,ptr);
+
+There are no char *OUTPUT typemaps, however you can apply the signed char * typemaps instead:
+ %include <typemaps.i>
+ %apply signed char *OUTPUT {char *output};
+ void f(char *output);
+*/
+
+/* Java BigInteger[] */
+%typecheck(SWIG_TYPECHECK_INT128_ARRAY) SWIGBIGINTEGERARRAY ""
+
+%define OUTPUT_TYPEMAP(TYPE, JNITYPE, JTYPE, JAVATYPE, JNIDESC, TYPECHECKTYPE)
+%typemap(jni) TYPE *OUTPUT, TYPE &OUTPUT %{JNITYPE##Array%}
+%typemap(jtype) TYPE *OUTPUT, TYPE &OUTPUT "JTYPE[]"
+%typemap(jstype) TYPE *OUTPUT, TYPE &OUTPUT "JTYPE[]"
+%typemap(javain) TYPE *OUTPUT, TYPE &OUTPUT "$javainput"
+%typemap(javadirectorin) TYPE *OUTPUT, TYPE &OUTPUT "$jniinput"
+%typemap(javadirectorout) TYPE *OUTPUT, TYPE &OUTPUT "$javacall"
+
+%typemap(in) TYPE *OUTPUT($*1_ltype temp), TYPE &OUTPUT($*1_ltype temp)
+{
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
+ return $null;
+ }
+ if (JCALL1(GetArrayLength, jenv, $input) == 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
+ return $null;
+ }
+ temp = ($*1_ltype)0;
+ $1 = &temp;
+}
+
+%typemap(freearg) TYPE *OUTPUT, TYPE &OUTPUT ""
+
+%typemap(argout) TYPE *OUTPUT, TYPE &OUTPUT
+{
+ JNITYPE jvalue = (JNITYPE)temp$argnum;
+ JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &jvalue);
+}
+
+%typemap(directorin,descriptor=JNIDESC) TYPE &OUTPUT %{
+ $input = JCALL1(New##JAVATYPE##Array, jenv, 1);
+ if (!$input) return $null;
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(directorin,descriptor=JNIDESC) TYPE *OUTPUT %{
+ if ($1) {
+ $input = JCALL1(New##JAVATYPE##Array, jenv, 1);
+ if (!$input) return $null;
+ }
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(directorargout, noblock=1) TYPE &OUTPUT
+{
+ JNITYPE $1_jvalue;
+ JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ $result = ($*1_ltype)$1_jvalue;
+}
+
+%typemap(directorargout, noblock=1) TYPE *OUTPUT
+{
+ if ($result) {
+ JNITYPE $1_jvalue;
+ JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ *$result = ($*1_ltype)$1_jvalue;
+ }
+}
+
+%typemap(typecheck) TYPE *OUTPUT = TYPECHECKTYPE;
+%typemap(typecheck) TYPE &OUTPUT = TYPECHECKTYPE;
+%enddef
+
+OUTPUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Z", jbooleanArray);
+OUTPUT_TYPEMAP(signed char, jbyte, byte, Byte, "[B", jbyteArray);
+OUTPUT_TYPEMAP(unsigned char, jshort, short, Short, "[S", jshortArray);
+OUTPUT_TYPEMAP(short, jshort, short, Short, "[S", jshortArray);
+OUTPUT_TYPEMAP(unsigned short, jint, int, Int, "[I", jintArray);
+OUTPUT_TYPEMAP(int, jint, int, Int, "[I", jintArray);
+OUTPUT_TYPEMAP(unsigned int, jlong, long, Long, "[J", jlongArray);
+OUTPUT_TYPEMAP(long, jint, int, Int, "[I", jintArray);
+OUTPUT_TYPEMAP(unsigned long, jlong, long, Long, "[J", jlongArray);
+OUTPUT_TYPEMAP(long long, jlong, long, Long, "[J", jlongArray);
+OUTPUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, Object, "[Ljava/math/BigInteger;", jobjectArray);
+OUTPUT_TYPEMAP(float, jfloat, float, Float, "[F", jfloatArray);
+OUTPUT_TYPEMAP(double, jdouble, double, Double, "[D", jdoubleArray);
+
+#undef OUTPUT_TYPEMAP
+
+%typemap(in) bool *OUTPUT($*1_ltype temp), bool &OUTPUT($*1_ltype temp)
+{
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
+ return $null;
+ }
+ if (JCALL1(GetArrayLength, jenv, $input) == 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
+ return $null;
+ }
+ temp = false;
+ $1 = &temp;
+}
+
+%typemap(directorargout, noblock=1) bool &OUTPUT
+{
+ jboolean $1_jvalue;
+ JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ $result = $1_jvalue ? true : false;
+}
+
+%typemap(directorargout, noblock=1) bool *OUTPUT
+{
+ if ($result) {
+ jboolean $1_jvalue;
+ JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ *$result = $1_jvalue ? true : false;
+ }
+}
+
+
+/* Convert to BigInteger - byte array holds number in 2's complement big endian format */
+/* Use first element in BigInteger array for output */
+/* Overrides the typemap in the OUTPUT_TYPEMAP macro */
+%typemap(argout) unsigned long long *OUTPUT, unsigned long long &OUTPUT {
+ jbyteArray ba = JCALL1(NewByteArray, jenv, 9);
+ jbyte* bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ jclass clazz = JCALL1(FindClass, jenv, "java/math/BigInteger");
+ jmethodID mid = JCALL3(GetMethodID, jenv, clazz, "<init>", "([B)V");
+ jobject bigint;
+ int i;
+
+ bae[0] = 0;
+ for(i=1; i<9; i++ ) {
+ bae[i] = (jbyte)(temp$argnum>>8*(8-i));
+ }
+
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+ bigint = JCALL3(NewObject, jenv, clazz, mid, ba);
+ JCALL1(DeleteLocalRef, jenv, ba);
+ JCALL3(SetObjectArrayElement, jenv, $input, 0, bigint);
+}
+
+/*
+INOUT typemaps
+--------------
+
+Mappings for a parameter that is both an input and an output parameter
+
+The following typemaps can be applied to make a function parameter both
+an input and output value. This combines the behavior of both the
+"INPUT" and "OUTPUT" typemaps described earlier. Output values are
+returned as an element in a Java array.
+
+ bool *INOUT, bool &INOUT
+ signed char *INOUT, signed char &INOUT
+ unsigned char *INOUT, unsigned char &INOUT
+ short *INOUT, short &INOUT
+ unsigned short *INOUT, unsigned short &INOUT
+ int *INOUT, int &INOUT
+ unsigned int *INOUT, unsigned int &INOUT
+ long *INOUT, long &INOUT
+ unsigned long *INOUT, unsigned long &INOUT
+ long long *INOUT, long long &INOUT
+ unsigned long long *INOUT, unsigned long long &INOUT
+ float *INOUT, float &INOUT
+ double *INOUT, double &INOUT
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ void neg(double *INOUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INOUT { double *x };
+ void neg(double *x);
+
+This works similarly to C in that the mapping directly modifies the
+input value - the input must be an array with a minimum of one element.
+The element in the array is the input and the output is the element in
+the array.
+
+ double x[] = {5.0};
+ neg(x);
+
+The implementation of the OUTPUT and INOUT typemaps is different to other
+languages in that other languages will return the output value as part
+of the function return value. This difference is due to Java being a typed language.
+
+There are no char *INOUT typemaps, however you can apply the signed char * typemaps instead:
+ %include <typemaps.i>
+ %apply signed char *INOUT {char *inout};
+ void f(char *inout);
+*/
+
+%define INOUT_TYPEMAP(TYPE, JNITYPE, JTYPE, JAVATYPE, JNIDESC, TYPECHECKTYPE)
+%typemap(jni) TYPE *INOUT, TYPE &INOUT %{JNITYPE##Array%}
+%typemap(jtype) TYPE *INOUT, TYPE &INOUT "JTYPE[]"
+%typemap(jstype) TYPE *INOUT, TYPE &INOUT "JTYPE[]"
+%typemap(javain) TYPE *INOUT, TYPE &INOUT "$javainput"
+%typemap(javadirectorin) TYPE *INOUT, TYPE &INOUT "$jniinput"
+%typemap(javadirectorout) TYPE *INOUT, TYPE &INOUT "$javacall"
+
+%typemap(in) TYPE *INOUT, TYPE &INOUT {
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
+ return $null;
+ }
+ if (JCALL1(GetArrayLength, jenv, $input) == 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
+ return $null;
+ }
+ $1 = ($1_ltype) JCALL2(Get##JAVATYPE##ArrayElements, jenv, $input, 0);
+}
+
+%typemap(freearg) TYPE *INOUT, TYPE &INOUT ""
+
+%typemap(argout) TYPE *INOUT, TYPE &INOUT
+{ JCALL3(Release##JAVATYPE##ArrayElements, jenv, $input, (JNITYPE *)$1, 0); }
+
+%typemap(directorin,descriptor=JNIDESC) TYPE &INOUT %{
+ $input = JCALL1(New##JAVATYPE##Array, jenv, 1);
+ if (!$input) return $null;
+ JNITYPE $1_jvalue = (JNITYPE)$1;
+ JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(directorin,descriptor=JNIDESC) TYPE *INOUT %{
+ if ($1) {
+ $input = JCALL1(New##JAVATYPE##Array, jenv, 1);
+ if (!$input) return $null;
+ JNITYPE $1_jvalue = (JNITYPE)*$1;
+ JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ }
+ Swig::LocalRefGuard $1_refguard(jenv, $input); %}
+
+%typemap(directorargout, noblock=1) TYPE &INOUT
+{
+ JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ $result = ($*1_ltype)$1_jvalue;
+}
+
+%typemap(directorargout, noblock=1) TYPE *INOUT
+{
+ if ($result) {
+ JNITYPE $1_jvalue;
+ JCALL4(Get##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ *$result = ($*1_ltype)$1_jvalue;
+ }
+}
+
+%typemap(typecheck) TYPE *INOUT = TYPECHECKTYPE;
+%typemap(typecheck) TYPE &INOUT = TYPECHECKTYPE;
+%enddef
+
+INOUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Z", jbooleanArray);
+INOUT_TYPEMAP(signed char, jbyte, byte, Byte, "[B", jbyteArray);
+INOUT_TYPEMAP(unsigned char, jshort, short, Short, "[S", jshortArray);
+INOUT_TYPEMAP(short, jshort, short, Short, "[S", jshortArray);
+INOUT_TYPEMAP(unsigned short, jint, int, Int, "[I", jintArray);
+INOUT_TYPEMAP(int, jint, int, Int, "[I", jintArray);
+INOUT_TYPEMAP(unsigned int, jlong, long, Long, "[J", jlongArray);
+INOUT_TYPEMAP(long, jint, int, Int, "[I", jintArray);
+INOUT_TYPEMAP(unsigned long, jlong, long, Long, "[J", jlongArray);
+INOUT_TYPEMAP(long long, jlong, long, Long, "[J", jlongArray);
+INOUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, Object, "[java/math/BigInteger;", jobjectArray);
+INOUT_TYPEMAP(float, jfloat, float, Float, "[F", jfloatArray);
+INOUT_TYPEMAP(double, jdouble, double, Double, "[D", jdoubleArray);
+
+#undef INOUT_TYPEMAP
+
+/* Override typemaps in the INOUT_TYPEMAP macro for booleans to fix casts
+ as a jboolean isn't always the same size as a bool */
+%typemap(in) bool *INOUT (bool btemp, jboolean *jbtemp), bool &INOUT (bool btemp, jboolean *jbtemp) {
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
+ return $null;
+ }
+ if (JCALL1(GetArrayLength, jenv, $input) == 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
+ return $null;
+ }
+ jbtemp = JCALL2(GetBooleanArrayElements, jenv, $input, 0);
+ btemp = (*jbtemp) ? true : false;
+ $1 = &btemp;
+}
+
+%typemap(argout) bool *INOUT, bool &INOUT {
+ *jbtemp$argnum = btemp$argnum ? (jboolean)1 : (jboolean)0;
+ JCALL3(ReleaseBooleanArrayElements, jenv, $input , (jboolean *)jbtemp$argnum, 0);
+}
+
+%typemap(directorargout, noblock=1) bool &INOUT
+{
+ JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ $result = $1_jvalue ? true : false;
+}
+
+%typemap(directorargout, noblock=1) bool *INOUT
+{
+ if ($result) {
+ jboolean $1_jvalue;
+ JCALL4(GetBooleanArrayRegion, jenv, $input, 0, 1, &$1_jvalue);
+ *$result = $1_jvalue ? true : false;
+ }
+}
+
+
+/* Override the typemap in the INOUT_TYPEMAP macro for unsigned long long */
+%typemap(in) unsigned long long *INOUT ($*1_ltype temp), unsigned long long &INOUT ($*1_ltype temp) {
+ jobject bigint;
+ jclass clazz;
+ jmethodID mid;
+ jbyteArray ba;
+ jbyte* bae;
+ jsize sz;
+ int i;
+
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
+ return $null;
+ }
+ if (JCALL1(GetArrayLength, jenv, $input) == 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
+ return $null;
+ }
+ bigint = JCALL2(GetObjectArrayElement, jenv, $input, 0);
+ if (!bigint) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array element null");
+ return $null;
+ }
+ clazz = JCALL1(GetObjectClass, jenv, bigint);
+ mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
+ ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, bigint, mid);
+ bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
+ sz = JCALL1(GetArrayLength, jenv, ba);
+ temp = 0;
+ if (sz > 0) {
+ temp = ($*1_ltype)(signed char)bae[0];
+ for(i=1; i<sz; i++) {
+ temp = (temp << 8) | ($*1_ltype)(unsigned char)bae[i];
+ }
+ }
+ JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
+ $1 = &temp;
+}
+
+%typemap(argout) unsigned long long *INOUT = unsigned long long *OUTPUT;
+%typemap(argout) unsigned long long &INOUT = unsigned long long &OUTPUT;
+
+#if defined(SWIGWORDSIZE64)
+%apply long long *INPUT { long *INPUT };
+%apply unsigned long long *INPUT { unsigned long *INPUT };
+
+%apply long long &INPUT { long &INPUT };
+%apply unsigned long long &INPUT { unsigned long &INPUT };
+
+%apply long long *INOUT { long *INOUT };
+%apply unsigned long long *INOUT { unsigned long *INOUT };
+
+%apply long long &INOUT { long &INOUT };
+%apply unsigned long long &INOUT { unsigned long &INOUT };
+
+%apply long long *OUTPUT { long *OUTPUT };
+%apply unsigned long long *OUTPUT { unsigned long *OUTPUT };
+
+%apply long long &OUTPUT { long &OUTPUT };
+%apply unsigned long long &OUTPUT { unsigned long &OUTPUT };
+#endif
diff --git a/contrib/tools/swig/Lib/java/various.i b/contrib/tools/swig/Lib/java/various.i
new file mode 100644
index 00000000000..24796ba84f0
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/various.i
@@ -0,0 +1,194 @@
+/* -----------------------------------------------------------------------------
+ * various.i
+ *
+ * SWIG Typemap library for Java.
+ * Various useful typemaps.
+ * ----------------------------------------------------------------------------- */
+
+/*
+ * char **STRING_ARRAY typemaps.
+ * These typemaps are for C String arrays which are NULL terminated.
+ * char *values[] = { "one", "two", "three", NULL }; // note NULL
+ * char ** is mapped to a Java String[].
+ *
+ * Example usage wrapping:
+ * %apply char **STRING_ARRAY { char **input };
+ * char ** foo(char **input);
+ *
+ * Java usage:
+ * String numbers[] = { "one", "two", "three" };
+ * String[] ret = modulename.foo( numbers };
+ */
+%typemap(jni) char **STRING_ARRAY "jobjectArray"
+%typemap(jtype) char **STRING_ARRAY "String[]"
+%typemap(jstype) char **STRING_ARRAY "String[]"
+%typemap(in) char **STRING_ARRAY (jint size) {
+ int i = 0;
+ if ($input) {
+ size = JCALL1(GetArrayLength, jenv, $input);
+#ifdef __cplusplus
+ $1 = new char*[size+1];
+#else
+ $1 = (char **)malloc((size+1) * sizeof(char *));
+#endif
+ for (i = 0; i<size; i++) {
+ jstring j_string = (jstring)JCALL2(GetObjectArrayElement, jenv, $input, i);
+ const char *c_string = JCALL2(GetStringUTFChars, jenv, j_string, 0);
+#ifdef __cplusplus
+ $1[i] = new char [strlen(c_string)+1];
+#else
+ $1[i] = (char *)malloc((strlen(c_string)+1) * sizeof(const char *));
+#endif
+ strcpy($1[i], c_string);
+ JCALL2(ReleaseStringUTFChars, jenv, j_string, c_string);
+ JCALL1(DeleteLocalRef, jenv, j_string);
+ }
+ $1[i] = 0;
+ } else {
+ $1 = 0;
+ size = 0;
+ }
+}
+
+%typemap(freearg) char **STRING_ARRAY {
+ int i;
+ for (i=0; i<size$argnum; i++)
+#ifdef __cplusplus
+ delete[] $1[i];
+ delete[] $1;
+#else
+ free($1[i]);
+ free($1);
+#endif
+}
+
+%typemap(out) char **STRING_ARRAY {
+ if ($1) {
+ int i;
+ jsize len=0;
+ jstring temp_string;
+ const jclass clazz = JCALL1(FindClass, jenv, "java/lang/String");
+
+ while ($1[len]) len++;
+ $result = JCALL3(NewObjectArray, jenv, len, clazz, NULL);
+ /* exception checking omitted */
+
+ for (i=0; i<len; i++) {
+ temp_string = JCALL1(NewStringUTF, jenv, *$1++);
+ JCALL3(SetObjectArrayElement, jenv, $result, i, temp_string);
+ JCALL1(DeleteLocalRef, jenv, temp_string);
+ }
+ }
+}
+
+%typemap(javain) char **STRING_ARRAY "$javainput"
+%typemap(javaout) char **STRING_ARRAY {
+ return $jnicall;
+ }
+
+/*
+ * char **STRING_OUT typemaps.
+ * These are typemaps for returning strings when using a C char ** parameter type.
+ * The returned string appears in the 1st element of the passed in Java String array.
+ *
+ * Example usage wrapping:
+ * %apply char **STRING_OUT { char **string_out };
+ * void foo(char **string_out);
+ *
+ * Java usage:
+ * String stringOutArray[] = { "" };
+ * modulename.foo(stringOutArray);
+ * System.out.println( stringOutArray[0] );
+ */
+%typemap(jni) char **STRING_OUT "jobjectArray"
+%typemap(jtype) char **STRING_OUT "String[]"
+%typemap(jstype) char **STRING_OUT "String[]"
+%typemap(javain) char **STRING_OUT "$javainput"
+
+%typemap(in) char **STRING_OUT($*1_ltype temp) {
+ if (!$input) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
+ return $null;
+ }
+ if (JCALL1(GetArrayLength, jenv, $input) == 0) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
+ return $null;
+ }
+ $1 = &temp;
+ *$1 = 0;
+}
+
+%typemap(argout) char **STRING_OUT {
+ jstring jnewstring = NULL;
+ if ($1) {
+ jnewstring = JCALL1(NewStringUTF, jenv, *$1);
+ }
+ JCALL3(SetObjectArrayElement, jenv, $input, 0, jnewstring);
+}
+
+/*
+ * char *BYTE typemaps.
+ * These are input typemaps for mapping a Java byte[] array to a C char array.
+ * Note that as a Java array is used and thus passed by reference, the C routine
+ * can return data to Java via the parameter.
+ *
+ * Example usage wrapping:
+ * void foo(char *array);
+ *
+ * Java usage:
+ * byte b[] = new byte[20];
+ * modulename.foo(b);
+ */
+%typemap(jni) char *BYTE "jbyteArray"
+%typemap(jtype) char *BYTE "byte[]"
+%typemap(jstype) char *BYTE "byte[]"
+%typemap(in) char *BYTE {
+ $1 = (char *) JCALL2(GetByteArrayElements, jenv, $input, 0);
+}
+
+%typemap(argout) char *BYTE {
+ JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *) $1, 0);
+}
+
+%typemap(javain) char *BYTE "$javainput"
+
+/* Prevent default freearg typemap from being used */
+%typemap(freearg) char *BYTE ""
+
+/*
+ * unsigned char *NIOBUFFER typemaps.
+ * This is for mapping Java nio buffers to C char arrays.
+ * It is useful for performance critical code as it reduces the memory copy an marshaling overhead.
+ * Note: The Java buffer has to be allocated with allocateDirect.
+ *
+ * Example usage wrapping:
+ * %apply unsigned char *NIOBUFFER { unsigned char *buf };
+ * void foo(unsigned char *buf);
+ *
+ * Java usage:
+ * java.nio.ByteBuffer b = ByteBuffer.allocateDirect(20);
+ * modulename.foo(b);
+ */
+%typemap(jni) unsigned char *NIOBUFFER "jobject"
+%typemap(jtype) unsigned char *NIOBUFFER "java.nio.ByteBuffer"
+%typemap(jstype) unsigned char *NIOBUFFER "java.nio.ByteBuffer"
+%typemap(javain,
+ pre=" assert $javainput.isDirect() : \"Buffer must be allocated direct.\";") unsigned char *NIOBUFFER "$javainput"
+%typemap(javaout) unsigned char *NIOBUFFER {
+ return $jnicall;
+}
+%typemap(in) unsigned char *NIOBUFFER {
+ $1 = (unsigned char *) JCALL1(GetDirectBufferAddress, jenv, $input);
+ if ($1 == NULL) {
+ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "Unable to get address of a java.nio.ByteBuffer direct byte buffer. Buffer must be a direct buffer and not a non-direct buffer.");
+ }
+}
+%typemap(memberin) unsigned char *NIOBUFFER {
+ if ($input) {
+ $1 = $input;
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(freearg) unsigned char *NIOBUFFER ""
+
diff --git a/contrib/tools/swig/Lib/java/ya.make b/contrib/tools/swig/Lib/java/ya.make
new file mode 100644
index 00000000000..677a3eab232
--- /dev/null
+++ b/contrib/tools/swig/Lib/java/ya.make
@@ -0,0 +1,24 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+LICENSE(LicenseRef-scancode-swig)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+SUBSCRIBER(g:cpp-contrib)
+
+VERSION(4.3.1)
+
+ORIGINAL_SOURCE(https://github.com/swig/swig/archive/v4.3.1.tar.gz)
+
+ADDINCL(
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib/java
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib
+)
+
+END()
diff --git a/contrib/tools/swig/Lib/math.i b/contrib/tools/swig/Lib/math.i
new file mode 100644
index 00000000000..ac8d9a6eb4a
--- /dev/null
+++ b/contrib/tools/swig/Lib/math.i
@@ -0,0 +1,89 @@
+/* -----------------------------------------------------------------------------
+ * math.i
+ *
+ * SWIG library file for floating point operations.
+ * ----------------------------------------------------------------------------- */
+
+%module math
+%{
+#include <math.h>
+%}
+
+#ifndef SWIGPHP /* PHP already provides all these functions except fabs() */
+
+extern double cos(double x);
+/* Cosine of x */
+
+extern double sin(double x);
+/* Sine of x */
+
+extern double tan(double x);
+/* Tangent of x */
+
+extern double acos(double x);
+/* Inverse cosine in range [-PI/2,PI/2], x in [-1,1]. */
+
+extern double asin(double x);
+/* Inverse sine in range [0,PI], x in [-1,1]. */
+
+extern double atan(double x);
+/* Inverse tangent in range [-PI/2,PI/2]. */
+
+extern double atan2(double y, double x);
+/* Inverse tangent of y/x in range [-PI,PI]. */
+
+extern double cosh(double x);
+/* Hyperbolic cosine of x */
+
+extern double sinh(double x);
+/* Hyperbolic sine of x */
+
+extern double tanh(double x);
+/* Hyperbolic tangent of x */
+
+extern double exp(double x);
+/* Natural exponential function e^x */
+
+extern double log(double x);
+/* Natural logarithm ln(x), x > 0 */
+
+extern double log10(double x);
+/* Base 10 logarithm, x > 0 */
+
+extern double pow(double x, double y);
+/* Power function x^y. */
+
+extern double sqrt(double x);
+/* Square root. x >= 0 */
+
+extern double ceil(double x);
+/* Smallest integer not less than x, as a double */
+
+extern double floor(double x);
+/* Largest integer not greater than x, as a double */
+
+extern double fmod(double x, double y);
+/* Floating-point remainder of x/y, with the same sign as x. */
+
+#endif
+
+extern double fabs(double x);
+/* Absolute value of x */
+
+#ifndef SWIGPHP /* PHP already provides these constants and it's an error to redefine them */
+
+#define M_E 2.7182818284590452354
+#define M_LOG2E 1.4426950408889634074
+#define M_LOG10E 0.43429448190325182765
+#define M_LN2 0.69314718055994530942
+#define M_LN10 2.30258509299404568402
+#define M_PI 3.14159265358979323846
+#define M_PI_2 1.57079632679489661923
+#define M_PI_4 0.78539816339744830962
+#define M_1_PI 0.31830988618379067154
+#define M_2_PI 0.63661977236758134308
+#define M_2_SQRTPI 1.12837916709551257390
+#define M_SQRT2 1.41421356237309504880
+#define M_SQRT1_2 0.70710678118654752440
+
+#endif
diff --git a/contrib/tools/swig/Lib/perl5/.yandex_meta/licenses.list.txt b/contrib/tools/swig/Lib/perl5/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..8aad0f87d67
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/.yandex_meta/licenses.list.txt
@@ -0,0 +1,916 @@
+====================File: COPYRIGHT====================
+SWIG Copyright and Authors
+--------------------------
+
+Copyright (c) 1995-2023 The SWIG Developers
+Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
+Copyright (c) 1998-2005 University of Chicago.
+Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
+
+Portions also copyrighted by:
+ Network Applied Communication Laboratory, Inc
+ Information-technology Promotion Agency, Japan
+
+Active SWIG Developers:
+ William Fulton ([email protected]) (SWIG core, Java, C#, Windows, Cygwin)
+ Olly Betts ([email protected]) (PHP)
+ Joseph Wang ([email protected]) (R)
+ Momtchil Momtchev ([email protected]) (Javascript Node-API)
+ Simon Marchetto ([email protected]) (Scilab)
+ Zackery Spytz ([email protected]) (OCaml, SWIG core)
+
+Past SWIG developers and major contributors include:
+ Dave Beazley ([email protected]) (SWIG core, Python, Tcl, Perl)
+ Henning Thielemann ([email protected]) (Modula3)
+ Matthias Köppe ([email protected]) (Guile, MzScheme)
+ Luigi Ballabio ([email protected]) (STL wrapping)
+ Mikel Bancroft ([email protected]) (Allegro CL)
+ Surendra Singhi ([email protected]) (CLISP, CFFI)
+ Marcelo Matus ([email protected]) (SWIG core, Python, UTL[python,perl,tcl,ruby])
+ Art Yerkes ([email protected]) (OCaml)
+ Lyle Johnson ([email protected]) (Ruby)
+ Charlie Savage ([email protected]) (Ruby)
+ Thien-Thi Nguyen ([email protected]) (build/test/misc)
+ Richard Palmer ([email protected]) (PHP)
+ Sam Liddicott - Ananova Ltd ([email protected]) (PHP)
+ Tim Hockin - Sun Microsystems ([email protected]) (PHP)
+ Kevin Ruland (PHP)
+ Shibukawa Yoshiki (Japanese Translation)
+ Jason Stewart ([email protected]) (Perl5)
+ Loic Dachary (Perl5)
+ David Fletcher (Perl5)
+ Gary Holt (Perl5)
+ Masaki Fukushima (Ruby)
+ Scott Michel ([email protected]) (Java directors)
+ Tiger Feng ([email protected]) (SWIG core)
+ Mark Rose ([email protected]) (Directors)
+ Jonah Beckford ([email protected]) (CHICKEN)
+ Ahmon Dancy ([email protected]) (Allegro CL)
+ Dirk Gerrits (Allegro CL)
+ Neil Cawse (C#)
+ Harco de Hilster (Java)
+ Alexey Dyachenko ([email protected]) (Tcl)
+ Bob Techentin (Tcl)
+ Martin Froehlich <[email protected]> (Guile)
+ Marcio Luis Teixeira <[email protected]> (Guile)
+ Duncan Temple Lang (R)
+ Miklos Vajna <[email protected]> (PHP directors)
+ Mark Gossage ([email protected]) (Lua)
+ Raman Gopalan ([email protected]) (eLua)
+ Gonzalo Garramuno ([email protected]) (Ruby, Ruby's UTL)
+ John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
+ Baozeng Ding <[email protected]> (Scilab)
+ Ian Lance Taylor (Go)
+ Dmitry Kabak ([email protected]) (Doxygen)
+ Vadim Zeitlin (PCRE, Python, Doxygen)
+ Stefan Zager ([email protected]) (Python)
+ Vincent Couvert (Scilab)
+ Sylvestre Ledru (Scilab)
+ Wolfgang Frisch (Scilab)
+ Oliver Buchtala ([email protected]) (Javascript)
+ Neha Narang ([email protected]) (Javascript)
+ Xavier Delacour ([email protected]) (Octave)
+ David Nadlinger ([email protected]) (D)
+ Leif Middelschulte ([email protected]) (C)
+
+Past contributors include:
+ James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
+ Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
+ Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
+ Klaus Wiederänders, Richard Beare, Hans Oesterholt.
+ (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
+
+Past students:
+ Songyan Feng (Chicago).
+ Xinghua Shi (Chicago).
+ Jing Cao (Chicago).
+ Aquinas Hobor (Chicago).
+
+Historically, the following people contributed to early versions of SWIG.
+Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
+at Los Alamos National Laboratory were the first users. Patrick
+Tullmann at the University of Utah suggested the idea of automatic
+documentation generation. John Schmidt and Kurtis Bleeker at the
+University of Utah tested out the early versions. Chris Johnson
+supported SWIG's developed at the University of Utah. John Buckman,
+Larry Virden, and Tom Schwaller provided valuable input on the first
+releases and improving the portability of SWIG. David Fletcher and
+Gary Holt have provided a great deal of input on improving SWIG's
+Perl5 implementation. Kevin Butler contributed the first Windows NT
+port.
+
+Early bug reports and patches:
+Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
+Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
+Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
+Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
+Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
+Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
+Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
+Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
+Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
+Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
+Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
+Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
+Zhong Ren.
+
+
+
+====================File: LICENSE-GPL====================
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+====================File: LICENSE-UNIVERSITIES====================
+SWIG is distributed under the following terms:
+
+I.
+
+Copyright (c) 1995-1998
+The University of Utah and the Regents of the University of California
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following two paragraphs
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+IN NO EVENT SHALL THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, THE
+UNIVERSITY OF UTAH OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
+PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
+EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, AND THE UNIVERSITY OF UTAH
+SPECIFICALLY DISCLAIM ANY WARRANTIES,INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
+THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+
+II.
+
+This software includes contributions that are Copyright (c) 1998-2005
+University of Chicago.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer. Redistributions
+in binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution. Neither the name of
+the University of Chicago nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF CHICAGO AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+CHICAGO OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+III.
+
+This software includes contributions that are Copyright (c) 2005-2006
+Arizona Board of Regents (University of Arizona).
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following paragraph
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF ARIZONA AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+ARIZONA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+====================LicenseRef-scancode-swig====================
+SWIG is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. See the LICENSE-GPL file for
+the full terms of the GNU General Public license version 3.
+
+Portions of SWIG are also licensed under the terms of the licenses
+in the file LICENSE-UNIVERSITIES. You must observe the terms of
+these licenses, as well as the terms of the GNU General Public License,
+when you distribute SWIG.
+
+The SWIG library and examples, under the Lib and Examples top level
+directories, are distributed under the following terms:
+
+ You may copy, modify, distribute, and make derivative works based on
+ this software, in source code or object code form, without
+ restriction. If you distribute the software to others, you may do
+ so according to the terms of your choice. This software is offered as
+ is, without warranty of any kind.
+
+See the COPYRIGHT file for a list of contributors to SWIG and their
+copyright notices. \ No newline at end of file
diff --git a/contrib/tools/swig/Lib/perl5/Makefile.pl b/contrib/tools/swig/Lib/perl5/Makefile.pl
new file mode 100644
index 00000000000..cffdc8e79f8
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/Makefile.pl
@@ -0,0 +1,19 @@
+# File : Makefile.pl
+# MakeMaker file for a SWIG module. Use this file if you are
+# producing a module for general use or distribution.
+#
+# 1. Modify the file as appropriate. Replace $module with the
+# real name of your module and wrapper file.
+# 2. Run perl as 'perl Makefile.pl'
+# 3. Type 'make' to build your module
+# 4. Type 'make install' to install your module.
+#
+# See "Programming Perl", 2nd. Ed, for more gory details than
+# you ever wanted to know.
+
+use ExtUtils::MakeMaker;
+WriteMakefile(
+ 'NAME' => '$module', # Name of your module
+ 'LIBS' => [''], # Custom libraries (if any)
+ 'OBJECT' => '$module_wrap.o' # Object files
+);
diff --git a/contrib/tools/swig/Lib/perl5/argcargv.i b/contrib/tools/swig/Lib/perl5/argcargv.i
new file mode 100644
index 00000000000..ee238130b5a
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/argcargv.i
@@ -0,0 +1,30 @@
+/* -------------------------------------------------------------
+ * SWIG library containing argc and argv multi-argument typemaps
+ * ------------------------------------------------------------- */
+
+%typemap(in) (int ARGC, char **ARGV) {
+ int i;
+ SSize_t len;
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV) {
+ SWIG_croak("in method '$symname', Expecting reference to argv array");
+ goto fail;
+ }
+ len = av_len(av) + 1;
+ $1 = ($1_ltype) len;
+ $2 = (char **) malloc((len+1)*sizeof(char *));
+ for (i = 0; i < len; i++) {
+ SV **tv = av_fetch(av, i, 0);
+ $2[i] = SvPV_nolen(*tv);
+ }
+ $2[i] = NULL;
+}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) {
+ AV *av = (AV *)SvRV($input);
+ $1 = SvTYPE(av) == SVt_PVAV;
+}
+
+%typemap(freearg) (int ARGC, char **ARGV) {
+ free((void *)$2);
+}
diff --git a/contrib/tools/swig/Lib/perl5/attribute.i b/contrib/tools/swig/Lib/perl5/attribute.i
new file mode 100644
index 00000000000..779716cd2ea
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/attribute.i
@@ -0,0 +1 @@
+%include <typemaps/attribute.swg>
diff --git a/contrib/tools/swig/Lib/perl5/carrays.i b/contrib/tools/swig/Lib/perl5/carrays.i
new file mode 100644
index 00000000000..c1e6db3f0b4
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/carrays.i
@@ -0,0 +1 @@
+%include <typemaps/carrays.swg>
diff --git a/contrib/tools/swig/Lib/perl5/cmalloc.i b/contrib/tools/swig/Lib/perl5/cmalloc.i
new file mode 100644
index 00000000000..248f06b961b
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/cmalloc.i
@@ -0,0 +1 @@
+%include <typemaps/cmalloc.swg>
diff --git a/contrib/tools/swig/Lib/perl5/cpointer.i b/contrib/tools/swig/Lib/perl5/cpointer.i
new file mode 100644
index 00000000000..d824792fa7a
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/cpointer.i
@@ -0,0 +1 @@
+%include <typemaps/cpointer.swg>
diff --git a/contrib/tools/swig/Lib/perl5/cstring.i b/contrib/tools/swig/Lib/perl5/cstring.i
new file mode 100644
index 00000000000..ede9c596aef
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/cstring.i
@@ -0,0 +1 @@
+%include <typemaps/cstring.swg>
diff --git a/contrib/tools/swig/Lib/perl5/director.swg b/contrib/tools/swig/Lib/perl5/director.swg
new file mode 100644
index 00000000000..f0a6614fc5c
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/director.swg
@@ -0,0 +1,317 @@
+/* -----------------------------------------------------------------------------
+ * director.swg
+ *
+ * This file contains support for director classes so that Perl proxy
+ * methods can be called from C++.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DIRECTOR_PERL_HEADER_
+#define SWIG_DIRECTOR_PERL_HEADER_
+
+#include <string>
+#include <iostream>
+#include <exception>
+#include <vector>
+#include <map>
+
+
+/*
+ Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the
+ native C++ RTTI and dynamic_cast<>. But be aware that directors
+ could stop working when using this option.
+*/
+#ifdef SWIG_DIRECTOR_NORTTI
+/*
+ When we don't use the native C++ RTTI, we implement a minimal one
+ only for Directors.
+*/
+# ifndef SWIG_DIRECTOR_RTDIR
+# define SWIG_DIRECTOR_RTDIR
+
+namespace Swig {
+ class Director;
+ SWIGINTERN std::map<void *, Director *>& get_rtdir_map() {
+ static std::map<void *, Director *> rtdir_map;
+ return rtdir_map;
+ }
+
+ SWIGINTERNINLINE void set_rtdir(void *vptr, Director *rtdir) {
+ get_rtdir_map()[vptr] = rtdir;
+ }
+
+ SWIGINTERNINLINE Director *get_rtdir(void *vptr) {
+ std::map<void *, Director *>::const_iterator pos = get_rtdir_map().find(vptr);
+ Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0;
+ return rtdir;
+ }
+}
+# endif /* SWIG_DIRECTOR_RTDIR */
+
+# define SWIG_DIRECTOR_CAST(ARG) Swig::get_rtdir(static_cast<void *>(ARG))
+# define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast<void *>(ARG1), ARG2)
+
+#else
+
+# define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG)
+# define SWIG_DIRECTOR_RGTR(ARG1, ARG2)
+
+#endif /* SWIG_DIRECTOR_NORTTI */
+
+extern "C" {
+ struct swig_type_info;
+}
+
+namespace Swig {
+
+ /* memory handler */
+ struct GCItem {
+ virtual ~GCItem() {}
+
+ virtual int get_own() const {
+ return 0;
+ }
+ };
+
+ struct GCItem_var {
+ GCItem_var(GCItem *item = 0) : _item(item) {
+ }
+
+ GCItem_var& operator=(GCItem *item) {
+ GCItem *tmp = _item;
+ _item = item;
+ delete tmp;
+ return *this;
+ }
+
+ ~GCItem_var() {
+ delete _item;
+ }
+
+ GCItem *operator->() const {
+ return _item;
+ }
+
+ private:
+ GCItem *_item;
+ };
+
+ struct GCItem_Object : GCItem {
+ GCItem_Object(int own) : _own(own) {
+ }
+
+ virtual ~GCItem_Object() {
+ }
+
+ int get_own() const {
+ return _own;
+ }
+
+ private:
+ int _own;
+ };
+
+ template <typename Type>
+ struct GCItem_T : GCItem {
+ GCItem_T(Type *ptr) : _ptr(ptr) {
+ }
+
+ virtual ~GCItem_T() {
+ delete _ptr;
+ }
+
+ private:
+ Type *_ptr;
+ };
+
+ template <typename Type>
+ struct GCArray_T : GCItem {
+ GCArray_T(Type *ptr) : _ptr(ptr) {
+ }
+
+ virtual ~GCArray_T() {
+ delete[] _ptr;
+ }
+
+ private:
+ Type *_ptr;
+ };
+
+ /* base class for director exceptions */
+ class DirectorException : public std::exception {
+ public:
+ virtual SV *getNative() const = 0;
+ };
+
+ /* exceptions emitted by Perl */
+ class DirectorMethodException : public DirectorException {
+ protected:
+ SV *err;
+ public:
+ DirectorMethodException(SV *sv = sv_mortalcopy(ERRSV)) : err(sv) {
+ SvREFCNT_inc(err);
+ }
+
+ const char *what() const throw() {
+ return SvPV_nolen(err);
+ }
+
+ SV *getNative() const {
+ return sv_2mortal(newSVsv(err));
+ }
+
+ static void raise(SV *sv) {
+ throw DirectorMethodException(sv);
+ }
+ };
+
+ /* exceptions emitted by wrap code */
+ class DirectorWrapException : public DirectorException {
+ protected:
+ std::string msg;
+ DirectorWrapException(const char *str) : msg(str) {
+ }
+
+ public:
+ virtual ~DirectorWrapException() throw() {
+ }
+
+ const char *what() const throw() {
+ return msg.c_str();
+ }
+
+ virtual SV *getNative() const {
+ return sv_2mortal(newSVpvn(msg.data(), msg.size()));
+ }
+ };
+
+ class DirectorTypeMismatchException : public DirectorWrapException {
+ public:
+ DirectorTypeMismatchException(const char *str) : DirectorWrapException(str) {
+ }
+
+ static void raise(const char *type, const char *msg) {
+ std::string err = std::string(type);
+ err += ": ";
+ err += msg;
+ throw DirectorTypeMismatchException(err.c_str());
+ }
+ };
+
+ class DirectorPureVirtualException : public DirectorWrapException {
+ public:
+ DirectorPureVirtualException(const char *name)
+ : DirectorWrapException("SWIG director pure virtual method called: ") {
+ msg += name;
+ }
+
+ static void raise(const char *name) {
+ throw DirectorPureVirtualException(name);
+ }
+ };
+
+ /* director base class */
+ class Director {
+ private:
+ /* pointer to the wrapped perl object */
+ SV *swig_self;
+ /* class of wrapped perl object */
+ std::string swig_class;
+ /* flag indicating whether the object is owned by perl or c++ */
+ mutable bool swig_disown_flag;
+
+ /* decrement the reference count of the wrapped perl object */
+ void swig_decref() const {
+ if (swig_disown_flag) {
+ SvREFCNT_dec(swig_self);
+ }
+ }
+
+ public:
+ /* wrap a Perl object. */
+ Director(SV *pkg) : swig_disown_flag(false) {
+ STRLEN len;
+ char *str = SvPV(pkg, len);
+ swig_class = std::string(str, len);
+ swig_self = newRV_inc((SV *)newHV());
+ }
+
+ /* discard our reference at destruction */
+ virtual ~Director() {
+ swig_decref();
+ }
+
+ /* return a pointer to the wrapped Perl object */
+ SV *swig_get_self() const {
+ return swig_self;
+ }
+
+ const char *swig_get_class() const {
+ return swig_class.c_str();
+ }
+
+ /* acquire ownership of the wrapped Perl object (the sense of "disown" is from perl) */
+ void swig_disown() const {
+ if (!swig_disown_flag) {
+ swig_disown_flag=true;
+ swig_incref();
+ }
+ }
+
+ /* increase the reference count of the wrapped Perl object */
+ void swig_incref() const {
+ if (swig_disown_flag) {
+ SvREFCNT_inc(swig_self);
+ }
+ }
+
+ /* methods to implement pseudo protected director members */
+ virtual bool swig_get_inner(const char * /* swig_protected_method_name */) const {
+ return true;
+ }
+
+ virtual void swig_set_inner(const char * /* swig_protected_method_name */, bool /* swig_val */) const {
+ }
+
+ /* ownership management */
+ private:
+ typedef std::map<void *, GCItem_var> swig_ownership_map;
+ mutable swig_ownership_map swig_owner;
+
+ public:
+ template <typename Type>
+ void swig_acquire_ownership_array(Type *vptr) const {
+ if (vptr) {
+ swig_owner[vptr] = new GCArray_T<Type>(vptr);
+ }
+ }
+
+ template <typename Type>
+ void swig_acquire_ownership(Type *vptr) const {
+ if (vptr) {
+ swig_owner[vptr] = new GCItem_T<Type>(vptr);
+ }
+ }
+
+ void swig_acquire_ownership_obj(void *vptr, int own) const {
+ if (vptr && own) {
+ swig_owner[vptr] = new GCItem_Object(own);
+ }
+ }
+
+ int swig_release_ownership(void *vptr) const {
+ int own = 0;
+ if (vptr) {
+ swig_ownership_map::iterator iter = swig_owner.find(vptr);
+ if (iter != swig_owner.end()) {
+ own = iter->second->get_own();
+ swig_owner.erase(iter);
+ }
+ }
+ return own;
+ }
+ };
+
+}
+
+#endif
+
diff --git a/contrib/tools/swig/Lib/perl5/exception.i b/contrib/tools/swig/Lib/perl5/exception.i
new file mode 100644
index 00000000000..b786f25e299
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/exception.i
@@ -0,0 +1,5 @@
+%include <typemaps/exception.swg>
+
+%insert("runtime") {
+ %define_as(SWIG_exception(code, msg), %block(%error(code, msg); SWIG_fail; ))
+}
diff --git a/contrib/tools/swig/Lib/perl5/extra-install.list b/contrib/tools/swig/Lib/perl5/extra-install.list
new file mode 100644
index 00000000000..db93830aabf
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/extra-install.list
@@ -0,0 +1,2 @@
+# see top-level Makefile.in
+Makefile.pl noembed.h
diff --git a/contrib/tools/swig/Lib/perl5/factory.i b/contrib/tools/swig/Lib/perl5/factory.i
new file mode 100644
index 00000000000..46a0a8733e7
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/factory.i
@@ -0,0 +1 @@
+%include <typemaps/factory.swg>
diff --git a/contrib/tools/swig/Lib/perl5/noembed.h b/contrib/tools/swig/Lib/perl5/noembed.h
new file mode 100644
index 00000000000..4e30f1117c8
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/noembed.h
@@ -0,0 +1,116 @@
+/* Workaround perl5 global namespace pollution. Note that undefining library
+ * functions like fopen will not solve the problem on all platforms as fopen
+ * might be a macro on Windows but not necessarily on other operating systems. */
+#ifdef do_open
+ #undef do_open
+#endif
+#ifdef do_close
+ #undef do_close
+#endif
+#ifdef do_exec
+ #undef do_exec
+#endif
+#ifdef scalar
+ #undef scalar
+#endif
+#ifdef list
+ #undef list
+#endif
+#ifdef apply
+ #undef apply
+#endif
+#ifdef convert
+ #undef convert
+#endif
+#ifdef Error
+ #undef Error
+#endif
+#ifdef form
+ #undef form
+#endif
+#ifdef vform
+ #undef vform
+#endif
+#ifdef LABEL
+ #undef LABEL
+#endif
+#ifdef METHOD
+ #undef METHOD
+#endif
+#ifdef Move
+ #undef Move
+#endif
+#ifdef yylex
+ #undef yylex
+#endif
+#ifdef yyparse
+ #undef yyparse
+#endif
+#ifdef yyerror
+ #undef yyerror
+#endif
+#ifdef invert
+ #undef invert
+#endif
+#ifdef ref
+ #undef ref
+#endif
+#ifdef read
+ #undef read
+#endif
+#ifdef write
+ #undef write
+#endif
+#ifdef eof
+ #undef eof
+#endif
+#ifdef close
+ #undef close
+#endif
+#ifdef rewind
+ #undef rewind
+#endif
+#ifdef free
+ #undef free
+#endif
+#ifdef malloc
+ #undef malloc
+#endif
+#ifdef calloc
+ #undef calloc
+#endif
+#ifdef Stat
+ #undef Stat
+#endif
+#ifdef check
+ #undef check
+#endif
+#ifdef seekdir
+ #undef seekdir
+#endif
+#ifdef open
+ #undef open
+#endif
+#ifdef readdir
+ #undef readdir
+#endif
+#ifdef bind
+ #undef bind
+#endif
+#ifdef access
+ #undef access
+#endif
+#ifdef stat
+ #undef stat
+#endif
+#ifdef seed
+ #undef seed
+#endif
+
+#ifdef bool
+ /* Leave if macro is from C99 stdbool.h */
+ #ifndef __bool_true_false_are_defined
+ #undef bool
+ #endif
+#endif
+
diff --git a/contrib/tools/swig/Lib/perl5/perl5.swg b/contrib/tools/swig/Lib/perl5/perl5.swg
new file mode 100644
index 00000000000..693c2b9457c
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perl5.swg
@@ -0,0 +1,42 @@
+/* ------------------------------------------------------------
+ * perl.swg
+ *
+ * Perl configuration module.
+ * ------------------------------------------------------------ */
+
+/* ------------------------------------------------------------
+ * Inner macros
+ * ------------------------------------------------------------ */
+%include <perlmacros.swg>
+
+/* ------------------------------------------------------------
+ * The runtime part
+ * ------------------------------------------------------------ */
+%include <perlruntime.swg>
+
+/* ------------------------------------------------------------
+ * Special user directives
+ * ------------------------------------------------------------ */
+%include <perluserdir.swg>
+
+/* ------------------------------------------------------------
+ * Typemap specializations
+ * ------------------------------------------------------------ */
+%include <perltypemaps.swg>
+
+/* ------------------------------------------------------------
+ * Overloaded operator support
+ * ------------------------------------------------------------ */
+%include <perlopers.swg>
+
+/* ------------------------------------------------------------
+ * Warnings for Perl keywords
+ * ------------------------------------------------------------ */
+%include <perlkw.swg>
+
+/* ------------------------------------------------------------
+ * The Perl initialization function
+ * ------------------------------------------------------------ */
+%include <perlinit.swg>
+
+
diff --git a/contrib/tools/swig/Lib/perl5/perlerrors.swg b/contrib/tools/swig/Lib/perl5/perlerrors.swg
new file mode 100644
index 00000000000..0e563b62df1
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlerrors.swg
@@ -0,0 +1,36 @@
+/* -----------------------------------------------------------------------------
+ * error manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGINTERN const char*
+SWIG_Perl_ErrorType(int code) {
+ switch(code) {
+ case SWIG_MemoryError:
+ return "MemoryError";
+ case SWIG_IOError:
+ return "IOError";
+ case SWIG_RuntimeError:
+ return "RuntimeError";
+ case SWIG_IndexError:
+ return "IndexError";
+ case SWIG_TypeError:
+ return "TypeError";
+ case SWIG_DivisionByZero:
+ return "ZeroDivisionError";
+ case SWIG_OverflowError:
+ return "OverflowError";
+ case SWIG_SyntaxError:
+ return "SyntaxError";
+ case SWIG_ValueError:
+ return "ValueError";
+ case SWIG_SystemError:
+ return "SystemError";
+ case SWIG_AttributeError:
+ return "AttributeError";
+ case SWIG_NullReferenceError:
+ return "NullReferenceError";
+ default:
+ return "RuntimeError";
+ }
+}
+
diff --git a/contrib/tools/swig/Lib/perl5/perlfragments.swg b/contrib/tools/swig/Lib/perl5/perlfragments.swg
new file mode 100644
index 00000000000..45d25d1f6c3
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlfragments.swg
@@ -0,0 +1,23 @@
+/*
+
+ Create a file with this name, 'perlfragments.swg', in your working
+ directory and add all the %fragments you want to take precedence
+ over the ones defined by default by swig.
+
+ For example, if you add:
+
+ %fragment(SWIG_AsVal_frag(int),"header") {
+ SWIGINTERNINLINE int
+ SWIG_AsVal(int)(PyObject *obj, int *val)
+ {
+ <your code here>;
+ }
+ }
+
+ this will replace the code used to retrieve an integer value for all
+ the typemaps that need it, including:
+
+ int, std::vector<int>, std::list<std::pair<int,int> >, etc.
+
+
+*/
diff --git a/contrib/tools/swig/Lib/perl5/perlhead.swg b/contrib/tools/swig/Lib/perl5/perlhead.swg
new file mode 100644
index 00000000000..11ea50a9edf
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlhead.swg
@@ -0,0 +1,94 @@
+#ifdef __cplusplus
+/* Needed on some windows machines---since MS plays funny games with the header files under C++ */
+#include <math.h>
+#include <stdlib.h>
+extern "C" {
+#endif
+
+#if __GNUC__ >= 10
+#if defined(__cplusplus)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvolatile"
+#endif
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#if __GNUC__ >= 10
+#if defined(__cplusplus)
+#pragma GCC diagnostic pop
+#endif
+#endif
+
+/* PERL_REVISION was added in Perl 5.6. */
+#if !defined PERL_REVISION || (PERL_REVISION-0 == 5 && PERL_VERSION-0 < 8)
+# error SWIG requires Perl >= 5.8.0
+#endif
+
+#if defined(WIN32) && defined(PERL_OBJECT) && !defined(PerlIO_exportFILE)
+#define PerlIO_exportFILE(fh,fl) (FILE*)(fh)
+#endif
+
+#ifndef SvIOK_UV
+# define SvIOK_UV(sv) (SvIOK(sv) && (SvUVX(sv) == SvIVX(sv)))
+#endif
+
+#ifndef SvUOK
+# define SvUOK(sv) SvIOK_UV(sv)
+#endif
+
+#ifndef IVSIZE
+# ifdef LONGSIZE
+# define IVSIZE LONGSIZE
+# else
+# define IVSIZE 4 /* A bold guess, but the best we can make. */
+# endif
+#endif
+
+#ifndef INT2PTR
+# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
+# define PTRV UV
+# define INT2PTR(any,d) (any)(d)
+# else
+# if PTRSIZE == LONGSIZE
+# define PTRV unsigned long
+# else
+# define PTRV unsigned
+# endif
+# define INT2PTR(any,d) (any)(PTRV)(d)
+# endif
+
+# define NUM2PTR(any,d) (any)(PTRV)(d)
+# define PTR2IV(p) INT2PTR(IV,p)
+# define PTR2UV(p) INT2PTR(UV,p)
+# define PTR2NV(p) NUM2PTR(NV,p)
+
+# if PTRSIZE == LONGSIZE
+# define PTR2ul(p) (unsigned long)(p)
+# else
+# define PTR2ul(p) INT2PTR(unsigned long,p)
+# endif
+#endif /* !INT2PTR */
+
+#ifndef SvPV_nolen
+# define SvPV_nolen(x) SvPV(x,PL_na)
+#endif
+
+#ifndef get_sv
+# define get_sv perl_get_sv
+#endif
+
+#ifndef ERRSV
+# define ERRSV get_sv("@",FALSE)
+#endif
+
+#ifndef pTHX_
+#define pTHX_
+#endif
+
+#include <string.h>
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/tools/swig/Lib/perl5/perlinit.swg b/contrib/tools/swig/Lib/perl5/perlinit.swg
new file mode 100644
index 00000000000..c26b93fadb9
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlinit.swg
@@ -0,0 +1,78 @@
+
+/* Export the SWIG initialization function */
+%header %{
+#ifdef __cplusplus
+extern "C"
+#endif
+#ifndef MULTIPLICITY
+SWIGEXPORT void SWIG_init (CV* cv);
+#else
+SWIGEXPORT void SWIG_init (pTHXo_ CV* cv);
+#endif
+%}
+
+/* Module initialization function */
+
+%insert(init) "swiginit.swg"
+
+%init %{
+
+#if defined(__cplusplus) && ! defined(XSPROTO)
+extern "C"
+#endif
+
+XS(SWIG_init) {
+ dXSARGS;
+ int i;
+ (void)items;
+
+ SWIG_InitializeModule(0);
+
+ /* Install commands */
+ for (i = 0; swig_commands[i].name; i++) {
+ /* Casts only needed for Perl < 5.10. */
+#ifdef __cplusplus
+ newXS(const_cast<char*>(swig_commands[i].name), swig_commands[i].wrapper, const_cast<char*>(__FILE__));
+#else
+ newXS((char*)swig_commands[i].name, swig_commands[i].wrapper, (char*)__FILE__);
+#endif
+ }
+
+ /* Install variables */
+ for (i = 0; swig_variables[i].name; i++) {
+ SV *sv;
+ sv = get_sv(swig_variables[i].name, TRUE | 0x2 | GV_ADDMULTI);
+ if (swig_variables[i].type) {
+ SWIG_MakePtr(sv,(void *)1, *swig_variables[i].type,0);
+ } else {
+ sv_setiv(sv,(IV) 0);
+ }
+ swig_create_magic(sv, swig_variables[i].name, swig_variables[i].set, swig_variables[i].get);
+ }
+
+ /* Install constant */
+ for (i = 0; swig_constants[i].type; i++) {
+ SV *sv;
+ sv = get_sv(swig_constants[i].name, TRUE | 0x2 | GV_ADDMULTI);
+ switch(swig_constants[i].type) {
+ case SWIG_INT:
+ sv_setiv(sv, (IV) swig_constants[i].lvalue);
+ break;
+ case SWIG_FLOAT:
+ sv_setnv(sv, (double) swig_constants[i].dvalue);
+ break;
+ case SWIG_STRING:
+ sv_setpv(sv, (const char *) swig_constants[i].pvalue);
+ break;
+ case SWIG_POINTER:
+ SWIG_MakePtr(sv, swig_constants[i].pvalue, *(swig_constants[i].ptype),0);
+ break;
+ case SWIG_BINARY:
+ SWIG_MakePackedObj(sv, swig_constants[i].pvalue, swig_constants[i].lvalue, *(swig_constants[i].ptype));
+ break;
+ default:
+ break;
+ }
+ SvREADONLY_on(sv);
+ }
+%}
diff --git a/contrib/tools/swig/Lib/perl5/perlkw.swg b/contrib/tools/swig/Lib/perl5/perlkw.swg
new file mode 100644
index 00000000000..00648e0bf38
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlkw.swg
@@ -0,0 +1,251 @@
+/* Warnings for Perl keywords */
+#define PERLKW(x) %keywordwarn("'" `x` "' is a perl keyword") `x`
+#define PERLBN(x) %builtinwarn("'" `x` "' conflicts with a built-in name in perl") "::" `x`
+
+
+/*
+
+ From http://www.rocketaware.com/perl/perlfunc/
+
+*/
+
+/* Functions for SCALARs or strings*/
+PERLBN(chomp);
+PERLBN(chop);
+PERLBN(chr);
+PERLBN(crypt);
+PERLBN(hex);
+PERLBN(index);
+PERLBN(lc);
+PERLBN(lcfirst);
+PERLBN(length);
+PERLBN(oct);
+PERLBN(ord);
+PERLBN(pack);
+PERLBN(reverse);
+PERLBN(rindex);
+PERLBN(sprintf);
+PERLBN(substr);
+PERLBN(uc);
+PERLBN(ucfirst);
+
+/* Regular expressions and pattern matching */
+PERLBN(m);
+PERLBN(pos);
+PERLBN(quotemeta);
+PERLBN(split);
+PERLBN(study);
+
+/* Numeric functions */
+PERLBN(abs);
+PERLBN(atan2);
+PERLBN(cos);
+PERLBN(exp);
+PERLBN(hex);
+PERLBN(int);
+PERLBN(log);
+PERLBN(oct);
+PERLBN(rand);
+PERLBN(sin);
+PERLBN(sqrt);
+PERLBN(srand);
+
+
+/* Functions for real @ARRAYs*/
+PERLBN(pop);
+PERLBN(push);
+PERLBN(shift);
+PERLBN(splice);
+PERLBN(unshift);
+
+/* Functions for list data*/
+PERLBN(grep);
+PERLBN(join);
+PERLBN(map);
+PERLBN(qw);
+PERLBN(reverse);
+PERLBN(sort);
+PERLBN(unpack);
+
+
+/* Functions for real %HASHes*/
+PERLBN(delete);
+PERLBN(each);
+PERLBN(exists);
+PERLBN(keys);
+PERLBN(values);
+
+
+/* Input and output functions*/
+
+PERLBN(binmode);
+PERLBN(close);
+PERLBN(closedir);
+PERLBN(dbmclose);
+PERLBN(dbmopen);
+PERLBN(die);
+PERLBN(eof);
+PERLBN(fileno);
+PERLBN(flock);
+PERLBN(format);
+PERLBN(getc);
+PERLBN(print);
+PERLBN(printf);
+PERLBN(read);
+PERLBN(readdir);
+PERLBN(rewinddir);
+PERLBN(seek);
+PERLBN(seekdir);
+PERLBN(select);
+PERLBN(syscall);
+PERLBN(sysread);
+PERLBN(sysseek);
+PERLBN(syswrite);
+PERLBN(tell);
+PERLBN(telldir);
+PERLBN(truncate);
+PERLBN(warn);
+PERLBN(write);
+
+
+/* Functions for fixed length data or records*/
+PERLBN(pack);
+PERLBN(read);
+PERLBN(syscall);
+PERLBN(sysread);
+PERLBN(syswrite);
+PERLBN(unpack);
+PERLBN(vec);
+
+
+/* Functions for filehandles, files, or directories */
+PERLBN(chdir);
+PERLBN(chmod);
+PERLBN(chown);
+PERLBN(chroot);
+PERLBN(fcntl);
+PERLBN(glob);
+PERLBN(ioctl);
+PERLBN(link);
+PERLBN(lstat);
+PERLBN(mkdir);
+PERLBN(open);
+PERLBN(opendir);
+PERLBN(readlink);
+PERLBN(rename);
+PERLBN(rmdir);
+PERLBN(stat);
+PERLBN(symlink);
+PERLBN(umask);
+PERLBN(unlink);
+PERLBN(utime);
+
+
+/* Keywords related to the control flow of your perl program */
+PERLKW(caller);
+PERLKW(continue);
+PERLKW(die);
+PERLKW(do);
+PERLKW(dump);
+PERLKW(eval);
+PERLKW(exit);
+PERLKW(goto);
+PERLKW(last);
+PERLKW(next);
+PERLKW(redo);
+PERLKW(return);
+PERLKW(sub);
+PERLKW(wantarray);
+
+
+/* Keywords related to scoping */
+PERLKW(caller);
+PERLKW(import);
+PERLKW(local);
+PERLKW(my);
+PERLKW(package);
+PERLKW(use);
+
+
+/* Miscellaneous functions */
+PERLBN("defined");
+PERLBN(dump);
+PERLBN(eval);
+PERLBN(formline);
+PERLBN(local);
+PERLBN(my);
+PERLBN(reset);
+PERLBN(scalar);
+PERLBN(undef);
+PERLBN(wantarray);
+
+
+/* Functions for processes and process groups */
+PERLBN(alarm);
+PERLBN(exec);
+PERLBN(fork);
+PERLBN(getpgrp);
+PERLBN(getppid);
+PERLBN(getpriority);
+PERLBN(kill);
+PERLBN(pipe);
+PERLBN(setpgrp);
+PERLBN(setpriority);
+PERLBN(sleep);
+PERLBN(system);
+PERLBN(times);
+PERLBN(wait);
+PERLBN(waitpid);
+
+
+/* Keywords related to perl modules */
+PERLKW(do);
+PERLKW(import);
+PERLKW(no);
+PERLKW(package);
+PERLKW(require);
+PERLKW(use);
+
+
+/* Keywords related to classes and object-orientedness */
+PERLKW(bless);
+PERLKW(dbmclose);
+PERLKW(dbmopen);
+PERLKW(package);
+PERLKW(ref);
+PERLKW(tie);
+PERLKW(tied);
+PERLKW(untie);
+PERLKW(use);
+
+/* Functions new in perl5 */
+PERLBN(abs);
+PERLBN(bless);
+PERLBN(chomp);
+PERLBN(chr);
+PERLBN(exists);
+PERLBN(formline);
+PERLBN(glob);
+PERLBN(import);
+PERLBN(lc);
+PERLBN(lcfirst);
+PERLBN(map);
+PERLBN(my);
+PERLBN(no);
+PERLBN(prototype);
+PERLBN(qx);
+PERLBN(qw);
+PERLBN(readline);
+PERLBN(readpipe);
+PERLBN(ref);
+PERLBN(sub);
+PERLBN(sysopen);
+PERLBN(tie);
+PERLBN(tied);
+PERLBN(uc);
+PERLBN(ucfirst);
+PERLBN(untie);
+PERLBN(use);
+
+#undef PERLKW
+#undef PERLBN
diff --git a/contrib/tools/swig/Lib/perl5/perlmacros.swg b/contrib/tools/swig/Lib/perl5/perlmacros.swg
new file mode 100644
index 00000000000..4917f6efc59
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlmacros.swg
@@ -0,0 +1,2 @@
+%include <typemaps/swigmacros.swg>
+
diff --git a/contrib/tools/swig/Lib/perl5/perlmain.i b/contrib/tools/swig/Lib/perl5/perlmain.i
new file mode 100644
index 00000000000..14f1cf2191a
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlmain.i
@@ -0,0 +1,77 @@
+/* -----------------------------------------------------------------------------
+ * perlmain.i
+ *
+ * Code to statically rebuild perl5.
+ * ----------------------------------------------------------------------------- */
+
+// This module provides support for building a new version of the
+// Perl executable. This will be necessary on systems that do
+// not support shared libraries and may be necessary with C++
+// extensions.
+//
+// This module may only build a stripped down version of the
+// Perl executable. Thus, it may be necessary (or desirable)
+// to hand-edit this file for your particular application. To
+// do this, simply copy this file from swig_lib/perl5/perlmain.i
+// to your working directory and make the appropriate modifications.
+//
+// This library file works with Perl 5.003. It may work with earlier
+// versions, but it hasn't been tested. As far as I know, this
+// library is C++ safe.
+
+%{
+
+static void xs_init _((pTHX));
+static PerlInterpreter *my_perl;
+
+int perl_eval(char *string) {
+ char *argv[2];
+ argv[0] = string;
+ argv[1] = (char *) 0;
+ return perl_call_argv("eval",0,argv);
+}
+
+int
+main(int argc, char **argv, char **env)
+{
+ int exitstatus;
+
+ my_perl = perl_alloc();
+ if (!my_perl)
+ exit(1);
+ perl_construct( my_perl );
+
+ exitstatus = perl_parse( my_perl, xs_init, argc, argv, (char **) NULL );
+ if (exitstatus)
+ exit( exitstatus );
+
+ /* Initialize all of the module variables */
+
+ exitstatus = perl_run( my_perl );
+
+ perl_destruct( my_perl );
+ perl_free( my_perl );
+
+ exit( exitstatus );
+}
+
+/* Register any extra external extensions */
+
+/* Do not delete this line--writemain depends on it */
+/* EXTERN_C void boot_DynaLoader _((CV* cv)); */
+
+static void
+xs_init(pTHX)
+{
+/* dXSUB_SYS; */
+ char *file = __FILE__;
+ {
+ /* newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); */
+ newXS(SWIG_name, SWIG_init, file);
+#ifdef SWIGMODINIT
+ SWIGMODINIT
+#endif
+ }
+}
+
+%}
diff --git a/contrib/tools/swig/Lib/perl5/perlopers.swg b/contrib/tools/swig/Lib/perl5/perlopers.swg
new file mode 100644
index 00000000000..e7d13b678ad
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlopers.swg
@@ -0,0 +1,54 @@
+/* ------------------------------------------------------------
+ * Overloaded operator support
+ * ------------------------------------------------------------ */
+
+#ifdef __cplusplus
+
+// These are auto-supported by the Perl-module
+%rename(__plusplus__) *::operator++;
+%rename(__minmin__) *::operator--;
+%rename(__add__) *::operator+;
+%rename(__sub__) *::operator-;
+%rename(__neg__) *::operator-();
+%rename(__neg__) *::operator-() const;
+%rename(__mul__) *::operator*;
+%rename(__div__) *::operator/;
+%rename(__eq__) *::operator==;
+%rename(__ne__) *::operator!=;
+%rename(__mod__) *::operator%;
+%rename(__gt__) *::operator>;
+%rename(__lt__) *::operator<;
+%rename(__not__) *::operator!;
+%rename(__le__) *::operator<=;
+%rename(__ge__) *::operator>=;
+%rename(__and__) *::operator&;
+%rename(__or__) *::operator|;
+%rename(__iadd__) *::operator+=;
+%rename(__isub__) *::operator-=;
+
+// These are renamed, but no test exists in operator_overload_runme.pl
+%ignoreoperator(EQ) operator=;
+
+// These are renamed, but no 'use overload...' is added
+%rename(__lshift__) *::operator<<;
+%rename(__rshift__) *::operator>>;
+%rename(__xor__) *::operator^;
+%rename(__invert__) *::operator~;
+%rename(__call__) *::operator();
+
+/* Ignored operators */
+%ignoreoperator(LAND) operator&&;
+%ignoreoperator(LOR) operator||;
+%ignoreoperator(MULEQ) operator*=;
+%ignoreoperator(DIVEQ) operator/=;
+%ignoreoperator(MODEQ) operator%=;
+%ignoreoperator(LSHIFTEQ) operator<<=;
+%ignoreoperator(RSHIFTEQ) operator>>=;
+%ignoreoperator(ANDEQ) operator&=;
+%ignoreoperator(OREQ) operator|=;
+%ignoreoperator(XOREQ) operator^=;
+%ignoreoperator(ARROWSTAR) operator->*;
+%ignoreoperator(INDEX) operator[];
+
+
+#endif /* __cplusplus */
diff --git a/contrib/tools/swig/Lib/perl5/perlprimtypes.swg b/contrib/tools/swig/Lib/perl5/perlprimtypes.swg
new file mode 100644
index 00000000000..57f390a2549
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlprimtypes.swg
@@ -0,0 +1,364 @@
+/* ------------------------------------------------------------
+ * Primitive Types
+ * ------------------------------------------------------------ */
+
+/* bool */
+
+%fragment(SWIG_From_frag(bool),"header") {
+SWIGINTERNINLINE SV *
+SWIG_From_dec(bool)(bool value)
+{
+ return boolSV(value);
+}
+}
+
+%fragment(SWIG_AsVal_frag(bool),"header") {
+SWIGINTERN int
+SWIG_AsVal_dec(bool)(SV *obj, bool* val)
+{
+ if (obj == &PL_sv_yes) {
+ if (val) *val = true;
+ return SWIG_OK;
+ } else if (obj == &PL_sv_no) {
+ if (val) *val = false;
+ return SWIG_OK;
+ } else {
+ if (val) *val = SvTRUE(obj) ? true : false;
+ return SWIG_AddCast(SWIG_OK);
+ }
+}
+}
+
+
+/* long */
+
+%fragment(SWIG_From_frag(long),"header") {
+SWIGINTERNINLINE SV *
+SWIG_From_dec(long)(long value)
+{
+ SV *sv;
+ if (IVSIZE >= sizeof(value) || (value >= IV_MIN && value <= IV_MAX))
+ sv = newSViv(value);
+ else
+ sv = newSVpvf("%ld", value);
+ return sv_2mortal(sv);
+}
+}
+
+%fragment(SWIG_AsVal_frag(long),"header",
+ fragment="<limits.h>",
+ fragment="<stdlib.h>",
+ fragment="SWIG_CanCastAsInteger") {
+SWIGINTERN int
+SWIG_AsVal_dec(long)(SV *obj, long* val)
+{
+ if (SvUOK(obj)) {
+ UV v = SvUV(obj);
+ if (UVSIZE < sizeof(*val) || v <= LONG_MAX) {
+ if (val) *val = v;
+ return SWIG_OK;
+ }
+ return SWIG_OverflowError;
+ } else if (SvIOK(obj)) {
+ IV v = SvIV(obj);
+ if (IVSIZE <= sizeof(*val) || (v >= LONG_MIN && v <= LONG_MAX)) {
+ if(val) *val = v;
+ return SWIG_OK;
+ }
+ return SWIG_OverflowError;
+ } else {
+ int dispatch = 0;
+ const char *nptr = SvPV_nolen(obj);
+ if (nptr) {
+ char *endptr;
+ long v;
+ errno = 0;
+ v = strtol(nptr, &endptr,0);
+ if (errno == ERANGE) {
+ errno = 0;
+ return SWIG_OverflowError;
+ } else {
+ if (*endptr == '\0') {
+ if (val) *val = v;
+ return SWIG_Str2NumCast(SWIG_OK);
+ }
+ }
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+ if (val) *val = (long)(d);
+ return res;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+
+/* unsigned long */
+
+%fragment(SWIG_From_frag(unsigned long),"header") {
+SWIGINTERNINLINE SV *
+SWIG_From_dec(unsigned long)(unsigned long value)
+{
+ SV *sv;
+ if (UVSIZE >= sizeof(value) || value <= UV_MAX)
+ sv = newSVuv(value);
+ else
+ sv = newSVpvf("%lu", value);
+ return sv_2mortal(sv);
+}
+}
+
+%fragment(SWIG_AsVal_frag(unsigned long),"header",
+ fragment="<limits.h>",
+ fragment="<stdlib.h>",
+ fragment="SWIG_CanCastAsInteger") {
+SWIGINTERN int
+SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val)
+{
+ if (SvUOK(obj)) {
+ UV v = SvUV(obj);
+ if (UVSIZE <= sizeof(*val) || v <= ULONG_MAX) {
+ if (val) *val = v;
+ return SWIG_OK;
+ }
+ return SWIG_OverflowError;
+ } else if (SvIOK(obj)) {
+ IV v = SvIV(obj);
+ if (v >= 0 && (IVSIZE <= sizeof(*val) || v <= ULONG_MAX)) {
+ if (val) *val = v;
+ return SWIG_OK;
+ }
+ return SWIG_OverflowError;
+ } else {
+ int dispatch = 0;
+ const char *nptr = SvPV_nolen(obj);
+ if (nptr) {
+ char *endptr;
+ unsigned long v;
+ errno = 0;
+ v = strtoul(nptr, &endptr,0);
+ if (errno == ERANGE) {
+ errno = 0;
+ return SWIG_OverflowError;
+ } else {
+ if (*endptr == '\0') {
+ if (val) *val = v;
+ return SWIG_Str2NumCast(SWIG_OK);
+ }
+ }
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+ if (val) *val = (unsigned long)(d);
+ return res;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+
+/* long long */
+
+%fragment(SWIG_From_frag(long long),"header",
+ fragment="SWIG_LongLongAvailable",
+ fragment="<stdio.h>") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERNINLINE SV *
+SWIG_From_dec(long long)(long long value)
+{
+ SV *sv;
+ if (IVSIZE >= sizeof(value) || (value >= IV_MIN && value <= IV_MAX))
+ sv = newSViv((IV)(value));
+ else {
+ //sv = newSVpvf("%lld", value); doesn't work in non 64bit Perl
+ char temp[256];
+ SWIG_snprintf(temp, sizeof(temp), "%lld", value);
+ sv = newSVpv(temp, 0);
+ }
+ return sv_2mortal(sv);
+}
+%#endif
+}
+
+%fragment(SWIG_AsVal_frag(long long),"header",
+ fragment="SWIG_LongLongAvailable",
+ fragment="<stdlib.h>",
+ fragment="SWIG_CanCastAsInteger") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERN int
+SWIG_AsVal_dec(long long)(SV *obj, long long *val)
+{
+ if (SvUOK(obj)) {
+ UV v = SvUV(obj);
+ /* pretty sure this could allow v == LLONG MAX */
+ if (UVSIZE < sizeof(*val) || v < LLONG_MAX) {
+ if (val) *val = v;
+ return SWIG_OK;
+ }
+ return SWIG_OverflowError;
+ } else if (SvIOK(obj)) {
+ IV v = SvIV(obj);
+ if (IVSIZE <= sizeof(*val) || (v >= LLONG_MIN && v <= LLONG_MAX)) {
+ if (val) *val = v;
+ return SWIG_OK;
+ }
+ return SWIG_OverflowError;
+ } else {
+ int dispatch = 0;
+ const char *nptr = SvPV_nolen(obj);
+ if (nptr) {
+ char *endptr;
+ long long v;
+ errno = 0;
+ v = strtoll(nptr, &endptr,0);
+ if (errno == ERANGE) {
+ errno = 0;
+ return SWIG_OverflowError;
+ } else {
+ if (*endptr == '\0') {
+ if (val) *val = v;
+ return SWIG_Str2NumCast(SWIG_OK);
+ }
+ }
+ }
+ if (!dispatch) {
+ const double mant_max = 1LL << DBL_MANT_DIG;
+ const double mant_min = -mant_max;
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, mant_min, mant_max)) {
+ if (val) *val = (long long)(d);
+ return res;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+%#endif
+}
+
+/* unsigned long long */
+
+%fragment(SWIG_From_frag(unsigned long long),"header",
+ fragment="SWIG_LongLongAvailable",
+ fragment="<stdio.h>") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERNINLINE SV *
+SWIG_From_dec(unsigned long long)(unsigned long long value)
+{
+ SV *sv;
+ if (UVSIZE >= sizeof(value) || value <= UV_MAX)
+ sv = newSVuv((UV)(value));
+ else {
+ //sv = newSVpvf("%llu", value); doesn't work in non 64bit Perl
+ char temp[256];
+ SWIG_snprintf(temp, sizeof(temp), "%llu", value);
+ sv = newSVpv(temp, 0);
+ }
+ return sv_2mortal(sv);
+}
+%#endif
+}
+
+%fragment(SWIG_AsVal_frag(unsigned long long),"header",
+ fragment="SWIG_LongLongAvailable",
+ fragment="<stdlib.h>",
+ fragment="SWIG_CanCastAsInteger") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERN int
+SWIG_AsVal_dec(unsigned long long)(SV *obj, unsigned long long *val)
+{
+ if (SvUOK(obj)) {
+ /* pretty sure this should be conditional on
+ * (UVSIZE <= sizeof(*val) || v <= ULLONG_MAX) */
+ if (val) *val = SvUV(obj);
+ return SWIG_OK;
+ } else if (SvIOK(obj)) {
+ IV v = SvIV(obj);
+ if (v >= 0 && (IVSIZE <= sizeof(*val) || v <= ULLONG_MAX)) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ return SWIG_OverflowError;
+ }
+ } else {
+ int dispatch = 0;
+ const char *nptr = SvPV_nolen(obj);
+ if (nptr) {
+ char *endptr;
+ unsigned long long v;
+ errno = 0;
+ v = strtoull(nptr, &endptr,0);
+ if (errno == ERANGE) {
+ errno = 0;
+ return SWIG_OverflowError;
+ } else {
+ if (*endptr == '\0') {
+ if (val) *val = v;
+ return SWIG_Str2NumCast(SWIG_OK);
+ }
+ }
+ }
+ if (!dispatch) {
+ const double mant_max = 1LL << DBL_MANT_DIG;
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) {
+ if (val) *val = (unsigned long long)(d);
+ return res;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+%#endif
+}
+
+/* double */
+
+%fragment(SWIG_From_frag(double),"header") {
+SWIGINTERNINLINE SV *
+SWIG_From_dec(double)(double value)
+{
+ return sv_2mortal(newSVnv(value));
+}
+}
+
+%fragment(SWIG_AsVal_frag(double),"header") {
+SWIGINTERN int
+SWIG_AsVal_dec(double)(SV *obj, double *val)
+{
+ if (SvNIOK(obj)) {
+ if (val) *val = SvNV(obj);
+ return SWIG_OK;
+ } else if (SvIOK(obj)) {
+ if (val) *val = (double) SvIV(obj);
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ const char *nptr = SvPV_nolen(obj);
+ if (nptr) {
+ char *endptr;
+ double v;
+ errno = 0;
+ v = strtod(nptr, &endptr);
+ if (errno == ERANGE) {
+ errno = 0;
+ return SWIG_OverflowError;
+ } else {
+ if (*endptr == '\0') {
+ if (val) *val = v;
+ return SWIG_Str2NumCast(SWIG_OK);
+ }
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+}
diff --git a/contrib/tools/swig/Lib/perl5/perlrun.swg b/contrib/tools/swig/Lib/perl5/perlrun.swg
new file mode 100644
index 00000000000..dfb2c8ee2d8
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlrun.swg
@@ -0,0 +1,493 @@
+/* -----------------------------------------------------------------------------
+ * perlrun.swg
+ *
+ * This file contains the runtime support for Perl modules
+ * and includes code for managing global variables and pointer
+ * type checking.
+ * ----------------------------------------------------------------------------- */
+
+#define SWIG_PERL_OBJECT_DECL
+#define SWIG_PERL_OBJECT_CALL
+
+/* Common SWIG API */
+
+/* for raw pointers */
+#define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Perl_ConvertPtr(SWIG_PERL_OBJECT_CALL obj, pp, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj, pp, type, flags,own) SWIG_Perl_ConvertPtrAndOwn(SWIG_PERL_OBJECT_CALL obj, pp, type, flags, own)
+#define SWIG_NewPointerObj(p, type, flags) SWIG_Perl_NewPointerObj(SWIG_PERL_OBJECT_CALL p, type, flags)
+#define SWIG_AcquirePtr(ptr, src) SWIG_Perl_AcquirePtr(ptr, src)
+#define swig_owntype int
+
+/* for raw packed data */
+#define SWIG_ConvertPacked(obj, p, s, type) SWIG_Perl_ConvertPacked(SWIG_PERL_OBJECT_CALL obj, p, s, type)
+#define SWIG_NewPackedObj(p, s, type) SWIG_Perl_NewPackedObj(SWIG_PERL_OBJECT_CALL p, s, type)
+
+/* for class or struct pointers */
+#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
+
+/* for C or C++ function pointers */
+#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_ConvertPtr(obj, pptr, type, 0)
+#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NewPointerObj(ptr, type, 0)
+
+/* for C++ member pointers, ie, member methods */
+#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewMemberObj(ptr, sz, type) SWIG_NewPackedObj(ptr, sz, type)
+
+
+/* Runtime API */
+
+#define SWIG_GetModule(clientdata) SWIG_Perl_GetModule(clientdata)
+#define SWIG_SetModule(clientdata, pointer) SWIG_Perl_SetModule(pointer)
+
+
+/* Error manipulation */
+
+#define SWIG_ErrorType(code) SWIG_Perl_ErrorType(code)
+#define SWIG_Error(code, msg) sv_setpvf(get_sv("@", GV_ADD), "%s %s", SWIG_ErrorType(code), msg)
+#define SWIG_fail goto fail
+
+/* Perl-specific SWIG API */
+
+#define SWIG_MakePtr(sv, ptr, type, flags) SWIG_Perl_MakePtr(SWIG_PERL_OBJECT_CALL sv, ptr, type, flags)
+#define SWIG_MakePackedObj(sv, p, s, type) SWIG_Perl_MakePackedObj(SWIG_PERL_OBJECT_CALL sv, p, s, type)
+#define SWIG_SetError(str) SWIG_Error(SWIG_RuntimeError, str)
+
+
+#define SWIG_PERL_DECL_ARGS_1(arg1) (SWIG_PERL_OBJECT_DECL arg1)
+#define SWIG_PERL_CALL_ARGS_1(arg1) (SWIG_PERL_OBJECT_CALL arg1)
+#define SWIG_PERL_DECL_ARGS_2(arg1, arg2) (SWIG_PERL_OBJECT_DECL arg1, arg2)
+#define SWIG_PERL_CALL_ARGS_2(arg1, arg2) (SWIG_PERL_OBJECT_CALL arg1, arg2)
+
+/* -----------------------------------------------------------------------------
+ * pointers/data manipulation
+ * ----------------------------------------------------------------------------- */
+
+/* For backward compatibility only */
+#define SWIG_POINTER_EXCEPTION 0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SWIG_OWNER SWIG_POINTER_OWN
+#define SWIG_SHADOW SWIG_OWNER << 1
+
+#define SWIG_MAYBE_PERL_OBJECT SWIG_PERL_OBJECT_DECL
+
+/* SWIG Perl macros */
+
+/* Macro to declare an XS function */
+#ifndef XSPROTO
+# define XSPROTO(name) void name(pTHX_ CV* cv)
+#endif
+
+/* Macro to call an XS function */
+#ifndef MULTIPLICITY
+# define SWIG_CALLXS(_name) _name(cv)
+#else
+# define SWIG_CALLXS(_name) _name(PERL_GET_THX, cv)
+#endif
+
+#define MAGIC_PPERL
+#define SWIGCLASS_STATIC static SWIGUNUSED
+
+#ifndef MULTIPLICITY
+#define SWIG_MAGIC(a,b) (SV *a, MAGIC *b)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef int (*SwigMagicFunc)(SV *, MAGIC *);
+#ifdef __cplusplus
+}
+#endif
+
+#else /* MULTIPLICITY */
+
+#define SWIG_MAGIC(a,b) (struct interpreter *interp, SV *a, MAGIC *b)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef int (*SwigMagicFunc)(struct interpreter *, SV *, MAGIC *);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MULTIPLICITY */
+
+static void SWIGUNUSED SWIG_croak_null()
+{
+ SV *err = get_sv("@", GV_ADD);
+ if (sv_isobject(err))
+ croak(0);
+ else
+ croak("%s", SvPV_nolen(err));
+}
+
+
+/*
+ Define how strict is the cast between strings and integers/doubles
+ when overloading between these types occurs.
+
+ The default is making it as strict as possible by using SWIG_AddCast
+ when needed.
+
+ You can use -DSWIG_PERL_NO_STRICT_STR2NUM at compilation time to
+ disable the SWIG_AddCast, making the casting between string and
+ numbers less strict.
+
+ In the end, we try to solve the overloading between strings and
+ numerical types in the more natural way, but if you can avoid it,
+ well, avoid it using %rename, for example.
+*/
+#ifndef SWIG_PERL_NO_STRICT_STR2NUM
+# ifndef SWIG_PERL_STRICT_STR2NUM
+# define SWIG_PERL_STRICT_STR2NUM
+# endif
+#endif
+#ifdef SWIG_PERL_STRICT_STR2NUM
+/* string takes precedence */
+#define SWIG_Str2NumCast(x) SWIG_AddCast(x)
+#else
+/* number takes precedence */
+#define SWIG_Str2NumCast(x) x
+#endif
+
+
+
+#include <stdlib.h>
+
+SWIGRUNTIME const char *
+SWIG_Perl_TypeProxyName(const swig_type_info *type) {
+ if (!type) return NULL;
+ if (type->clientdata != NULL) {
+ return (const char*) type->clientdata;
+ }
+ else {
+ return type->name;
+ }
+}
+
+/* Identical to SWIG_TypeCheck, except for strcmp comparison */
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeProxyCheck(const char *c, swig_type_info *ty) {
+ if (ty) {
+ swig_cast_info *iter = ty->cast;
+ while (iter) {
+ if (strcmp(SWIG_Perl_TypeProxyName(iter->type), c) == 0) {
+ if (iter == ty->cast)
+ return iter;
+ /* Move iter to the top of the linked list */
+ iter->prev->next = iter->next;
+ if (iter->next)
+ iter->next->prev = iter->prev;
+ iter->next = ty->cast;
+ iter->prev = 0;
+ if (ty->cast) ty->cast->prev = iter;
+ ty->cast = iter;
+ return iter;
+ }
+ iter = iter->next;
+ }
+ }
+ return 0;
+}
+
+/* Acquire a pointer value */
+
+SWIGRUNTIME int
+SWIG_Perl_AcquirePtr(SWIG_MAYBE_PERL_OBJECT SV *SWIGUNUSEDPARM(sv), int SWIGUNUSEDPARM(own)) {
+ /* TODO */
+ return 0;
+}
+
+/* Function for getting a pointer value */
+
+SWIGRUNTIME int
+SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags, int *own) {
+ swig_cast_info *tc;
+ void *voidptr = (void *)0;
+ SV *tsv = 0;
+ int check_owned_pointer_release = (flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE;
+
+ if (own)
+ *own = 0;
+
+ /* If magical, apply more magic */
+ if (SvGMAGICAL(sv))
+ mg_get(sv);
+
+ /* Check to see if this is an object */
+ if (sv_isobject(sv)) {
+ IV tmp = 0;
+ tsv = (SV*) SvRV(sv);
+ if ((SvTYPE(tsv) == SVt_PVHV)) {
+ MAGIC *mg;
+ if (SvMAGICAL(tsv)) {
+ mg = mg_find(tsv,'P');
+ if (mg) {
+ sv = mg->mg_obj;
+ if (sv_isobject(sv)) {
+ tsv = (SV*)SvRV(sv);
+ tmp = SvIV(tsv);
+ }
+ }
+ } else {
+ return SWIG_ERROR;
+ }
+ } else {
+ tmp = SvIV(tsv);
+ }
+ voidptr = INT2PTR(void *,tmp);
+ } else if (! SvOK(sv)) { /* Check for undef */
+ *(ptr) = (void *) 0;
+ return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK;
+ } else if (SvTYPE(sv) == SVt_RV) { /* Check for NULL pointer */
+ if (!SvROK(sv)) {
+ /* In Perl 5.12 and later, SVt_RV == SVt_IV, so sv could be a valid integer value. */
+ if (SvIOK(sv)) {
+ return SWIG_ERROR;
+ } else {
+ /* NULL pointer (reference to undef). */
+ *(ptr) = (void *) 0;
+ return SWIG_OK;
+ }
+ } else {
+ return SWIG_ERROR;
+ }
+ } else { /* Don't know what it is */
+ return SWIG_ERROR;
+ }
+ if (_t) {
+ /* Now see if the types match */
+ char *_c = HvNAME(SvSTASH(SvRV(sv)));
+ tc = SWIG_TypeProxyCheck(_c,_t);
+#ifdef SWIG_DIRECTORS
+ if (!tc && !sv_derived_from(sv,SWIG_Perl_TypeProxyName(_t))) {
+#else
+ if (!tc) {
+#endif
+ return SWIG_ERROR;
+ }
+ {
+ int newmemory = 0;
+ *ptr = SWIG_TypeCast(tc,voidptr,&newmemory);
+ if (newmemory == SWIG_CAST_NEW_MEMORY) {
+ assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+ if (own)
+ *own = *own | SWIG_CAST_NEW_MEMORY;
+ }
+ }
+ } else {
+ *ptr = voidptr;
+ }
+
+ /*
+ * DISOWN implementation: we need a perl guru to check this one.
+ */
+ if (tsv && ((flags & SWIG_POINTER_DISOWN) || check_owned_pointer_release)) {
+ /*
+ * almost copy paste code from below SWIG_POINTER_OWN setting
+ */
+ SV *obj = sv;
+ HV *stash = SvSTASH(SvRV(obj));
+ GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
+ int owned = 0;
+ if (isGV(gv)) {
+ HV *hv = GvHVn(gv);
+ /*
+ * To set ownership (see below), a newSViv(1) entry is added.
+ * Hence, to remove ownership, we delete the entry.
+ */
+ if (hv_exists_ent(hv, obj, 0)) {
+ owned = 1;
+ if (flags & SWIG_POINTER_DISOWN) {
+ hv_delete_ent(hv, obj, 0, 0);
+ }
+ }
+ }
+ if (check_owned_pointer_release && !owned) {
+ return SWIG_ERROR_RELEASE_NOT_OWNED;
+ }
+ }
+
+ if (tsv && (flags & SWIG_POINTER_CLEAR)) {
+ SvIV_set(tsv, 0);
+ }
+
+ return SWIG_OK;
+}
+
+SWIGRUNTIME int
+SWIG_Perl_ConvertPtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_info *_t, int flags) {
+ return SWIG_Perl_ConvertPtrAndOwn(sv, ptr, _t, flags, 0);
+}
+
+SWIGRUNTIME void
+SWIG_Perl_MakePtr(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, swig_type_info *t, int flags) {
+ if (ptr && (flags & (SWIG_SHADOW | SWIG_POINTER_OWN))) {
+ SV *self;
+ SV *obj=newSV(0);
+ HV *hash=newHV();
+ HV *stash;
+ sv_setref_pv(obj, SWIG_Perl_TypeProxyName(t), ptr);
+ stash=SvSTASH(SvRV(obj));
+ if (flags & SWIG_POINTER_OWN) {
+ HV *hv;
+ GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
+ if (!isGV(gv))
+ gv_init(gv, stash, "OWNER", 5, FALSE);
+ hv=GvHVn(gv);
+ hv_store_ent(hv, obj, newSViv(1), 0);
+ }
+ sv_magic((SV *)hash, (SV *)obj, 'P', Nullch, 0);
+ SvREFCNT_dec(obj);
+ self=newRV_noinc((SV *)hash);
+ sv_setsv(sv, self);
+ SvREFCNT_dec((SV *)self);
+ sv_bless(sv, stash);
+ }
+ else {
+ sv_setref_pv(sv, SWIG_Perl_TypeProxyName(t), ptr);
+ }
+}
+
+SWIGRUNTIMEINLINE SV *
+SWIG_Perl_NewPointerObj(SWIG_MAYBE_PERL_OBJECT void *ptr, swig_type_info *t, int flags) {
+ SV *result = sv_newmortal();
+ SWIG_MakePtr(result, ptr, t, flags);
+ return result;
+}
+
+SWIGRUNTIME void
+SWIG_Perl_MakePackedObj(SWIG_MAYBE_PERL_OBJECT SV *sv, void *ptr, int sz, swig_type_info *type) {
+ char result[1024];
+ char *r = result;
+ if ((2*sz + 1 + strlen(SWIG_Perl_TypeProxyName(type))) > 1000) return;
+ *(r++) = '_';
+ r = SWIG_PackData(r,ptr,sz);
+ strcpy(r,SWIG_Perl_TypeProxyName(type));
+ sv_setpv(sv, result);
+}
+
+SWIGRUNTIME SV *
+SWIG_Perl_NewPackedObj(SWIG_MAYBE_PERL_OBJECT void *ptr, int sz, swig_type_info *type) {
+ SV *result = sv_newmortal();
+ SWIG_Perl_MakePackedObj(result, ptr, sz, type);
+ return result;
+}
+
+/* Convert a packed pointer value */
+SWIGRUNTIME int
+SWIG_Perl_ConvertPacked(SWIG_MAYBE_PERL_OBJECT SV *obj, void *ptr, int sz, swig_type_info *ty) {
+ swig_cast_info *tc;
+ const char *c = 0;
+
+ if ((!obj) || (!SvOK(obj))) return SWIG_ERROR;
+ c = SvPV_nolen(obj);
+ /* Pointer values must start with leading underscore */
+ if (*c != '_') return SWIG_ERROR;
+ c++;
+ c = SWIG_UnpackData(c,ptr,sz);
+ if (ty) {
+ tc = SWIG_TypeCheck(c,ty);
+ if (!tc) return SWIG_ERROR;
+ }
+ return SWIG_OK;
+}
+
+
+/* Macros for low-level exception handling */
+#define SWIG_croak(x) { SWIG_Error(SWIG_RuntimeError, x); SWIG_fail; }
+
+
+typedef XSPROTO(SwigPerlWrapper);
+typedef SwigPerlWrapper *SwigPerlWrapperPtr;
+
+/* Structure for command table */
+typedef struct {
+ const char *name;
+ SwigPerlWrapperPtr wrapper;
+} swig_command_info;
+
+/* Information for constant table */
+
+#define SWIG_INT 1
+#define SWIG_FLOAT 2
+#define SWIG_STRING 3
+#define SWIG_POINTER 4
+#define SWIG_BINARY 5
+
+/* Constant information structure */
+typedef struct swig_constant_info {
+ int type;
+ const char *name;
+ long lvalue;
+ double dvalue;
+ void *pvalue;
+ swig_type_info **ptype;
+} swig_constant_info;
+
+
+/* Structure for variable table */
+typedef struct {
+ const char *name;
+ SwigMagicFunc set;
+ SwigMagicFunc get;
+ swig_type_info **type;
+} swig_variable_info;
+
+/* Magic variable code */
+#ifdef __cplusplus
+# define swig_create_magic(s,a,b,c) _swig_create_magic(s,const_cast<char*>(a),b,c)
+#else
+# define swig_create_magic(s,a,b,c) _swig_create_magic(s,(char*)(a),b,c)
+#endif
+#ifndef MULTIPLICITY
+SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(SV *, MAGIC *), int (*get)(SV *,MAGIC *))
+#else
+SWIGRUNTIME void _swig_create_magic(SV *sv, char *name, int (*set)(struct interpreter*, SV *, MAGIC *), int (*get)(struct interpreter*, SV *,MAGIC *))
+#endif
+{
+ MAGIC *mg;
+ sv_magic(sv,sv,'U',name,(I32)strlen(name));
+ mg = mg_find(sv,'U');
+ mg->mg_virtual = (MGVTBL *) malloc(sizeof(MGVTBL));
+ mg->mg_virtual->svt_get = (SwigMagicFunc) get;
+ mg->mg_virtual->svt_set = (SwigMagicFunc) set;
+ mg->mg_virtual->svt_len = 0;
+ mg->mg_virtual->svt_clear = 0;
+ mg->mg_virtual->svt_free = 0;
+}
+
+
+SWIGRUNTIME swig_module_info *
+SWIG_Perl_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
+ static void *type_pointer = (void *)0;
+ SV *pointer;
+
+ /* first check if pointer already created */
+ if (!type_pointer) {
+ pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, FALSE | GV_ADDMULTI);
+ if (pointer && SvOK(pointer)) {
+ type_pointer = INT2PTR(swig_type_info **, SvIV(pointer));
+ }
+ }
+
+ return (swig_module_info *) type_pointer;
+}
+
+SWIGRUNTIME void
+SWIG_Perl_SetModule(swig_module_info *module) {
+ SV *pointer;
+
+ /* create a new pointer */
+ pointer = get_sv("swig_runtime_data::type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, TRUE | GV_ADDMULTI);
+ sv_setiv(pointer, PTR2IV(module));
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/tools/swig/Lib/perl5/perlruntime.swg b/contrib/tools/swig/Lib/perl5/perlruntime.swg
new file mode 100644
index 00000000000..f948023de7a
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlruntime.swg
@@ -0,0 +1,8 @@
+
+%runtime "swigrun.swg" // Common C API type-checking code
+%runtime "swigerrors.swg" // SWIG errors
+%runtime "perlhead.swg" // Perl includes and fixes
+%runtime "perlerrors.swg" // Perl errors
+%runtime "perlrun.swg" // Perl runtime functions
+%runtime "noembed.h" // undefine Perl5 macros
+
diff --git a/contrib/tools/swig/Lib/perl5/perlstrings.swg b/contrib/tools/swig/Lib/perl5/perlstrings.swg
new file mode 100644
index 00000000000..d21b75afbb2
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perlstrings.swg
@@ -0,0 +1,59 @@
+/* ------------------------------------------------------------
+ * utility methods for char strings
+ * ------------------------------------------------------------ */
+
+%fragment("SWIG_AsCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") {
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc)
+{
+ if (SvMAGICAL(obj)) {
+ SV *tmp = sv_newmortal();
+ SvSetSV(tmp, obj);
+ obj = tmp;
+ }
+ if (SvPOK(obj)) {
+ STRLEN len = 0;
+ char *cstr = SvPV(obj, len);
+ size_t size = len + 1;
+ if (cptr) {
+ if (alloc) {
+ if (*alloc == SWIG_NEWOBJ) {
+ *cptr = %new_copy_array(cstr, size, char);
+ } else {
+ *cptr = cstr;
+ *alloc = SWIG_OLDOBJ;
+ }
+ }
+ }
+ if (psize) *psize = size;
+ return SWIG_OK;
+ } else {
+ swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+ if (pchar_descriptor) {
+ char* vptr = 0;
+ if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) {
+ if (cptr) *cptr = vptr;
+ if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0;
+ if (alloc) *alloc = SWIG_OLDOBJ;
+ return SWIG_OK;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+
+%fragment("SWIG_FromCharPtrAndSize","header") {
+SWIGINTERNINLINE SV *
+SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+{
+ SV *obj = sv_newmortal();
+ if (carray) {
+ sv_setpvn(obj, carray, size);
+ } else {
+ sv_setsv(obj, &PL_sv_undef);
+ }
+ return obj;
+}
+}
+
diff --git a/contrib/tools/swig/Lib/perl5/perltypemaps.swg b/contrib/tools/swig/Lib/perl5/perltypemaps.swg
new file mode 100644
index 00000000000..42f8887befd
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perltypemaps.swg
@@ -0,0 +1,104 @@
+/* ------------------------------------------------------------
+ * Typemap specializations for Perl
+ * ------------------------------------------------------------ */
+
+/* ------------------------------------------------------------
+ * Fragment section
+ * ------------------------------------------------------------ */
+
+/*
+ in Perl we need to pass the CPerlObj value, sometimes, so, we define
+ the decl/call macros as needed.
+*/
+
+#define SWIG_AS_DECL_ARGS SWIG_PERL_DECL_ARGS_2
+#define SWIG_AS_CALL_ARGS SWIG_PERL_CALL_ARGS_2
+
+#define SWIG_FROM_DECL_ARGS SWIG_PERL_DECL_ARGS_1
+#define SWIG_FROM_CALL_ARGS SWIG_PERL_CALL_ARGS_1
+
+
+/* Include fundamental fragment definitions */
+%include <typemaps/fragments.swg>
+
+/* Look for user fragments file. */
+%include <perlfragments.swg>
+
+/* Perl fragments for primitive types */
+%include <perlprimtypes.swg>
+
+/* Perl fragments for char* strings */
+%include <perlstrings.swg>
+
+
+/* ------------------------------------------------------------
+ * Unified typemap section
+ * ------------------------------------------------------------ */
+
+/* director support in Perl is experimental */
+#ifndef SWIG_DIRECTOR_TYPEMAPS
+#define SWIG_DIRECTOR_TYPEMAPS
+#endif
+
+
+/* Perl types */
+#define SWIG_Object SV *
+#define VOID_Object &PL_sv_undef
+
+/* Perl $shadow flag */
+#define %newpointer_flags $shadow
+#define %newinstance_flags $shadow
+
+
+/* Complete overload of the output/constant/exception macros */
+
+/* output */
+%define %set_output(obj) $result = obj; argvi++ %enddef
+
+/* append output */
+%define %append_output(obj)
+if (argvi >= items) EXTEND(sp, argvi+1);
+%set_output(obj) %enddef
+
+/* variable output */
+%define %set_varoutput(obj) sv_setsv($result,obj) %enddef
+
+/* constant */
+%define %set_constant(name, obj) %begin_block
+ SV *sv = get_sv((char*) SWIG_prefix name, TRUE | 0x2 | GV_ADDMULTI);
+ sv_setsv(sv, obj);
+ SvREADONLY_on(sv);
+%end_block %enddef
+
+/* raise exception */
+%define %raise(obj, type, desc) sv_setsv(get_sv("@", GV_ADD), obj); SWIG_fail %enddef
+
+/* For directors to raise/throw the original exception */
+%typemap(throws) Swig::DirectorException
+%{ sv_setsv(ERRSV, $1.getNative()); SWIG_fail; %}
+
+/* Include the unified typemap library */
+%include <typemaps/swigtypemaps.swg>
+
+/* ------------------------------------------------------------
+ * Perl extra typemaps / typemap overrides
+ * ------------------------------------------------------------ */
+
+%typemap(varout,type="$1_descriptor") SWIGTYPE *, SWIGTYPE []
+ "sv_setiv(SvRV($result),PTR2IV($1));";
+
+%typemap(varout,type="$1_descriptor") SWIGTYPE &
+ "sv_setiv(SvRV($result),PTR2IV(&$1));";
+
+%typemap(varout,type="$1_descriptor") SWIGTYPE &&
+ "sv_setiv(SvRV($result),PTR2IV(&$1));";
+
+%typemap(varout,type="$&1_descriptor") SWIGTYPE
+ "sv_setiv(SvRV($result), PTR2IV(&$1));";
+
+%typemap(varout,type="$1_descriptor") SWIGTYPE (CLASS::*) {
+ SWIG_MakePackedObj($result, (void *) &$1, sizeof($1), $1_descriptor);
+}
+
+%typemap(varout) SWIGTYPE *const = SWIGTYPE *;
+
diff --git a/contrib/tools/swig/Lib/perl5/perluserdir.swg b/contrib/tools/swig/Lib/perl5/perluserdir.swg
new file mode 100644
index 00000000000..718440e8372
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/perluserdir.swg
@@ -0,0 +1,2 @@
+#define %perlcode %insert("perl")
+
diff --git a/contrib/tools/swig/Lib/perl5/reference.i b/contrib/tools/swig/Lib/perl5/reference.i
new file mode 100644
index 00000000000..b424c533b1b
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/reference.i
@@ -0,0 +1,261 @@
+/* -----------------------------------------------------------------------------
+ * reference.i
+ *
+ * Accept Perl references as pointers
+ * ----------------------------------------------------------------------------- */
+
+/*
+The following methods make Perl references work like simple C
+pointers. References can only be used for simple input/output
+values, not C arrays however. It should also be noted that
+REFERENCES are specific to Perl and not supported in other
+scripting languages at this time.
+
+ int *REFERENCE
+ short *REFERENCE
+ long *REFERENCE
+ unsigned int *REFERENCE
+ unsigned short *REFERENCE
+ unsigned long *REFERENCE
+ unsigned char *REFERENCE
+ float *REFERENCE
+ double *REFERENCE
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include reference.i
+ void neg(double *REFERENCE);
+
+or you can use the %apply directive :
+
+ %include reference.i
+ %apply double *REFERENCE { double *x };
+ void neg(double *x);
+
+Unlike the INOUT mapping described in typemaps.i, this approach directly
+modifies the value of a Perl reference. Thus, you could use it
+as follows :
+
+ $x = 3;
+ neg(\$x);
+ print "$x\n"; # Should print out -3.
+
+*/
+
+%typemap(in) double *REFERENCE (double dvalue), double &REFERENCE(double dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) {
+ printf("Received %d\n", SvTYPE(tempsv));
+ SWIG_croak("Expected a double reference.");
+ }
+ dvalue = SvNV(tempsv);
+ $1 = &dvalue;
+}
+
+%typemap(in) float *REFERENCE (float dvalue), float &REFERENCE(float dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) {
+ SWIG_croak("expected a double reference");
+ }
+ dvalue = (float) SvNV(tempsv);
+ $1 = &dvalue;
+}
+
+%typemap(in) int *REFERENCE (int dvalue), int &REFERENCE (int dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = SvIV(tempsv);
+ $1 = &dvalue;
+}
+
+%typemap(in) short *REFERENCE (short dvalue), short &REFERENCE(short dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (short) SvIV(tempsv);
+ $1 = &dvalue;
+}
+%typemap(in) long *REFERENCE (long dvalue), long &REFERENCE(long dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (long) SvIV(tempsv);
+ $1 = &dvalue;
+}
+%typemap(in) unsigned int *REFERENCE (unsigned int dvalue), unsigned int &REFERENCE(unsigned int dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (unsigned int) SvUV(tempsv);
+ $1 = &dvalue;
+}
+%typemap(in) unsigned short *REFERENCE (unsigned short dvalue), unsigned short &REFERENCE(unsigned short dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (unsigned short) SvUV(tempsv);
+ $1 = &dvalue;
+}
+%typemap(in) unsigned long *REFERENCE (unsigned long dvalue), unsigned long &REFERENCE(unsigned long dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (unsigned long) SvUV(tempsv);
+ $1 = &dvalue;
+}
+
+%typemap(in) unsigned char *REFERENCE (unsigned char dvalue), unsigned char &REFERENCE(unsigned char dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (unsigned char) SvUV(tempsv);
+ $1 = &dvalue;
+}
+
+%typemap(in) signed char *REFERENCE (signed char dvalue), signed char &REFERENCE(signed char dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = (signed char) SvIV(tempsv);
+ $1 = &dvalue;
+}
+
+%typemap(in) bool *REFERENCE (bool dvalue), bool &REFERENCE(bool dvalue)
+{
+ SV *tempsv;
+ if (!SvROK($input)) {
+ SWIG_croak("expected a reference");
+ }
+ tempsv = SvRV($input);
+ if (!SvIOK(tempsv)) {
+ SWIG_croak("expected an integer reference");
+ }
+ dvalue = SvIV(tempsv) ? true : false;
+ $1 = &dvalue;
+}
+
+%typemap(typecheck) int *REFERENCE, int &REFERENCE,
+ short *REFERENCE, short &REFERENCE,
+ long *REFERENCE, long &REFERENCE,
+ signed char *REFERENCE, signed char &REFERENCE,
+ bool *REFERENCE, bool &REFERENCE
+{
+ $1 = SvROK($input) && SvIOK(SvRV($input));
+}
+%typemap(typecheck) double *REFERENCE, double &REFERENCE,
+ float *REFERENCE, float &REFERENCE
+{
+ $1 = SvROK($input);
+ if($1) {
+ SV *tmpsv = SvRV($input);
+ $1 = SvNOK(tmpsv) || SvIOK(tmpsv);
+ }
+}
+%typemap(typecheck) unsigned int *REFERENCE, unsigned int &REFERENCE,
+ unsigned short *REFERENCE, unsigned short &REFERENCE,
+ unsigned long *REFERENCE, unsigned long &REFERENCE,
+ unsigned char *REFERENCE, unsigned char &REFERENCE
+{
+ $1 = SvROK($input);
+ if($1) {
+ SV *tmpsv = SvRV($input);
+ $1 = SvUOK(tmpsv) || SvIOK(tmpsv);
+ }
+}
+
+%typemap(argout) double *REFERENCE, double &REFERENCE,
+ float *REFERENCE, float &REFERENCE
+{
+ SV *tempsv;
+ tempsv = SvRV($arg);
+ if (!$1) SWIG_croak("expected a reference");
+ sv_setnv(tempsv, (double) *$1);
+}
+
+%typemap(argout) int *REFERENCE, int &REFERENCE,
+ short *REFERENCE, short &REFERENCE,
+ long *REFERENCE, long &REFERENCE,
+ signed char *REFERENCE, signed char &REFERENCE,
+ bool *REFERENCE, bool &REFERENCE
+{
+ SV *tempsv;
+ tempsv = SvRV($input);
+ if (!$1) SWIG_croak("expected a reference");
+ sv_setiv(tempsv, (IV) *$1);
+}
+
+%typemap(argout) unsigned int *REFERENCE, unsigned int &REFERENCE,
+ unsigned short *REFERENCE, unsigned short &REFERENCE,
+ unsigned long *REFERENCE, unsigned long &REFERENCE,
+ unsigned char *REFERENCE, unsigned char &REFERENCE
+{
+ SV *tempsv;
+ tempsv = SvRV($input);
+ if (!$1) SWIG_croak("expected a reference");
+ sv_setuv(tempsv, (UV) *$1);
+}
diff --git a/contrib/tools/swig/Lib/perl5/std_auto_ptr.i b/contrib/tools/swig/Lib/perl5/std_auto_ptr.i
new file mode 100644
index 00000000000..3d7ae8ba16e
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_auto_ptr.i
@@ -0,0 +1,39 @@
+/* -----------------------------------------------------------------------------
+ * std_auto_ptr.i
+ *
+ * SWIG library file for handling std::auto_ptr.
+ * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
+ * class when returning a std::auto_ptr from a function.
+ * Memory ownership is passed from the proxy class to the std::auto_ptr in the
+ * C++ layer when passed as a parameter to a wrapped function.
+ * ----------------------------------------------------------------------------- */
+
+%define %auto_ptr(TYPE)
+%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "TYPE *", $symname, $argnum);
+ } else {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ }
+ $1.reset((TYPE *)argp);
+}
+
+%typemap (out) std::auto_ptr< TYPE > %{
+ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
+%}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0);
+ $1 = SWIG_CheckState(res);
+}
+
+%template() std::auto_ptr< TYPE >;
+%enddef
+
+namespace std {
+ template <class T> class auto_ptr {};
+}
diff --git a/contrib/tools/swig/Lib/perl5/std_common.i b/contrib/tools/swig/Lib/perl5/std_common.i
new file mode 100644
index 00000000000..7c1ff232899
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_common.i
@@ -0,0 +1,28 @@
+/* -----------------------------------------------------------------------------
+ * std_common.i
+ *
+ * SWIG typemaps for STL - common utilities
+ * ----------------------------------------------------------------------------- */
+
+%include <std/std_except.i>
+
+%apply size_t { std::size_t };
+
+%fragment("<string>");
+%{
+SWIGINTERN
+double SwigSvToNumber(SV* sv) {
+ return SvIOK(sv) ? double(SvIVX(sv)) : SvNVX(sv);
+}
+SWIGINTERN
+std::string SwigSvToString(SV* sv) {
+ STRLEN len;
+ char *ptr = SvPV(sv, len);
+ return std::string(ptr, len);
+}
+SWIGINTERN
+void SwigSvFromString(SV* sv, const std::string& s) {
+ sv_setpvn(sv,s.data(),s.size());
+}
+%}
+
diff --git a/contrib/tools/swig/Lib/perl5/std_deque.i b/contrib/tools/swig/Lib/perl5/std_deque.i
new file mode 100644
index 00000000000..cb98f6c2fb3
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_deque.i
@@ -0,0 +1 @@
+%include <std/_std_deque.i>
diff --git a/contrib/tools/swig/Lib/perl5/std_except.i b/contrib/tools/swig/Lib/perl5/std_except.i
new file mode 100644
index 00000000000..af98428f65d
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_except.i
@@ -0,0 +1 @@
+%include <typemaps/std_except.swg>
diff --git a/contrib/tools/swig/Lib/perl5/std_list.i b/contrib/tools/swig/Lib/perl5/std_list.i
new file mode 100644
index 00000000000..76f789b96ea
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_list.i
@@ -0,0 +1,377 @@
+/* -----------------------------------------------------------------------------
+ * std_list.i
+ *
+ * SWIG typemaps for std::list types
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <exception.i>
+
+// containers
+
+
+// ------------------------------------------------------------------------
+// std::list
+//
+// The aim of all that follows would be to integrate std::list with
+// Perl as much as possible, namely, to allow the user to pass and
+// be returned Perl arrays.
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::list<T>), f(const std::list<T>&), f(const std::list<T>*):
+// the parameter being read-only, either a Perl sequence or a
+// previously wrapped std::list<T> can be passed.
+// -- f(std::list<T>&), f(std::list<T>*):
+// the parameter must be modified; therefore, only a wrapped std::list
+// can be passed.
+// -- std::list<T> f():
+// the list is returned by copy; therefore, a Perl sequence of T:s
+// is returned which is most easily used in other Perl functions
+// -- std::list<T>& f(), std::list<T>* f(), const std::list<T>& f(),
+// const std::list<T>* f():
+// the list is returned by reference; therefore, a wrapped std::list
+// is returned
+// ------------------------------------------------------------------------
+
+%{
+#include <list>
+%}
+%fragment("<algorithm>");
+%fragment("<stdexcept>");
+
+// exported class
+
+namespace std {
+
+ template<class T> class list {
+ %typemap(in) list<T> (std::list<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $&1_descriptor,1) != -1) {
+ $1 = *v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ T* obj;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1) {
+ $1.push_back(*obj);
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(in) const list<T>& (std::list<T> temp,
+ std::list<T>* v),
+ const list<T>* (std::list<T> temp,
+ std::list<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,1) != -1) {
+ $1 = v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ T* obj;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1) {
+ temp.push_back(*obj);
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ $1 = &temp;
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(out) list<T> {
+ std::list< T >::const_iterator i;
+ unsigned int j;
+ int len = $1.size();
+ SV **svs = new SV*[len];
+ for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) {
+ T* ptr = new T(*i);
+ svs[j] = sv_newmortal();
+ SWIG_MakePtr(svs[j], (void*) ptr,
+ $descriptor(T *), $shadow|$owner);
+ }
+ AV *myav = av_make(len, svs);
+ delete[] svs;
+ $result = newRV_noinc((SV*) myav);
+ sv_2mortal($result);
+ argvi++;
+ }
+ %typecheck(SWIG_TYPECHECK_LIST) list<T> {
+ {
+ /* wrapped list? */
+ std::list< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_&descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ T* obj;
+ tv = av_fetch(av, 0, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1)
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ %typecheck(SWIG_TYPECHECK_LIST) const list<T>&,
+ const list<T>* {
+ {
+ /* wrapped list? */
+ std::list< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ T* obj;
+ tv = av_fetch(av, 0, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1)
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ list();
+ list(const list& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %rename(push) push_back;
+ void push_back(const T& x);
+ };
+
+
+ // specializations for built-ins
+
+ %define specialize_std_list(T,CHECK_T,TO_T,FROM_T)
+ template<> class list<T> {
+ %typemap(in) list<T> (std::list<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $&1_descriptor,1) != -1){
+ $1 = *v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (CHECK_T(*tv)) {
+ $1.push_back(TO_T(*tv));
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(in) const list<T>& (std::list<T> temp,
+ std::list<T>* v),
+ const list<T>* (std::list<T> temp,
+ std::list<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,1) != -1) {
+ $1 = v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ T* obj;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (CHECK_T(*tv)) {
+ temp.push_back(TO_T(*tv));
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ $1 = &temp;
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(out) list<T> {
+ std::list< T >::const_iterator i;
+ unsigned int j;
+ int len = $1.size();
+ SV **svs = new SV*[len];
+ for (i=$1.begin(), j=0; i!=$1.end(); i++, j++) {
+ svs[j] = sv_newmortal();
+ FROM_T(svs[j], *i);
+ }
+ AV *myav = av_make(len, svs);
+ delete[] svs;
+ $result = newRV_noinc((SV*) myav);
+ sv_2mortal($result);
+ argvi++;
+ }
+ %typecheck(SWIG_TYPECHECK_LIST) list<T> {
+ {
+ /* wrapped list? */
+ std::list< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_&descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ tv = av_fetch(av, 0, 0);
+ if (CHECK_T(*tv))
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ %typecheck(SWIG_TYPECHECK_LIST) const list<T>&,
+ const list<T>* {
+ {
+ /* wrapped list? */
+ std::list< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ tv = av_fetch(av, 0, 0);
+ if (CHECK_T(*tv))
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ public:
+ typedef size_t size_type;
+ typedef T value_type;
+ typedef const value_type& const_reference;
+
+ list();
+ list(const list& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %rename(push) push_back;
+ void push_back(T x);
+ };
+ %enddef
+
+ specialize_std_list(bool,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(char,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(int,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(short,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(long,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(unsigned char,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(unsigned int,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(unsigned short,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(unsigned long,SvIOK,SvIVX,sv_setiv);
+ specialize_std_list(float,SvNIOK,SwigSvToNumber,sv_setnv);
+ specialize_std_list(double,SvNIOK,SwigSvToNumber,sv_setnv);
+ specialize_std_list(std::string,SvPOK,SvPVX,SwigSvFromString);
+
+}
+
diff --git a/contrib/tools/swig/Lib/perl5/std_map.i b/contrib/tools/swig/Lib/perl5/std_map.i
new file mode 100644
index 00000000000..7d8103c0c47
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_map.i
@@ -0,0 +1,71 @@
+/* -----------------------------------------------------------------------------
+ * std_map.i
+ *
+ * SWIG typemaps for std::map
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::map
+// ------------------------------------------------------------------------
+
+%{
+#include <map>
+%}
+%fragment("<algorithm>");
+%fragment("<stdexcept>");
+
+// exported class
+
+namespace std {
+
+ template<class K, class T, class C = std::less<K> > class map {
+ // add typemaps here
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef K key_type;
+ typedef T mapped_type;
+ typedef std::pair< const K, T > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ map();
+ map(const map& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %extend {
+ const T& get(const K& key) throw (std::out_of_range) {
+ std::map< K, T, C >::iterator i = self->find(key);
+ if (i != self->end())
+ return i->second;
+ else
+ throw std::out_of_range("key not found");
+ }
+ void set(const K& key, const T& x) {
+%#ifdef __cpp_lib_map_try_emplace
+ (*self).insert_or_assign(key, x);
+%#else
+ (*self)[key] = x;
+%#endif
+ }
+ void del(const K& key) throw (std::out_of_range) {
+ std::map< K, T, C >::iterator i = self->find(key);
+ if (i != self->end())
+ self->erase(i);
+ else
+ throw std::out_of_range("key not found");
+ }
+ bool has_key(const K& key) {
+ std::map< K, T, C >::iterator i = self->find(key);
+ return i != self->end();
+ }
+ }
+ };
+
+}
diff --git a/contrib/tools/swig/Lib/perl5/std_pair.i b/contrib/tools/swig/Lib/perl5/std_pair.i
new file mode 100644
index 00000000000..732347db583
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_pair.i
@@ -0,0 +1,36 @@
+/* -----------------------------------------------------------------------------
+ * std_pair.i
+ *
+ * SWIG typemaps for std::pair
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <exception.i>
+
+// ------------------------------------------------------------------------
+// std::pair
+// ------------------------------------------------------------------------
+
+%{
+#include <utility>
+%}
+
+namespace std {
+
+ template<class T, class U> struct pair {
+ typedef T first_type;
+ typedef U second_type;
+
+ pair();
+ pair(T first, U second);
+ pair(const pair& other);
+
+ template <class U1, class U2> pair(const pair<U1, U2> &other);
+
+ T first;
+ U second;
+ };
+
+ // add specializations here
+
+}
diff --git a/contrib/tools/swig/Lib/perl5/std_string.i b/contrib/tools/swig/Lib/perl5/std_string.i
new file mode 100644
index 00000000000..6f34f18475f
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_string.i
@@ -0,0 +1,2 @@
+%include <perlstrings.swg>
+%include <typemaps/std_string.swg>
diff --git a/contrib/tools/swig/Lib/perl5/std_string_view.i b/contrib/tools/swig/Lib/perl5/std_string_view.i
new file mode 100644
index 00000000000..b1afffcc034
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_string_view.i
@@ -0,0 +1,2 @@
+%include <perlstrings.swg>
+%include <typemaps/std_string_view.swg>
diff --git a/contrib/tools/swig/Lib/perl5/std_unique_ptr.i b/contrib/tools/swig/Lib/perl5/std_unique_ptr.i
new file mode 100644
index 00000000000..e3669bb4a5a
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_unique_ptr.i
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ * std_unique_ptr.i
+ *
+ * SWIG library file for handling std::unique_ptr.
+ *
+ * Returning a std::unique_ptr from a wrapped function:
+ * Memory ownership is passed (moved) from the std::unique_ptr in the C++ layer
+ * to the proxy class when returning a std::unique_ptr by value from a function.
+ * Memory ownership is not moved when returning by any sort of reference.
+ *
+ * Passing a std::unique_ptr as a parameter to a wrapped function:
+ * Memory ownership is passed from the proxy class to the std::unique_ptr in the
+ * C++ layer when passed as a parameter by value, rvalue reference or non-const
+ * lvalue reference. Memory ownership is not transferred when passing by const
+ * lvalue reference.
+ * ----------------------------------------------------------------------------- */
+
+%include <unique_ptr.swg>
+
+%define %unique_ptr(TYPE)
+%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "TYPE *", $symname, $argnum);
+ } else {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ }
+ $1.reset((TYPE *)argp);
+}
+
+%typemap(in, noblock=1) std::unique_ptr< TYPE > & (void *argp = 0, int res = 0, std::unique_ptr< TYPE > uptr), std::unique_ptr< TYPE > && (void *argp = 0, int res = 0, std::unique_ptr< TYPE > uptr) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "TYPE *", $symname, $argnum);
+ } else {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ }
+ uptr.reset((TYPE *)argp);
+ $1 = &uptr;
+}
+
+%typemap(in, noblock=1, fragment="SwigNoDeleteUniquePtr") const std::unique_ptr< TYPE > & (void *argp = 0, int res = 0, swig::NoDeleteUniquePtr< TYPE > ndup) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), 0);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ ndup.uptr.reset((TYPE *)argp);
+ $1 = &ndup.uptr;
+}
+
+%typemap (out) std::unique_ptr< TYPE > %{
+ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
+%}
+%typemap (out) std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && %{
+ %set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
+%}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0);
+ $1 = SWIG_CheckState(res);
+}
+
+%template() std::unique_ptr< TYPE >;
+%enddef
diff --git a/contrib/tools/swig/Lib/perl5/std_vector.i b/contrib/tools/swig/Lib/perl5/std_vector.i
new file mode 100644
index 00000000000..06bc6f38347
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/std_vector.i
@@ -0,0 +1,592 @@
+/* -----------------------------------------------------------------------------
+ * std_vector.i
+ *
+ * SWIG typemaps for std::vector types
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+// ------------------------------------------------------------------------
+// std::vector
+//
+// The aim of all that follows would be to integrate std::vector with
+// Perl as much as possible, namely, to allow the user to pass and
+// be returned Perl arrays.
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::vector<T>), f(const std::vector<T>&), f(const std::vector<T>*):
+// the parameter being read-only, either a Perl sequence or a
+// previously wrapped std::vector<T> can be passed.
+// -- f(std::vector<T>&), f(std::vector<T>*):
+// the parameter must be modified; therefore, only a wrapped std::vector
+// can be passed.
+// -- std::vector<T> f():
+// the vector is returned by copy; therefore, a Perl sequence of T:s
+// is returned which is most easily used in other Perl functions
+// -- std::vector<T>& f(), std::vector<T>* f(), const std::vector<T>& f(),
+// const std::vector<T>* f():
+// the vector is returned by reference; therefore, a wrapped std::vector
+// is returned
+// ------------------------------------------------------------------------
+
+%{
+#include <vector>
+%}
+%fragment("<algorithm>");
+%fragment("<stdexcept>");
+
+// exported class
+
+namespace std {
+
+ template<class T> class vector {
+ %typemap(in) vector<T> (std::vector<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $&1_descriptor,1) != -1) {
+ $1 = *v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ T* obj;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1) {
+ $1.push_back(*obj);
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(in) const vector<T>& (std::vector<T> temp,
+ std::vector<T>* v),
+ const vector<T>* (std::vector<T> temp,
+ std::vector<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,1) != -1) {
+ $1 = v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ T* obj;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1) {
+ temp.push_back(*obj);
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ $1 = &temp;
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(out) vector<T> {
+ size_t len = $1.size();
+ SV **svs = new SV*[len];
+ for (size_t i=0; i<len; i++) {
+ T* ptr = new T($1[i]);
+ svs[i] = sv_newmortal();
+ SWIG_MakePtr(svs[i], (void*) ptr,
+ $descriptor(T *), $shadow|$owner);
+ }
+ AV *myav = av_make(len, svs);
+ delete[] svs;
+ $result = newRV_noinc((SV*) myav);
+ sv_2mortal($result);
+ argvi++;
+ }
+ %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
+ {
+ /* wrapped vector? */
+ std::vector< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $&1_descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ T* obj;
+ SV **tv = av_fetch(av, 0, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1)
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
+ const vector<T>* {
+ {
+ /* wrapped vector? */
+ std::vector< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ T* obj;
+ SV **tv = av_fetch(av, 0, 0);
+ if (SWIG_ConvertPtr(*tv, (void **)&obj,
+ $descriptor(T *),0) != -1)
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ vector(unsigned int size = 0);
+ vector(unsigned int size, const T& value);
+ vector(const vector& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %rename(push) push_back;
+ void push_back(const T& x);
+ %extend {
+ T pop() throw (std::out_of_range) {
+ if (self->size() == 0)
+ throw std::out_of_range("pop from empty vector");
+ T x = self->back();
+ self->pop_back();
+ return x;
+ }
+ T& get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ void set(int i, const T& x) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = x;
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+ };
+
+ // specializations for pointers
+ template<class T> class vector<T*> {
+ %typemap(in) vector<T*> (std::vector<T*>* v) {
+ int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0);
+ if (SWIG_IsOK(res)){
+ $1 = *v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SSize_t len = av_len(av) + 1;
+ for (int i=0; i<len; i++) {
+ void *v;
+ SV **tv = av_fetch(av, i, 0);
+ int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
+ if (SWIG_IsOK(res)) {
+ $1.push_back(%static_cast(v, T *));
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(in) const vector<T *>& (std::vector<T *> temp,std::vector<T *>* v),
+ const vector<T *>* (std::vector<T *> temp,std::vector<T *>* v) {
+ int res = SWIG_ConvertPtr($input,(void **) &v, $1_descriptor,0);
+ if (SWIG_IsOK(res)) {
+ $1 = v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SSize_t len = av_len(av) + 1;
+ for (int i=0; i<len; i++) {
+ void *v;
+ SV **tv = av_fetch(av, i, 0);
+ int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
+ if (SWIG_IsOK(res)) {
+ temp.push_back(%static_cast(v, T *));
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ $1 = &temp;
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(out) vector<T *> {
+ size_t len = $1.size();
+ SV **svs = new SV*[len];
+ for (size_t i=0; i<len; i++) {
+ T *x = (($1_type &)$1)[i];
+ svs[i] = sv_newmortal();
+ sv_setsv(svs[i], SWIG_NewPointerObj(x, $descriptor(T *), 0));
+ }
+ AV *myav = av_make(len, svs);
+ delete[] svs;
+ $result = newRV_noinc((SV*) myav);
+ sv_2mortal($result);
+ argvi++;
+ }
+ %typecheck(SWIG_TYPECHECK_VECTOR) vector<T *> {
+ {
+ /* wrapped vector? */
+ std::vector< T *>* v;
+ int res = SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,0);
+ if (SWIG_IsOK(res)) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ void *v;
+ SV **tv = av_fetch(av, 0, 0);
+ int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
+ if (SWIG_IsOK(res))
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T *>&,const vector<T *>* {
+ {
+ /* wrapped vector? */
+ std::vector< T *> *v;
+ int res = SWIG_ConvertPtr($input,%as_voidptrptr(&v), $1_descriptor,0);
+ if (SWIG_IsOK(res)) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ void *v;
+ SV **tv = av_fetch(av, 0, 0);
+ int res = SWIG_ConvertPtr(*tv, &v, $descriptor(T *),0);
+ if (SWIG_IsOK(res))
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ vector(unsigned int size = 0);
+ vector(unsigned int size, T *value);
+ vector(const vector& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %rename(push) push_back;
+ void push_back(T *x);
+ %extend {
+ T *pop() throw (std::out_of_range) {
+ if (self->size() == 0)
+ throw std::out_of_range("pop from empty vector");
+ T *x = self->back();
+ self->pop_back();
+ return x;
+ }
+ T *get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ void set(int i, T *x) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = x;
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+ };
+
+
+ // specializations for built-ins
+
+ %define specialize_std_vector(T,CHECK_T,TO_T,FROM_T)
+ template<> class vector<T> {
+ %typemap(in) vector<T> (std::vector<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $&1_descriptor,1) != -1){
+ $1 = *v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (CHECK_T(*tv)) {
+ $1.push_back((T)TO_T(*tv));
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(in) const vector<T>& (std::vector<T> temp,
+ std::vector<T>* v),
+ const vector<T>* (std::vector<T> temp,
+ std::vector<T>* v) {
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,1) != -1) {
+ $1 = v;
+ } else if (SvROK($input)) {
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) != SVt_PVAV)
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ SV **tv;
+ SSize_t len = av_len(av) + 1;
+ for (int i=0; i<len; i++) {
+ tv = av_fetch(av, i, 0);
+ if (CHECK_T(*tv)) {
+ temp.push_back((T)TO_T(*tv));
+ } else {
+ SWIG_croak("Type error in argument $argnum of "
+ "$symname. "
+ "Expected an array of " #T);
+ }
+ }
+ $1 = &temp;
+ } else {
+ SWIG_croak("Type error in argument $argnum of $symname. "
+ "Expected an array of " #T);
+ }
+ }
+ %typemap(out) vector<T> {
+ size_t len = $1.size();
+ SV **svs = new SV*[len];
+ for (size_t i=0; i<len; i++) {
+ svs[i] = sv_newmortal();
+ FROM_T(svs[i], $1[i]);
+ }
+ AV *myav = av_make(len, svs);
+ delete[] svs;
+ $result = newRV_noinc((SV*) myav);
+ sv_2mortal($result);
+ argvi++;
+ }
+ %typecheck(SWIG_TYPECHECK_VECTOR) vector<T> {
+ {
+ /* wrapped vector? */
+ std::vector< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $&1_descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ SV **tv = av_fetch(av, 0, 0);
+ if (CHECK_T(*tv))
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ %typecheck(SWIG_TYPECHECK_VECTOR) const vector<T>&,
+ const vector<T>* {
+ {
+ /* wrapped vector? */
+ std::vector< T >* v;
+ if (SWIG_ConvertPtr($input,(void **) &v,
+ $1_descriptor,0) != -1) {
+ $1 = 1;
+ } else if (SvROK($input)) {
+ /* native sequence? */
+ AV *av = (AV *)SvRV($input);
+ if (SvTYPE(av) == SVt_PVAV) {
+ SSize_t len = av_len(av) + 1;
+ if (len == 0) {
+ /* an empty sequence can be of any type */
+ $1 = 1;
+ } else {
+ /* check the first element only */
+ SV **tv = av_fetch(av, 0, 0);
+ if (CHECK_T(*tv))
+ $1 = 1;
+ else
+ $1 = 0;
+ }
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+ }
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ vector(unsigned int size = 0);
+ vector(unsigned int size, T value);
+ vector(const vector& other);
+
+ unsigned int size() const;
+ bool empty() const;
+ void clear();
+ %rename(push) push_back;
+ void push_back(T x);
+ %extend {
+ T pop() throw (std::out_of_range) {
+ if (self->size() == 0)
+ throw std::out_of_range("pop from empty vector");
+ T x = self->back();
+ self->pop_back();
+ return x;
+ }
+ T get(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ void set(int i, T x) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i>=0 && i<size)
+ (*self)[i] = x;
+ else
+ throw std::out_of_range("vector index out of range");
+ }
+ }
+ };
+ %enddef
+
+ specialize_std_vector(bool,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(char,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(int,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(short,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(long,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(unsigned char,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(unsigned int,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(unsigned short,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(unsigned long,SvIOK,SvIVX,sv_setiv);
+ specialize_std_vector(float,SvNIOK,SwigSvToNumber,sv_setnv);
+ specialize_std_vector(double,SvNIOK,SwigSvToNumber,sv_setnv);
+ specialize_std_vector(std::string,SvPOK,SwigSvToString,SwigSvFromString);
+}
+
diff --git a/contrib/tools/swig/Lib/perl5/stl.i b/contrib/tools/swig/Lib/perl5/stl.i
new file mode 100644
index 00000000000..04f86014f2c
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/stl.i
@@ -0,0 +1,10 @@
+/* -----------------------------------------------------------------------------
+ * stl.i
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <std_string.i>
+%include <std_vector.i>
+%include <std_map.i>
+%include <std_pair.i>
+
diff --git a/contrib/tools/swig/Lib/perl5/swigmove.i b/contrib/tools/swig/Lib/perl5/swigmove.i
new file mode 100644
index 00000000000..62ecca76823
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/swigmove.i
@@ -0,0 +1 @@
+%include <typemaps/swigmove.swg>
diff --git a/contrib/tools/swig/Lib/perl5/typemaps.i b/contrib/tools/swig/Lib/perl5/typemaps.i
new file mode 100644
index 00000000000..078f24ce891
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/typemaps.i
@@ -0,0 +1,371 @@
+/* -----------------------------------------------------------------------------
+ * typemaps.i
+ *
+ * The SWIG typemap library provides a language independent mechanism for
+ * supporting output arguments, input values, and other C function
+ * calling mechanisms. The primary use of the library is to provide a
+ * better interface to certain C function--especially those involving
+ * pointers.
+ * ----------------------------------------------------------------------------- */
+
+#if !defined(SWIG_USE_OLD_TYPEMAPS)
+%include <typemaps/typemaps.swg>
+#else
+
+
+// INPUT typemaps.
+// These remap a C pointer to be an "INPUT" value which is passed by value
+// instead of reference.
+
+
+/*
+The following methods can be applied to turn a pointer into a simple
+"input" value. That is, instead of passing a pointer to an object,
+you would use a real value instead.
+
+ int *INPUT
+ short *INPUT
+ long *INPUT
+ long long *INPUT
+ unsigned int *INPUT
+ unsigned short *INPUT
+ unsigned long *INPUT
+ unsigned long long *INPUT
+ unsigned char *INPUT
+ bool *INPUT
+ float *INPUT
+ double *INPUT
+
+To use these, suppose you had a C function like this :
+
+ double fadd(double *a, double *b) {
+ return *a+*b;
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include typemaps.i
+ double fadd(double *INPUT, double *INPUT);
+
+or you can use the %apply directive :
+
+ %include typemaps.i
+ %apply double *INPUT { double *a, double *b };
+ double fadd(double *a, double *b);
+
+*/
+
+%define INPUT_TYPEMAP(type, converter)
+%typemap(in) type *INPUT(type temp), type &INPUT(type temp) {
+ temp = (type) converter($input);
+ $1 = &temp;
+}
+%typemap(typecheck) type *INPUT = type;
+%typemap(typecheck) type &INPUT = type;
+%enddef
+
+INPUT_TYPEMAP(float, SvNV);
+INPUT_TYPEMAP(double, SvNV);
+INPUT_TYPEMAP(int, SvIV);
+INPUT_TYPEMAP(long, SvIV);
+INPUT_TYPEMAP(short, SvIV);
+INPUT_TYPEMAP(signed char, SvIV);
+INPUT_TYPEMAP(unsigned int, SvUV);
+INPUT_TYPEMAP(unsigned long, SvUV);
+INPUT_TYPEMAP(unsigned short, SvUV);
+INPUT_TYPEMAP(unsigned char, SvUV);
+
+%typemap(in) bool *INPUT(bool temp), bool &INPUT(bool temp) {
+ temp = SvIV($input) ? true : false;
+ $1 = &temp;
+}
+%typemap(typecheck) bool *INPUT = bool;
+%typemap(typecheck) bool &INPUT = bool;
+
+%typemap(in) long long *INPUT($*1_ltype temp), long long &INPUT($*1_ltype temp) {
+ temp = strtoll(SvPV_nolen($input), 0, 0);
+ $1 = &temp;
+}
+%typemap(typecheck) long long *INPUT = long long;
+%typemap(typecheck) long long &INPUT = long long;
+
+%typemap(in) unsigned long long *INPUT($*1_ltype temp), unsigned long long &INPUT($*1_ltype temp) {
+ temp = strtoull(SvPV_nolen($input), 0, 0);
+ $1 = &temp;
+}
+%typemap(typecheck) unsigned long long *INPUT = unsigned long long;
+%typemap(typecheck) unsigned long long &INPUT = unsigned long long;
+
+
+#undef INPUT_TYPEMAP
+
+// OUTPUT typemaps. These typemaps are used for parameters that
+// are output only. The output value is appended to the result as
+// a list element.
+
+/*
+The following methods can be applied to turn a pointer into an "output"
+value. When calling a function, no input value would be given for
+a parameter, but an output value would be returned. In the case of
+multiple output values, functions will return a Perl array.
+
+ int *OUTPUT
+ short *OUTPUT
+ long *OUTPUT
+ long long *OUTPUT
+ unsigned int *OUTPUT
+ unsigned short *OUTPUT
+ unsigned long *OUTPUT
+ unsigned long long *OUTPUT
+ unsigned char *OUTPUT
+ bool *OUTPUT
+ float *OUTPUT
+ double *OUTPUT
+
+For example, suppose you were trying to wrap the modf() function in the
+C math library which splits x into integral and fractional parts (and
+returns the integer part in one of its parameters).:
+
+ double modf(double x, double *ip);
+
+You could wrap it with SWIG as follows :
+
+ %include typemaps.i
+ double modf(double x, double *OUTPUT);
+
+or you can use the %apply directive :
+
+ %include typemaps.i
+ %apply double *OUTPUT { double *ip };
+ double modf(double x, double *ip);
+
+The Perl output of the function would be an array containing both
+output values.
+
+*/
+
+// Force the argument to be ignored.
+
+%typemap(in,numinputs=0) int *OUTPUT(int temp), int &OUTPUT(int temp),
+ short *OUTPUT(short temp), short &OUTPUT(short temp),
+ long *OUTPUT(long temp), long &OUTPUT(long temp),
+ unsigned int *OUTPUT(unsigned int temp), unsigned int &OUTPUT(unsigned int temp),
+ unsigned short *OUTPUT(unsigned short temp), unsigned short &OUTPUT(unsigned short temp),
+ unsigned long *OUTPUT(unsigned long temp), unsigned long &OUTPUT(unsigned long temp),
+ unsigned char *OUTPUT(unsigned char temp), unsigned char &OUTPUT(unsigned char temp),
+ signed char *OUTPUT(signed char temp), signed char &OUTPUT(signed char temp),
+ bool *OUTPUT(bool temp), bool &OUTPUT(bool temp),
+ float *OUTPUT(float temp), float &OUTPUT(float temp),
+ double *OUTPUT(double temp), double &OUTPUT(double temp),
+ long long *OUTPUT($*1_ltype temp), long long &OUTPUT($*1_ltype temp),
+ unsigned long long *OUTPUT($*1_ltype temp), unsigned long long &OUTPUT($*1_ltype temp)
+"$1 = &temp;";
+
+%typemap(argout) int *OUTPUT, int &OUTPUT,
+ short *OUTPUT, short &OUTPUT,
+ long *OUTPUT, long &OUTPUT,
+ signed char *OUTPUT, signed char &OUTPUT,
+ bool *OUTPUT, bool &OUTPUT
+{
+ if (argvi >= items) {
+ EXTEND(sp, argvi+1);
+ }
+ $result = sv_newmortal();
+ sv_setiv($result,(IV) *($1));
+ argvi++;
+}
+
+%typemap(argout) unsigned int *OUTPUT, unsigned int &OUTPUT,
+ unsigned short *OUTPUT, unsigned short &OUTPUT,
+ unsigned long *OUTPUT, unsigned long &OUTPUT,
+ unsigned char *OUTPUT, unsigned char &OUTPUT
+{
+ if (argvi >= items) {
+ EXTEND(sp, argvi+1);
+ }
+ $result = sv_newmortal();
+ sv_setuv($result,(UV) *($1));
+ argvi++;
+}
+
+
+
+%typemap(argout) float *OUTPUT, float &OUTPUT,
+ double *OUTPUT, double &OUTPUT
+{
+ if (argvi >= items) {
+ EXTEND(sp, argvi+1);
+ }
+ $result = sv_newmortal();
+ sv_setnv($result,(double) *($1));
+ argvi++;
+}
+
+%typemap(argout) long long *OUTPUT, long long &OUTPUT {
+ char temp[256];
+ if (argvi >= items) {
+ EXTEND(sp, argvi+1);
+ }
+ SWIG_snprintf(temp, sizeof(temp),"%lld", (long long)*($1));
+ $result = sv_newmortal();
+ sv_setpv($result,temp);
+ argvi++;
+}
+
+%typemap(argout) unsigned long long *OUTPUT, unsigned long long &OUTPUT {
+ char temp[256];
+ if (argvi >= items) {
+ EXTEND(sp, argvi+1);
+ }
+ SWIG_snprintf(temp, sizeof(temp),"%llu", (unsigned long long)*($1));
+ $result = sv_newmortal();
+ sv_setpv($result,temp);
+ argvi++;
+}
+
+// INOUT
+// Mappings for an argument that is both an input and output
+// parameter
+
+/*
+The following methods can be applied to make a function parameter both
+an input and output value. This combines the behavior of both the
+"INPUT" and "OUTPUT" methods described earlier. Output values are
+returned in the form of a Perl array.
+
+ int *INOUT
+ short *INOUT
+ long *INOUT
+ long long *INOUT
+ unsigned int *INOUT
+ unsigned short *INOUT
+ unsigned long *INOUT
+ unsigned long long *INOUT
+ unsigned char *INOUT
+ bool *INOUT
+ float *INOUT
+ double *INOUT
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include typemaps.i
+ void neg(double *INOUT);
+
+or you can use the %apply directive :
+
+ %include typemaps.i
+ %apply double *INOUT { double *x };
+ void neg(double *x);
+
+Unlike C, this mapping does not directly modify the input value.
+Rather, the modified input value shows up as the return value of the
+function. Thus, to apply this function to a Perl variable you might
+do this :
+
+ $x = neg($x);
+
+*/
+
+%typemap(in) int *INOUT = int *INPUT;
+%typemap(in) short *INOUT = short *INPUT;
+%typemap(in) long *INOUT = long *INPUT;
+%typemap(in) unsigned *INOUT = unsigned *INPUT;
+%typemap(in) unsigned short *INOUT = unsigned short *INPUT;
+%typemap(in) unsigned long *INOUT = unsigned long *INPUT;
+%typemap(in) unsigned char *INOUT = unsigned char *INPUT;
+%typemap(in) signed char *INOUT = signed char *INPUT;
+%typemap(in) bool *INOUT = bool *INPUT;
+%typemap(in) float *INOUT = float *INPUT;
+%typemap(in) double *INOUT = double *INPUT;
+%typemap(in) long long *INOUT = long long *INPUT;
+%typemap(in) unsigned long long *INOUT = unsigned long long *INPUT;
+
+%typemap(in) int &INOUT = int &INPUT;
+%typemap(in) short &INOUT = short &INPUT;
+%typemap(in) long &INOUT = long &INPUT;
+%typemap(in) unsigned &INOUT = unsigned &INPUT;
+%typemap(in) unsigned short &INOUT = unsigned short &INPUT;
+%typemap(in) unsigned long &INOUT = unsigned long &INPUT;
+%typemap(in) unsigned char &INOUT = unsigned char &INPUT;
+%typemap(in) signed char &INOUT = signed char &INPUT;
+%typemap(in) bool &INOUT = bool &INPUT;
+%typemap(in) float &INOUT = float &INPUT;
+%typemap(in) double &INOUT = double &INPUT;
+%typemap(in) long long &INOUT = long long &INPUT;
+%typemap(in) unsigned long long &INOUT = unsigned long long &INPUT;
+
+
+%typemap(argout) int *INOUT = int *OUTPUT;
+%typemap(argout) short *INOUT = short *OUTPUT;
+%typemap(argout) long *INOUT = long *OUTPUT;
+%typemap(argout) unsigned *INOUT = unsigned *OUTPUT;
+%typemap(argout) unsigned short *INOUT = unsigned short *OUTPUT;
+%typemap(argout) unsigned long *INOUT = unsigned long *OUTPUT;
+%typemap(argout) unsigned char *INOUT = unsigned char *OUTPUT;
+%typemap(argout) signed char *INOUT = signed char *OUTPUT;
+%typemap(argout) bool *INOUT = bool *OUTPUT;
+%typemap(argout) float *INOUT = float *OUTPUT;
+%typemap(argout) double *INOUT = double *OUTPUT;
+%typemap(argout) long long *INOUT = long long *OUTPUT;
+%typemap(argout) unsigned long long *INOUT = unsigned long long *OUTPUT;
+
+
+%typemap(argout) int &INOUT = int &OUTPUT;
+%typemap(argout) short &INOUT = short &OUTPUT;
+%typemap(argout) long &INOUT = long &OUTPUT;
+%typemap(argout) unsigned &INOUT = unsigned &OUTPUT;
+%typemap(argout) unsigned short &INOUT = unsigned short &OUTPUT;
+%typemap(argout) unsigned long &INOUT = unsigned long &OUTPUT;
+%typemap(argout) unsigned char &INOUT = unsigned char &OUTPUT;
+%typemap(argout) signed char &INOUT = signed char &OUTPUT;
+%typemap(argout) bool &INOUT = bool &OUTPUT;
+%typemap(argout) float &INOUT = float &OUTPUT;
+%typemap(argout) double &INOUT = double &OUTPUT;
+%typemap(argout) long long &INOUT = long long &OUTPUT;
+%typemap(argout) unsigned long long &INOUT = unsigned long long &OUTPUT;
+
+
+/* Overloading information */
+
+%typemap(typecheck) double *INOUT = double;
+%typemap(typecheck) bool *INOUT = bool;
+%typemap(typecheck) signed char *INOUT = signed char;
+%typemap(typecheck) unsigned char *INOUT = unsigned char;
+%typemap(typecheck) unsigned long *INOUT = unsigned long;
+%typemap(typecheck) unsigned short *INOUT = unsigned short;
+%typemap(typecheck) unsigned int *INOUT = unsigned int;
+%typemap(typecheck) long *INOUT = long;
+%typemap(typecheck) short *INOUT = short;
+%typemap(typecheck) int *INOUT = int;
+%typemap(typecheck) float *INOUT = float;
+%typemap(typecheck) long long *INOUT = long long;
+%typemap(typecheck) unsigned long long *INOUT = unsigned long long;
+
+%typemap(typecheck) double &INOUT = double;
+%typemap(typecheck) bool &INOUT = bool;
+%typemap(typecheck) signed char &INOUT = signed char;
+%typemap(typecheck) unsigned char &INOUT = unsigned char;
+%typemap(typecheck) unsigned long &INOUT = unsigned long;
+%typemap(typecheck) unsigned short &INOUT = unsigned short;
+%typemap(typecheck) unsigned int &INOUT = unsigned int;
+%typemap(typecheck) long &INOUT = long;
+%typemap(typecheck) short &INOUT = short;
+%typemap(typecheck) int &INOUT = int;
+%typemap(typecheck) float &INOUT = float;
+%typemap(typecheck) long long &INOUT = long long;
+%typemap(typecheck) unsigned long long &INOUT = unsigned long long;
+
+#endif
+
+// --------------------------------------------------------------------
+// Special types
+// --------------------------------------------------------------------
+
+
+%include <reference.i>
diff --git a/contrib/tools/swig/Lib/perl5/ya.make b/contrib/tools/swig/Lib/perl5/ya.make
new file mode 100644
index 00000000000..e81e36377f8
--- /dev/null
+++ b/contrib/tools/swig/Lib/perl5/ya.make
@@ -0,0 +1,24 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+LICENSE(LicenseRef-scancode-swig)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+SUBSCRIBER(g:cpp-contrib)
+
+VERSION(4.3.1)
+
+ORIGINAL_SOURCE(https://github.com/swig/swig/archive/v4.3.1.tar.gz)
+
+ADDINCL(
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib/perl5
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib
+)
+
+END()
diff --git a/contrib/tools/swig/Lib/python/.yandex_meta/licenses.list.txt b/contrib/tools/swig/Lib/python/.yandex_meta/licenses.list.txt
new file mode 100644
index 00000000000..8aad0f87d67
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/.yandex_meta/licenses.list.txt
@@ -0,0 +1,916 @@
+====================File: COPYRIGHT====================
+SWIG Copyright and Authors
+--------------------------
+
+Copyright (c) 1995-2023 The SWIG Developers
+Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
+Copyright (c) 1998-2005 University of Chicago.
+Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
+
+Portions also copyrighted by:
+ Network Applied Communication Laboratory, Inc
+ Information-technology Promotion Agency, Japan
+
+Active SWIG Developers:
+ William Fulton ([email protected]) (SWIG core, Java, C#, Windows, Cygwin)
+ Olly Betts ([email protected]) (PHP)
+ Joseph Wang ([email protected]) (R)
+ Momtchil Momtchev ([email protected]) (Javascript Node-API)
+ Simon Marchetto ([email protected]) (Scilab)
+ Zackery Spytz ([email protected]) (OCaml, SWIG core)
+
+Past SWIG developers and major contributors include:
+ Dave Beazley ([email protected]) (SWIG core, Python, Tcl, Perl)
+ Henning Thielemann ([email protected]) (Modula3)
+ Matthias Köppe ([email protected]) (Guile, MzScheme)
+ Luigi Ballabio ([email protected]) (STL wrapping)
+ Mikel Bancroft ([email protected]) (Allegro CL)
+ Surendra Singhi ([email protected]) (CLISP, CFFI)
+ Marcelo Matus ([email protected]) (SWIG core, Python, UTL[python,perl,tcl,ruby])
+ Art Yerkes ([email protected]) (OCaml)
+ Lyle Johnson ([email protected]) (Ruby)
+ Charlie Savage ([email protected]) (Ruby)
+ Thien-Thi Nguyen ([email protected]) (build/test/misc)
+ Richard Palmer ([email protected]) (PHP)
+ Sam Liddicott - Ananova Ltd ([email protected]) (PHP)
+ Tim Hockin - Sun Microsystems ([email protected]) (PHP)
+ Kevin Ruland (PHP)
+ Shibukawa Yoshiki (Japanese Translation)
+ Jason Stewart ([email protected]) (Perl5)
+ Loic Dachary (Perl5)
+ David Fletcher (Perl5)
+ Gary Holt (Perl5)
+ Masaki Fukushima (Ruby)
+ Scott Michel ([email protected]) (Java directors)
+ Tiger Feng ([email protected]) (SWIG core)
+ Mark Rose ([email protected]) (Directors)
+ Jonah Beckford ([email protected]) (CHICKEN)
+ Ahmon Dancy ([email protected]) (Allegro CL)
+ Dirk Gerrits (Allegro CL)
+ Neil Cawse (C#)
+ Harco de Hilster (Java)
+ Alexey Dyachenko ([email protected]) (Tcl)
+ Bob Techentin (Tcl)
+ Martin Froehlich <[email protected]> (Guile)
+ Marcio Luis Teixeira <[email protected]> (Guile)
+ Duncan Temple Lang (R)
+ Miklos Vajna <[email protected]> (PHP directors)
+ Mark Gossage ([email protected]) (Lua)
+ Raman Gopalan ([email protected]) (eLua)
+ Gonzalo Garramuno ([email protected]) (Ruby, Ruby's UTL)
+ John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
+ Baozeng Ding <[email protected]> (Scilab)
+ Ian Lance Taylor (Go)
+ Dmitry Kabak ([email protected]) (Doxygen)
+ Vadim Zeitlin (PCRE, Python, Doxygen)
+ Stefan Zager ([email protected]) (Python)
+ Vincent Couvert (Scilab)
+ Sylvestre Ledru (Scilab)
+ Wolfgang Frisch (Scilab)
+ Oliver Buchtala ([email protected]) (Javascript)
+ Neha Narang ([email protected]) (Javascript)
+ Xavier Delacour ([email protected]) (Octave)
+ David Nadlinger ([email protected]) (D)
+ Leif Middelschulte ([email protected]) (C)
+
+Past contributors include:
+ James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
+ Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
+ Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
+ Klaus Wiederänders, Richard Beare, Hans Oesterholt.
+ (See CHANGES and CHANGES.current and the bug tracker for a more complete list).
+
+Past students:
+ Songyan Feng (Chicago).
+ Xinghua Shi (Chicago).
+ Jing Cao (Chicago).
+ Aquinas Hobor (Chicago).
+
+Historically, the following people contributed to early versions of SWIG.
+Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
+at Los Alamos National Laboratory were the first users. Patrick
+Tullmann at the University of Utah suggested the idea of automatic
+documentation generation. John Schmidt and Kurtis Bleeker at the
+University of Utah tested out the early versions. Chris Johnson
+supported SWIG's developed at the University of Utah. John Buckman,
+Larry Virden, and Tom Schwaller provided valuable input on the first
+releases and improving the portability of SWIG. David Fletcher and
+Gary Holt have provided a great deal of input on improving SWIG's
+Perl5 implementation. Kevin Butler contributed the first Windows NT
+port.
+
+Early bug reports and patches:
+Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
+Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
+Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
+Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
+Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
+Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
+Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
+Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
+Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
+Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
+Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
+Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
+Zhong Ren.
+
+
+
+====================File: LICENSE-GPL====================
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+====================File: LICENSE-UNIVERSITIES====================
+SWIG is distributed under the following terms:
+
+I.
+
+Copyright (c) 1995-1998
+The University of Utah and the Regents of the University of California
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following two paragraphs
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+IN NO EVENT SHALL THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, THE
+UNIVERSITY OF UTAH OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
+PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
+EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, AND THE UNIVERSITY OF UTAH
+SPECIFICALLY DISCLAIM ANY WARRANTIES,INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
+THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+
+II.
+
+This software includes contributions that are Copyright (c) 1998-2005
+University of Chicago.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer. Redistributions
+in binary form must reproduce the above copyright notice, this list of
+conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution. Neither the name of
+the University of Chicago nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF CHICAGO AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+CHICAGO OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+III.
+
+This software includes contributions that are Copyright (c) 2005-2006
+Arizona Board of Regents (University of Arizona).
+All Rights Reserved
+
+Permission is hereby granted, without written agreement and without
+license or royalty fees, to use, copy, modify, and distribute this
+software and its documentation for any purpose, provided that
+(1) The above copyright notice and the following paragraph
+appear in all copies of the source code and (2) redistributions
+including binaries reproduces these notices in the supporting
+documentation. Substantial modifications to this software may be
+copyrighted by their authors and need not follow the licensing terms
+described here, provided that the new terms are clearly indicated in
+all files where they apply.
+
+THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF ARIZONA AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF
+ARIZONA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+====================LicenseRef-scancode-swig====================
+SWIG is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version. See the LICENSE-GPL file for
+the full terms of the GNU General Public license version 3.
+
+Portions of SWIG are also licensed under the terms of the licenses
+in the file LICENSE-UNIVERSITIES. You must observe the terms of
+these licenses, as well as the terms of the GNU General Public License,
+when you distribute SWIG.
+
+The SWIG library and examples, under the Lib and Examples top level
+directories, are distributed under the following terms:
+
+ You may copy, modify, distribute, and make derivative works based on
+ this software, in source code or object code form, without
+ restriction. If you distribute the software to others, you may do
+ so according to the terms of your choice. This software is offered as
+ is, without warranty of any kind.
+
+See the COPYRIGHT file for a list of contributors to SWIG and their
+copyright notices. \ No newline at end of file
diff --git a/contrib/tools/swig/Lib/python/README b/contrib/tools/swig/Lib/python/README
new file mode 100644
index 00000000000..70968e7dd58
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/README
@@ -0,0 +1,103 @@
+/* -----------------------------------------------------------------------------
+ *
+ * User interfaces: include these ones as needed
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * Special types and user helpers
+ * ----------------------------------------------------------------------------- */
+
+argcargv.i Handler for (int argc, char **argv)
+attribute.i Convert a pair of set/get methods into a "native" python attribute
+ccomplex.i C99 complex type
+complex.i C99 or C++ complex type
+cstring.i Various forms of C character string handling
+cwstring.i Various forms of C wchar_t string handling
+embed.i embedding the Python interpreter in something else
+file.i FILE C type
+implicit.i Allow the use of implicit C++ constructors
+wchar.i wchar_t C type
+
+/* -----------------------------------------------------------------------------
+ * C++ STD + STL
+ * ----------------------------------------------------------------------------- */
+
+std_alloc.i allocator
+std_basic_string.i basic string
+std_char_traits.i char traits
+std_complex.i complex
+std_deque.i deque
+std_except.i exceptions
+std_ios.i ios
+std_iostream.i istream/ostream
+std_list.i list
+std_map.i map
+std_multimap.i multimap
+std_multiset.i multiset
+std_pair.i pair
+std_set.i set
+std_sstream.i string stream
+std_streambuf.i streambuf
+std_string.i string
+std_vector.i vector
+std_wios.i wios
+std_wiostream.i wistream/wostream
+std_wsstream.i wstring stream
+std_wstreambuf.i wstreambuf
+std_wstring.i wstring
+
+
+
+/* -----------------------------------------------------------------------------
+/*
+ * Implementation files: don't look at them unless you are really drunk
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * Basic files
+ * ----------------------------------------------------------------------------- */
+
+python.swg Main language file, it just includes what is needed.
+pyuserdir.swg User visible directives (%pythonnondynamic, etc)
+pymacros.swg Internal macros used for typemaps
+pyfragments.swg Allow the user to overload the default fragments
+pyopers.swg Python operations (+=, *=, etc)
+pythonkw.swg Python keywords and special names
+pyinit.swg Python Init method
+
+/* -----------------------------------------------------------------------------
+ * The runtime part
+ * ----------------------------------------------------------------------------- */
+
+pyruntime.swg Main runtime file definition
+pyapi.swg SWIG/Python API declarations
+pyrun.swg Python run-time code
+
+/* -----------------------------------------------------------------------------
+ * Internal typemap specializations
+ * ----------------------------------------------------------------------------- */
+
+pyswigtype.swg SWIGTYPE
+pystrings.swg Char strings (char *)
+pywstrings.swg Wchar Strings (wchar_t *)
+pyprimtypes.swg Primitive types (shot,int,double,etc)
+pycomplex.swg PyComplex and helper for C/C++ complex types
+pydocs.swg Typemaps documentation
+
+/* -----------------------------------------------------------------------------
+ * C++ STD + STL
+ * ----------------------------------------------------------------------------- */
+
+pycontainer.swg python container iterators
+std_common.i general common code for the STD/STL implementation
+std_container.i general common code for the STD/STL containers
+
+
+/*-----------------------------------------------------------------------------
+ * Backward compatibility and deprecated
+ * ----------------------------------------------------------------------------- */
+
+std_vectora.i vector + allocator (allocators are now supported in STD/STL)
+typemaps.i old in/out typemaps (doesn't need to be included)
diff --git a/contrib/tools/swig/Lib/python/argcargv.i b/contrib/tools/swig/Lib/python/argcargv.i
new file mode 100644
index 00000000000..af71840f58c
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/argcargv.i
@@ -0,0 +1,89 @@
+/* -------------------------------------------------------------
+ * SWIG library containing argc and argv multi-argument typemaps
+ * ------------------------------------------------------------- */
+
+%fragment("SWIG_AsArgcArgv","header",fragment="SWIG_AsCharPtrAndSize") {
+SWIGINTERN int
+SWIG_AsArgcArgv(PyObject *input, swig_type_info *ppchar_info, size_t *argc, char ***argv, int *owner) {
+ void *vptr;
+ int res = SWIG_ConvertPtr(input, &vptr, ppchar_info, 0);
+ if (!SWIG_IsOK(res)) {
+ int list = 0;
+ PyErr_Clear();
+ list = PyList_Check(input);
+ if (list || PyTuple_Check(input)) {
+ size_t i = 0;
+ size_t size = list ? PyList_Size(input) : PyTuple_Size(input);
+ if (argc) *argc = size;
+ if (argv) {
+ *argv = %new_array(size + 1, char*);
+ for (; i < size; ++i) {
+ PyObject *obj = list ? PyList_GetItem(input,i) : PyTuple_GetItem(input,i);
+ char *cptr = 0; size_t sz = 0; int alloc = 0;
+ res = SWIG_AsCharPtrAndSize(obj, &cptr, &sz, &alloc);
+ if (SWIG_IsOK(res)) {
+ if (cptr && sz) {
+ (*argv)[i] = (alloc == SWIG_NEWOBJ) ? cptr : %new_copy_array(cptr, sz, char);
+ } else {
+ (*argv)[i] = 0;
+ }
+ } else {
+ return SWIG_TypeError;
+ }
+ }
+ (*argv)[i] = 0;
+ if (owner) *owner = 1;
+ } else {
+ for (; i < size; ++i) {
+ PyObject *obj = list ? PyList_GetItem(input,i) : PyTuple_GetItem(input,i);
+ res = SWIG_AsCharPtrAndSize(obj, 0, 0, 0);
+ if (!SWIG_IsOK(res)) return SWIG_TypeError;
+ }
+ if (owner) *owner = 0;
+ }
+ return SWIG_OK;
+ } else {
+ return SWIG_TypeError;
+ }
+ } else {
+ /* seems dangerous, but the user asked for it... */
+ size_t i = 0;
+ if (argv) { while (*argv[i] != 0) ++i;}
+ if (argc) *argc = i;
+ if (owner) *owner = 0;
+ return SWIG_OK;
+ }
+}
+}
+
+/*
+ This typemap works with either a char **, a python list or a python
+ tuple
+ */
+
+%typemap(in,noblock=0,fragment="SWIG_AsArgcArgv") (int ARGC, char **ARGV) (int res,char **argv = 0, size_t argc = 0, int owner= 0) {
+ res = SWIG_AsArgcArgv($input, $descriptor(char**), &argc, &argv, &owner);
+ if (!SWIG_IsOK(res)) {
+ $1 = 0; $2 = 0;
+ %argument_fail(SWIG_TypeError, "int ARGC, char **ARGV", $symname, $argnum);
+ } else {
+ $1 = %static_cast(argc,$1_ltype);
+ $2 = %static_cast(argv, $2_ltype);
+ }
+}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (int ARGC, char **ARGV) {
+ int res = SWIG_AsArgcArgv($input, $descriptor(char**), 0, 0, 0);
+ $1 = SWIG_IsOK(res);
+}
+
+%typemap(freearg,noblock=1) (int ARGC, char **ARGV) {
+ if (owner$argnum) {
+ size_t i = argc$argnum;
+ while (i) {
+ %delete_array(argv$argnum[--i]);
+ }
+ %delete_array(argv$argnum);
+ }
+}
+
diff --git a/contrib/tools/swig/Lib/python/attribute.i b/contrib/tools/swig/Lib/python/attribute.i
new file mode 100644
index 00000000000..779716cd2ea
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/attribute.i
@@ -0,0 +1 @@
+%include <typemaps/attribute.swg>
diff --git a/contrib/tools/swig/Lib/python/boost_shared_ptr.i b/contrib/tools/swig/Lib/python/boost_shared_ptr.i
new file mode 100644
index 00000000000..bfd8787c08a
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/boost_shared_ptr.i
@@ -0,0 +1,411 @@
+%include <shared_ptr.i>
+
+// Set SHARED_PTR_DISOWN to $disown if required, for example
+// #define SHARED_PTR_DISOWN $disown
+#if !defined(SHARED_PTR_DISOWN)
+#define SHARED_PTR_DISOWN 0
+#endif
+
+%fragment("SWIG_null_deleter_python", "header", fragment="SWIG_null_deleter") {
+%#define SWIG_NO_NULL_DELETER_SWIG_BUILTIN_INIT
+}
+
+// Language specific macro implementing all the customisations for handling the smart pointer
+%define SWIG_SHARED_PTR_TYPEMAPS(CONST, TYPE...)
+
+// %naturalvar is as documented for member variables
+%naturalvar TYPE;
+%naturalvar SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+
+// destructor wrapper customisation
+%feature("unref") TYPE
+//"if (debug_shared) { cout << \"deleting use_count: \" << (*smartarg1).use_count() << \" [\" << (boost::get_deleter<SWIG_null_deleter>(*smartarg1) ? std::string(\"CANNOT BE DETERMINED SAFELY\") : ( (*smartarg1).get() ? (*smartarg1)->getValue() : std::string(\"NULL PTR\") )) << \"]\" << endl << flush; }\n"
+ "(void)arg1; delete smartarg1;"
+
+// Typemap customisations...
+
+// plain value
+%typemap(in) CONST TYPE (void *argp, int res = 0) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (!argp) {
+ %argument_nullref("$type", $symname, $argnum);
+ } else {
+ $1 = *(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get());
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ }
+}
+%typemap(out) CONST TYPE {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1));
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(varin) CONST TYPE {
+ void *argp = 0;
+ int newmem = 0;
+ int res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ if (!argp) {
+ %variable_nullref("$type", "$name");
+ } else {
+ $1 = *(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get());
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ }
+}
+%typemap(varout) CONST TYPE {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1));
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(directorin,noblock=1) CONST TYPE (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(SWIG_STD_MOVE($1)));
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) CONST TYPE (void *swig_argp, int swig_res = 0) {
+ int newmem = 0;
+ swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res, "$type");
+ }
+ if (!swig_argp) {
+ %dirout_nullref("$type");
+ } else {
+ $result = *(%reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get());
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ }
+}
+
+// plain pointer
+// Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance
+%typemap(in) CONST TYPE * (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ $1 = %const_cast(tempshared.get(), $1_ltype);
+ } else {
+ smartarg = %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype);
+ }
+}
+
+%typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE * {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner) : 0;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), $owner | SWIG_POINTER_OWN));
+}
+
+%typemap(varin) CONST TYPE * {
+ void *argp = 0;
+ int newmem = 0;
+ int res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared;
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0;
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ $1 = %const_cast(tempshared.get(), $1_ltype);
+ } else {
+ smartarg = %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ $1 = %const_cast((smartarg ? smartarg->get() : 0), $1_ltype);
+ }
+}
+%typemap(varout, fragment="SWIG_null_deleter_python") CONST TYPE * {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0;
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(directorin,noblock=1, fragment="SWIG_null_deleter_python") CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0;
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) CONST TYPE * %{
+#error "directorout typemap for plain pointer not implemented"
+%}
+
+// plain reference
+%typemap(in) CONST TYPE & (void *argp = 0, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (!argp) { %argument_nullref("$type", $symname, $argnum); }
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ $1 = %const_cast(tempshared.get(), $1_ltype);
+ } else {
+ $1 = %const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype);
+ }
+}
+%typemap(out, fragment="SWIG_null_deleter_python") CONST TYPE & {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_$owner);
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(varin) CONST TYPE & {
+ void *argp = 0;
+ int newmem = 0;
+ int res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared;
+ if (!argp) {
+ %variable_nullref("$type", "$name");
+ }
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ $1 = *%const_cast(tempshared.get(), $1_ltype);
+ } else {
+ $1 = *%const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $1_ltype);
+ }
+}
+%typemap(varout, fragment="SWIG_null_deleter_python") CONST TYPE & {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0);
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(directorin,noblock=1, fragment="SWIG_null_deleter_python") CONST TYPE & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(&$1 SWIG_NO_NULL_DELETER_0);
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) CONST TYPE & %{
+#error "directorout typemap for plain reference not implemented"
+%}
+
+// plain pointer by reference
+// Note: $disown not implemented by default as it will lead to a memory leak of the shared_ptr instance
+%typemap(in) TYPE *CONST& (void *argp = 0, int res = 0, $*1_ltype temp = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SHARED_PTR_DISOWN | %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ tempshared = *%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ delete %reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *);
+ temp = %const_cast(tempshared.get(), $*1_ltype);
+ } else {
+ temp = %const_cast(%reinterpret_cast(argp, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *)->get(), $*1_ltype);
+ }
+ $1 = &temp;
+}
+%typemap(out, fragment="SWIG_null_deleter_python") TYPE *CONST& {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1 SWIG_NO_NULL_DELETER_$owner) : 0;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(varin) TYPE *CONST& %{
+#error "varin typemap not implemented"
+%}
+%typemap(varout) TYPE *CONST& %{
+#error "varout typemap not implemented"
+%}
+
+%typemap(directorin,noblock=1, fragment="SWIG_null_deleter_python") TYPE *CONST& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1 SWIG_NO_NULL_DELETER_0) : 0;
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) TYPE *CONST& %{
+#error "directorout typemap for plain pointer by reference not implemented"
+%}
+
+// shared_ptr by value
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *argp, int res = 0) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (argp) $1 = *(%reinterpret_cast(argp, $&ltype));
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $&ltype);
+}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(varin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > {
+ int newmem = 0;
+ void *argp = 0;
+ int res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ $1 = argp ? *(%reinterpret_cast(argp, $&ltype)) : SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE >();
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $&ltype);
+}
+%typemap(varout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0;
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0;
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (void *swig_argp, int swig_res = 0) {
+ int newmem = 0;
+ swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res, "$type");
+ }
+ if (swig_argp) {
+ $result = *(%reinterpret_cast(swig_argp, $&ltype));
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(swig_argp, $&ltype);
+ }
+}
+
+// shared_ptr by reference
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (void *argp, int res = 0, $*1_ltype tempshared) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ if (argp) tempshared = *%reinterpret_cast(argp, $ltype);
+ delete %reinterpret_cast(argp, $ltype);
+ $1 = &tempshared;
+ } else {
+ $1 = (argp) ? %reinterpret_cast(argp, $ltype) : &tempshared;
+ }
+}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = *$1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(varin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{
+#error "varin typemap not implemented"
+%}
+%typemap(varout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{
+#error "varout typemap not implemented"
+%}
+
+%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = $1 ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >($1) : 0;
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > & %{
+#error "directorout typemap for shared_ptr ref not implemented"
+%}
+
+// shared_ptr by pointer
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (void *argp, int res = 0, $*1_ltype tempshared) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ if (argp) tempshared = *%reinterpret_cast(argp, $ltype);
+ delete %reinterpret_cast(argp, $ltype);
+ $1 = &tempshared;
+ } else {
+ $1 = (argp) ? %reinterpret_cast(argp, $ltype) : &tempshared;
+ }
+}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+ if ($owner) delete $1;
+}
+
+%typemap(varin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{
+#error "varin typemap not implemented"
+%}
+%typemap(varout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{
+#error "varout typemap not implemented"
+%}
+
+%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0;
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * %{
+#error "directorout typemap for pointer to shared_ptr not implemented"
+%}
+
+// shared_ptr by pointer reference
+%typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (void *argp, int res = 0, SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > tempshared, $*1_ltype temp = 0) {
+ int newmem = 0;
+ res = SWIG_ConvertPtrAndOwn($input, &argp, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), %convertptr_flags, &newmem);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (argp) tempshared = *%reinterpret_cast(argp, $*ltype);
+ if (newmem & SWIG_CAST_NEW_MEMORY) delete %reinterpret_cast(argp, $*ltype);
+ temp = &tempshared;
+ $1 = &temp;
+}
+%typemap(out) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& {
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartresult = (*$1 && **$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(**$1) : 0;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(smartresult), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN));
+}
+
+%typemap(varin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{
+#error "varin typemap not implemented"
+%}
+%typemap(varout) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{
+#error "varout typemap not implemented"
+%}
+
+%typemap(directorin,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{
+ smartarg = ($1 && *$1) ? new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(*$1) : 0;
+ $input = SWIG_NewPointerObj(%as_voidptr(smartarg), $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), SWIG_POINTER_OWN | %newpointer_flags);
+%}
+%typemap(directorout,noblock=1) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& %{
+#error "directorout typemap for pointer ref to shared_ptr not implemented"
+%}
+
+// Typecheck typemaps
+// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting
+// function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain.
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1)
+ TYPE CONST,
+ TYPE CONST &,
+ TYPE CONST *,
+ TYPE *CONST&,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *& {
+ int res = SWIG_ConvertPtr($input, 0, $descriptor(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > *), 0);
+ $1 = SWIG_CheckState(res);
+}
+
+
+// various missing typemaps - If ever used (unlikely) ensure compilation error rather than runtime bug
+%typemap(in) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+%typemap(out) CONST TYPE[], CONST TYPE[ANY], CONST TYPE (CLASS::*) %{
+#error "typemaps for $1_type not available"
+%}
+
+%typemap(doctype) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
+ SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
+ %{TYPE%}
+
+
+%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
+
+
+%enddef
diff --git a/contrib/tools/swig/Lib/python/builtin.swg b/contrib/tools/swig/Lib/python/builtin.swg
new file mode 100644
index 00000000000..e2e7f120f29
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/builtin.swg
@@ -0,0 +1,778 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SWIGINTERN Py_hash_t
+SwigPyObject_hash(PyObject *obj) {
+ SwigPyObject *sobj = (SwigPyObject *)obj;
+ void *ptr = sobj->ptr;
+#if PY_VERSION_HEX < 0x03020000
+ return (Py_hash_t)(Py_ssize_t)ptr;
+#else
+ return (Py_hash_t)ptr;
+#endif
+}
+
+SWIGINTERN Py_hash_t
+SWIG_PyNumber_AsPyHash(PyObject *obj) {
+ Py_hash_t result = -1;
+#if PY_VERSION_HEX < 0x03020000
+ if (PyInt_Check(obj))
+ result = PyInt_AsLong(obj);
+ else if (PyLong_Check(obj))
+ result = PyLong_AsLong(obj);
+#else
+ if (PyNumber_Check(obj))
+ result = PyNumber_AsSsize_t(obj, NULL);
+#endif
+ else
+ PyErr_Format(PyExc_TypeError, "Wrong type for hash function");
+ return PyErr_Occurred() ? -1 : result;
+}
+
+SWIGINTERN int
+SwigPyBuiltin_BadInit(PyObject *self, PyObject *SWIGUNUSEDPARM(args), PyObject *SWIGUNUSEDPARM(kwds)) {
+ PyErr_Format(PyExc_TypeError, "Cannot create new instances of type '%.300s'", self->ob_type->tp_name);
+ return -1;
+}
+
+SWIGINTERN void
+SwigPyBuiltin_BadDealloc(PyObject *obj) {
+ SwigPyObject *sobj = (SwigPyObject *)obj;
+ if (sobj->own) {
+ PyErr_Format(PyExc_TypeError, "Swig detected a memory leak in type '%.300s': no callable destructor found.", obj->ob_type->tp_name);
+ }
+}
+
+typedef struct {
+ PyCFunction get;
+ PyCFunction set;
+} SwigPyGetSet;
+
+SWIGINTERN PyObject *
+SwigPyBuiltin_GetterClosure (PyObject *obj, void *closure) {
+ SwigPyGetSet *getset;
+ PyObject *tuple, *result;
+ if (!closure)
+ return SWIG_Py_Void();
+ getset = (SwigPyGetSet *)closure;
+ if (!getset->get)
+ return SWIG_Py_Void();
+ tuple = PyTuple_New(0);
+ assert(tuple);
+ result = (*getset->get)(obj, tuple);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+SWIGINTERN PyObject *
+SwigPyBuiltin_FunpackGetterClosure (PyObject *obj, void *closure) {
+ SwigPyGetSet *getset;
+ PyObject *result;
+ if (!closure)
+ return SWIG_Py_Void();
+ getset = (SwigPyGetSet *)closure;
+ if (!getset->get)
+ return SWIG_Py_Void();
+ result = (*getset->get)(obj, NULL);
+ return result;
+}
+
+SWIGINTERN int
+SwigPyBuiltin_SetterClosure (PyObject *obj, PyObject *val, void *closure) {
+ SwigPyGetSet *getset;
+ PyObject *tuple, *result;
+ if (!closure) {
+ PyErr_Format(PyExc_TypeError, "Missing getset closure");
+ return -1;
+ }
+ getset = (SwigPyGetSet *)closure;
+ if (!getset->set) {
+ PyErr_Format(PyExc_TypeError, "Illegal member variable assignment in type '%.300s'", obj->ob_type->tp_name);
+ return -1;
+ }
+ tuple = PyTuple_New(1);
+ assert(tuple);
+ SWIG_Py_INCREF(val);
+ PyTuple_SET_ITEM(tuple, 0, val);
+ result = (*getset->set)(obj, tuple);
+ SWIG_Py_DECREF(tuple);
+ SWIG_Py_XDECREF(result);
+ return result ? 0 : -1;
+}
+
+SWIGINTERN int
+SwigPyBuiltin_FunpackSetterClosure (PyObject *obj, PyObject *val, void *closure) {
+ SwigPyGetSet *getset;
+ PyObject *result;
+ if (!closure) {
+ PyErr_Format(PyExc_TypeError, "Missing getset closure");
+ return -1;
+ }
+ getset = (SwigPyGetSet *)closure;
+ if (!getset->set) {
+ PyErr_Format(PyExc_TypeError, "Illegal member variable assignment in type '%.300s'", obj->ob_type->tp_name);
+ return -1;
+ }
+ result = (*getset->set)(obj, val);
+ SWIG_Py_XDECREF(result);
+ return result ? 0 : -1;
+}
+
+SWIGINTERN void
+SwigPyStaticVar_dealloc(PyDescrObject *descr) {
+ PyObject_GC_UnTrack(descr);
+ SWIG_Py_XDECREF((PyObject *)PyDescr_TYPE(descr));
+ SWIG_Py_XDECREF((PyObject *)PyDescr_NAME(descr));
+ PyObject_GC_Del(descr);
+}
+
+SWIGINTERN PyObject *
+SwigPyStaticVar_repr(PyGetSetDescrObject *descr) {
+#if PY_VERSION_HEX >= 0x03000000
+
+ return PyUnicode_FromFormat("<class attribute '%S' of type '%s'>", PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name);
+#else
+ return PyString_FromFormat("<class attribute '%s' of type '%s'>", PyString_AsString(PyDescr_NAME(descr)), PyDescr_TYPE(descr)->tp_name);
+#endif
+}
+
+SWIGINTERN int
+SwigPyStaticVar_traverse(PyObject *self, visitproc visit, void *arg) {
+ PyDescrObject *descr;
+ descr = (PyDescrObject *)self;
+ Py_VISIT((PyObject*) PyDescr_TYPE(descr));
+ return 0;
+}
+
+SWIGINTERN PyObject *
+SwigPyStaticVar_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *SWIGUNUSEDPARM(type)) {
+ if (descr->d_getset->get != NULL)
+ return descr->d_getset->get(obj, descr->d_getset->closure);
+#if PY_VERSION_HEX >= 0x03000000
+ PyErr_Format(PyExc_AttributeError, "attribute '%.300S' of '%.100s' objects is not readable", PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name);
+#else
+ PyErr_Format(PyExc_AttributeError, "attribute '%.300s' of '%.100s' objects is not readable", PyString_AsString(PyDescr_NAME(descr)), PyDescr_TYPE(descr)->tp_name);
+#endif
+ return NULL;
+}
+
+SWIGINTERN int
+SwigPyStaticVar_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) {
+ if (descr->d_getset->set != NULL)
+ return descr->d_getset->set(obj, value, descr->d_getset->closure);
+#if PY_VERSION_HEX >= 0x03000000
+ PyErr_Format(PyExc_AttributeError, "attribute '%.300S' of '%.100s' objects is not writable", PyDescr_NAME(descr), PyDescr_TYPE(descr)->tp_name);
+#else
+ PyErr_Format(PyExc_AttributeError, "attribute '%.300s' of '%.100s' objects is not writable", PyString_AsString(PyDescr_NAME(descr)), PyDescr_TYPE(descr)->tp_name);
+#endif
+ return -1;
+}
+
+SWIGINTERN int
+SwigPyObjectType_setattro(PyObject *typeobject, PyObject *name, PyObject *value) {
+ PyObject *attribute;
+ PyTypeObject *type;
+ descrsetfunc local_set;
+
+ assert(PyType_Check(typeobject));
+ type = (PyTypeObject *)typeobject;
+ attribute = _PyType_Lookup(type, name);
+ if (attribute != NULL) {
+ /* Implement descriptor functionality, if any */
+ local_set = attribute->ob_type->tp_descr_set;
+ if (local_set != NULL)
+ return local_set(attribute, (PyObject *)type, value);
+#if PY_VERSION_HEX >= 0x03000000
+ PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%.50s.%.400S'", type->tp_name, name);
+#else
+ PyErr_Format(PyExc_AttributeError, "cannot modify read-only attribute '%.50s.%.400s'", type->tp_name, PyString_AS_STRING(name));
+#endif
+ } else {
+#if PY_VERSION_HEX >= 0x03000000
+ PyErr_Format(PyExc_AttributeError, "type '%.50s' has no attribute '%.400S'", type->tp_name, name);
+#else
+ PyErr_Format(PyExc_AttributeError, "type '%.50s' has no attribute '%.400s'", type->tp_name, PyString_AS_STRING(name));
+#endif
+ }
+
+ return -1;
+}
+
+SWIGINTERN PyTypeObject*
+SwigPyStaticVar_Type(void) {
+ static PyTypeObject staticvar_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp = {
+#if PY_VERSION_HEX >= 0x03000000
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /* ob_size */
+#endif
+ "swig_static_var_getset_descriptor", /* tp_name */
+ sizeof(PyGetSetDescrObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SwigPyStaticVar_dealloc, /* tp_dealloc */
+#if PY_VERSION_HEX < 0x030800b4
+ (printfunc)0, /* tp_print */
+#else
+ (Py_ssize_t)0, /* tp_vectorcall_offset */
+#endif
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)SwigPyStaticVar_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_HAVE_CLASS, /* tp_flags */
+ 0, /* tp_doc */
+ SwigPyStaticVar_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ (descrgetfunc)SwigPyStaticVar_get, /* tp_descr_get */
+ (descrsetfunc)SwigPyStaticVar_set, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+#if PY_VERSION_HEX >= 0x03040000
+ 0, /* tp_finalize */
+#endif
+#if PY_VERSION_HEX >= 0x03080000
+ 0, /* tp_vectorcall */
+#endif
+#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)
+ 0, /* tp_print */
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ 0, /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d00a4
+ 0, /* tp_versions_used */
+#endif
+#ifdef COUNT_ALLOCS
+ 0, /* tp_allocs */
+ 0, /* tp_frees */
+ 0, /* tp_maxalloc */
+ 0, /* tp_prev */
+ 0 /* tp_next */
+#endif
+ };
+ staticvar_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&staticvar_type) < 0)
+ return NULL;
+ }
+ return &staticvar_type;
+}
+
+SWIGINTERN PyTypeObject*
+SwigPyObjectType(void) {
+ static char swigpyobjecttype_doc[] = "Metaclass for SWIG wrapped types";
+ static PyTypeObject swigpyobjecttype_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp = {
+#if PY_VERSION_HEX >= 0x03000000
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /* ob_size */
+#endif
+ "SwigPyObjectType", /* tp_name */
+ PyType_Type.tp_basicsize, /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+#if PY_VERSION_HEX < 0x030800b4
+ (printfunc)0, /* tp_print */
+#else
+ (Py_ssize_t)0, /* tp_vectorcall_offset */
+#endif
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ SwigPyObjectType_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_CLASS, /* tp_flags */
+ swigpyobjecttype_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+#if PY_VERSION_HEX >= 0x03040000
+ 0, /* tp_finalize */
+#endif
+#if PY_VERSION_HEX >= 0x03080000
+ 0, /* tp_vectorcall */
+#endif
+#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)
+ 0, /* tp_print */
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ 0, /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d00a4
+ 0, /* tp_versions_used */
+#endif
+#ifdef COUNT_ALLOCS
+ 0, /* tp_allocs */
+ 0, /* tp_frees */
+ 0, /* tp_maxalloc */
+ 0, /* tp_prev */
+ 0 /* tp_next */
+#endif
+ };
+ swigpyobjecttype_type = tmp;
+ type_init = 1;
+ swigpyobjecttype_type.tp_base = &PyType_Type;
+ if (PyType_Ready(&swigpyobjecttype_type) < 0)
+ return NULL;
+ }
+ return &swigpyobjecttype_type;
+}
+
+SWIGINTERN PyGetSetDescrObject *
+SwigPyStaticVar_new_getset(PyTypeObject *type, PyGetSetDef *getset) {
+
+ PyGetSetDescrObject *descr;
+ descr = (PyGetSetDescrObject *)PyType_GenericAlloc(SwigPyStaticVar_Type(), 0);
+ assert(descr);
+ SWIG_Py_XINCREF((PyObject *)type);
+ PyDescr_TYPE(descr) = type;
+ PyDescr_NAME(descr) = PyString_InternFromString(getset->name);
+ descr->d_getset = getset;
+ if (PyDescr_NAME(descr) == NULL) {
+ SWIG_Py_DECREF((PyObject *)descr);
+ descr = NULL;
+ }
+ return descr;
+}
+
+SWIGINTERN PyObject *
+SwigPyBuiltin_InitBases(PyTypeObject **bases) {
+ Py_ssize_t base_count = 0;
+ PyTypeObject **b;
+ PyObject *tuple;
+ Py_ssize_t i;
+
+ if (!bases[0]) {
+ bases[0] = SwigPyObject_type();
+ bases[1] = NULL;
+ }
+ for (b = bases; *b != NULL; ++b)
+ ++base_count;
+ tuple = PyTuple_New(base_count);
+ for (i = 0; i < base_count; ++i) {
+ SWIG_Py_INCREF((PyObject *)bases[i]);
+ PyTuple_SET_ITEM(tuple, i, (PyObject *)bases[i]);
+ }
+ return tuple;
+}
+
+SWIGINTERN PyObject *
+SwigPyBuiltin_ThisClosure (PyObject *self, void *SWIGUNUSEDPARM(closure)) {
+ PyObject *result;
+ result = (PyObject *)SWIG_Python_GetSwigThis(self);
+ SWIG_Py_XINCREF(result);
+ return result;
+}
+
+SWIGINTERN void
+SwigPyBuiltin_SetMetaType (PyTypeObject *type, PyTypeObject *metatype)
+{
+#if PY_VERSION_HEX >= 0x030900a4
+ Py_SET_TYPE(type, metatype);
+#else
+ Py_TYPE(type) = metatype;
+#endif
+}
+
+
+/* Start of callback function macros for use in PyTypeObject */
+
+typedef PyObject *(*SwigPyWrapperFunction)(PyObject *, PyObject *);
+
+#define SWIGPY_UNARYFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_unaryfunc_closure(PyObject *a) { \
+ return SwigPyBuiltin_unaryfunc_closure(wrapper, a); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_unaryfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ return wrapper(a, NULL);
+}
+
+#define SWIGPY_DESTRUCTOR_CLOSURE(wrapper) \
+SWIGINTERN void \
+wrapper##_destructor_closure(PyObject *a) { \
+ SwigPyBuiltin_destructor_closure(wrapper, #wrapper, a); \
+}
+SWIGINTERN void
+SwigPyBuiltin_destructor_closure(SwigPyWrapperFunction wrapper, const char *wrappername, PyObject *a) {
+ SwigPyObject *sobj;
+ sobj = (SwigPyObject *)a;
+ SWIG_Py_XDECREF(sobj->dict);
+ if (sobj->own) {
+ PyObject *o;
+ PyObject *type = 0, *value = 0, *traceback = 0;
+ PyErr_Fetch(&type, &value, &traceback);
+ o = wrapper(a, NULL);
+ if (!o) {
+ PyObject *deallocname = PyString_FromString(wrappername);
+ PyErr_WriteUnraisable(deallocname);
+ SWIG_Py_DECREF(deallocname);
+ }
+ PyErr_Restore(type, value, traceback);
+ SWIG_Py_XDECREF(o);
+ }
+ if (PyType_IS_GC(a->ob_type)) {
+ PyObject_GC_Del(a);
+ } else {
+ PyObject_Free(a);
+ }
+}
+
+#define SWIGPY_INQUIRY_CLOSURE(wrapper) \
+SWIGINTERN int \
+wrapper##_inquiry_closure(PyObject *a) { \
+ return SwigPyBuiltin_inquiry_closure(wrapper, a); \
+}
+SWIGINTERN int
+SwigPyBuiltin_inquiry_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ PyObject *pyresult;
+ int result;
+ pyresult = wrapper(a, NULL);
+ result = pyresult && PyObject_IsTrue(pyresult) ? 1 : 0;
+ SWIG_Py_XDECREF(pyresult);
+ return result;
+}
+
+#define SWIGPY_GETITERFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_getiterfunc_closure(PyObject *a) { \
+ return SwigPyBuiltin_getiterfunc_closure(wrapper, a); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_getiterfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ return wrapper(a, NULL);
+}
+
+#define SWIGPY_BINARYFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_binaryfunc_closure(PyObject *a, PyObject *b) { \
+ return SwigPyBuiltin_binaryfunc_closure(wrapper, a, b); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_binaryfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b) {
+ PyObject *tuple, *result;
+ tuple = PyTuple_New(1);
+ assert(tuple);
+ SWIG_Py_INCREF(b);
+ PyTuple_SET_ITEM(tuple, 0, b);
+ result = wrapper(a, tuple);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+typedef ternaryfunc ternarycallfunc;
+
+#define SWIGPY_TERNARYFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_ternaryfunc_closure(PyObject *a, PyObject *b, PyObject *c) { \
+ return SwigPyBuiltin_ternaryfunc_closure(wrapper, a, b, c); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_ternaryfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b, PyObject *c) {
+ PyObject *tuple, *result;
+ tuple = PyTuple_New(2);
+ assert(tuple);
+ SWIG_Py_INCREF(b);
+ PyTuple_SET_ITEM(tuple, 0, b);
+ if (c) {
+ SWIG_Py_INCREF(c);
+ PyTuple_SET_ITEM(tuple, 1, c);
+ }
+ result = wrapper(a, tuple);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+#define SWIGPY_TERNARYCALLFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_ternarycallfunc_closure(PyObject *a, PyObject *b, PyObject *c) { \
+ return SwigPyBuiltin_ternarycallfunc_closure(wrapper, a, b, c); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_ternarycallfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b, PyObject *c) {
+ (void) c;
+ return wrapper(a, b);
+}
+
+#define SWIGPY_LENFUNC_CLOSURE(wrapper) \
+SWIGINTERN Py_ssize_t \
+wrapper##_lenfunc_closure(PyObject *a) { \
+ return SwigPyBuiltin_lenfunc_closure(wrapper, a); \
+}
+SWIGINTERN Py_ssize_t
+SwigPyBuiltin_lenfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ PyObject *resultobj;
+ Py_ssize_t result;
+ resultobj = wrapper(a, NULL);
+ result = PyNumber_AsSsize_t(resultobj, NULL);
+ SWIG_Py_DECREF(resultobj);
+ return result;
+}
+
+#define SWIGPY_SSIZESSIZEARGFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_ssizessizeargfunc_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c) { \
+ return SwigPyBuiltin_ssizessizeargfunc_closure(wrapper, a, b, c); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_ssizessizeargfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b, Py_ssize_t c) {
+ PyObject *tuple, *result;
+ tuple = PyTuple_New(2);
+ assert(tuple);
+ PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b));
+ PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c));
+ result = wrapper(a, tuple);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+#define SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE(wrapper) \
+SWIGINTERN int \
+wrapper##_ssizessizeobjargproc_closure(PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) { \
+ return SwigPyBuiltin_ssizessizeobjargproc_closure(wrapper, a, b, c, d); \
+}
+SWIGINTERN int
+SwigPyBuiltin_ssizessizeobjargproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) {
+ PyObject *tuple, *resultobj;
+ int result;
+ tuple = PyTuple_New(d ? 3 : 2);
+ assert(tuple);
+ PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b));
+ PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c));
+ if (d) {
+ SWIG_Py_INCREF(d);
+ PyTuple_SET_ITEM(tuple, 2, d);
+ }
+ resultobj = wrapper(a, tuple);
+ result = resultobj ? 0 : -1;
+ SWIG_Py_DECREF(tuple);
+ SWIG_Py_XDECREF(resultobj);
+ return result;
+}
+
+#define SWIGPY_SSIZEARGFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_ssizeargfunc_closure(PyObject *a, Py_ssize_t b) { \
+ return SwigPyBuiltin_funpack_ssizeargfunc_closure(wrapper, a, b); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_funpack_ssizeargfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b) {
+ PyObject *tuple, *result;
+ tuple = PyTuple_New(1);
+ assert(tuple);
+ PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b));
+ result = wrapper(a, tuple);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+#define SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_ssizeargfunc_closure(PyObject *a, Py_ssize_t b) { \
+ return SwigPyBuiltin_ssizeargfunc_closure(wrapper, a, b); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_ssizeargfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b) {
+ PyObject *arg, *result;
+ arg = _PyLong_FromSsize_t(b);
+ result = wrapper(a, arg);
+ SWIG_Py_DECREF(arg);
+ return result;
+}
+
+#define SWIGPY_SSIZEOBJARGPROC_CLOSURE(wrapper) \
+SWIGINTERN int \
+wrapper##_ssizeobjargproc_closure(PyObject *a, Py_ssize_t b, PyObject *c) { \
+ return SwigPyBuiltin_ssizeobjargproc_closure(wrapper, a, b, c); \
+}
+SWIGINTERN int
+SwigPyBuiltin_ssizeobjargproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, Py_ssize_t b, PyObject *c) {
+ PyObject *tuple, *resultobj;
+ int result;
+ tuple = PyTuple_New(2);
+ assert(tuple);
+ PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b));
+ if (c) {
+ SWIG_Py_INCREF(c);
+ PyTuple_SET_ITEM(tuple, 1, c);
+ }
+ resultobj = wrapper(a, tuple);
+ result = resultobj ? 0 : -1;
+ SWIG_Py_XDECREF(resultobj);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+#define SWIGPY_OBJOBJPROC_CLOSURE(wrapper) \
+SWIGINTERN int \
+wrapper##_objobjproc_closure(PyObject *a, PyObject *b) { \
+ return SwigPyBuiltin_objobjproc_closure(wrapper, a, b); \
+}
+SWIGINTERN int
+SwigPyBuiltin_objobjproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b) {
+ int result;
+ PyObject *pyresult;
+ PyObject *tuple;
+ tuple = PyTuple_New(1);
+ assert(tuple);
+ SWIG_Py_INCREF(b);
+ PyTuple_SET_ITEM(tuple, 0, b);
+ pyresult = wrapper(a, tuple);
+ result = pyresult ? (PyObject_IsTrue(pyresult) ? 1 : 0) : -1;
+ SWIG_Py_XDECREF(pyresult);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+#define SWIGPY_FUNPACK_OBJOBJPROC_CLOSURE(wrapper) \
+SWIGINTERN int \
+wrapper##_objobjproc_closure(PyObject *a, PyObject *b) { \
+ return SwigPyBuiltin_funpack_objobjproc_closure(wrapper, a, b); \
+}
+SWIGINTERN int
+SwigPyBuiltin_funpack_objobjproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b) {
+ int result;
+ PyObject *pyresult;
+ pyresult = wrapper(a, b);
+ result = pyresult ? (PyObject_IsTrue(pyresult) ? 1 : 0) : -1;
+ SWIG_Py_XDECREF(pyresult);
+ return result;
+}
+
+#define SWIGPY_OBJOBJARGPROC_CLOSURE(wrapper) \
+SWIGINTERN int \
+wrapper##_objobjargproc_closure(PyObject *a, PyObject *b, PyObject *c) { \
+ return SwigPyBuiltin_objobjargproc_closure(wrapper, a, b, c); \
+}
+SWIGINTERN int
+SwigPyBuiltin_objobjargproc_closure(SwigPyWrapperFunction wrapper, PyObject *a, PyObject *b, PyObject *c) {
+ PyObject *tuple, *resultobj;
+ int result;
+ tuple = PyTuple_New(c ? 2 : 1);
+ assert(tuple);
+ SWIG_Py_INCREF(b);
+ PyTuple_SET_ITEM(tuple, 0, b);
+ if (c) {
+ SWIG_Py_INCREF(c);
+ PyTuple_SET_ITEM(tuple, 1, c);
+ }
+ resultobj = wrapper(a, tuple);
+ result = resultobj ? 0 : -1;
+ SWIG_Py_XDECREF(resultobj);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+#define SWIGPY_REPRFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_reprfunc_closure(PyObject *a) { \
+ return SwigPyBuiltin_reprfunc_closure(wrapper, a); \
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_reprfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ return wrapper(a, NULL);
+}
+
+#define SWIGPY_HASHFUNC_CLOSURE(wrapper) \
+SWIGINTERN Py_hash_t \
+wrapper##_hashfunc_closure(PyObject *a) { \
+ return SwigPyBuiltin_hashfunc_closure(wrapper, a); \
+}
+SWIGINTERN Py_hash_t
+SwigPyBuiltin_hashfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ PyObject *pyresult;
+ Py_hash_t result;
+ pyresult = wrapper(a, NULL);
+ if (!pyresult)
+ return -1;
+ result = SWIG_PyNumber_AsPyHash(pyresult);
+ SWIG_Py_DECREF(pyresult);
+ return result;
+}
+
+#define SWIGPY_ITERNEXTFUNC_CLOSURE(wrapper) \
+SWIGINTERN PyObject * \
+wrapper##_iternextfunc_closure(PyObject *a) { \
+ return SwigPyBuiltin_iternextfunc_closure(wrapper, a);\
+}
+SWIGINTERN PyObject *
+SwigPyBuiltin_iternextfunc_closure(SwigPyWrapperFunction wrapper, PyObject *a) {
+ return wrapper(a, NULL);
+}
+
+/* End of callback function macros for use in PyTypeObject */
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/contrib/tools/swig/Lib/python/carrays.i b/contrib/tools/swig/Lib/python/carrays.i
new file mode 100644
index 00000000000..a7b6120d38e
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/carrays.i
@@ -0,0 +1,9 @@
+%define %array_class(TYPE,NAME)
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "sq_item", functype="ssizeargfunc") NAME::__getitem__;
+ %feature("python:slot", "sq_ass_item", functype="ssizeobjargproc") NAME::__setitem__;
+#endif
+%array_class_wrap(TYPE,NAME,__getitem__,__setitem__)
+%enddef
+
+%include <typemaps/carrays.swg>
diff --git a/contrib/tools/swig/Lib/python/ccomplex.i b/contrib/tools/swig/Lib/python/ccomplex.i
new file mode 100644
index 00000000000..b99f96a4890
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/ccomplex.i
@@ -0,0 +1,27 @@
+/* -----------------------------------------------------------------------------
+ * ccomplex.i
+ *
+ * C complex typemaps
+ * ISO C99: 7.3 Complex arithmetic <complex.h>
+ * ----------------------------------------------------------------------------- */
+
+
+%include <pycomplex.swg>
+
+%{
+#include <complex.h>
+%}
+
+#define complex _Complex
+
+/* C complex constructor */
+#define CCplxConst(r, i) ((r) + I*(i))
+
+%swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag);
+%swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag);
+%swig_cplxdbl_convn(_Complex, CCplxConst, creal, cimag);
+
+/* declaring the typemaps */
+%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex);
+%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex);
+%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, _Complex);
diff --git a/contrib/tools/swig/Lib/python/cmalloc.i b/contrib/tools/swig/Lib/python/cmalloc.i
new file mode 100644
index 00000000000..248f06b961b
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/cmalloc.i
@@ -0,0 +1 @@
+%include <typemaps/cmalloc.swg>
diff --git a/contrib/tools/swig/Lib/python/complex.i b/contrib/tools/swig/Lib/python/complex.i
new file mode 100644
index 00000000000..4c3b3c5e2b1
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/complex.i
@@ -0,0 +1,6 @@
+#ifdef __cplusplus
+%include <std_complex.i>
+#else
+%include <ccomplex.i>
+#endif
+
diff --git a/contrib/tools/swig/Lib/python/cpointer.i b/contrib/tools/swig/Lib/python/cpointer.i
new file mode 100644
index 00000000000..d824792fa7a
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/cpointer.i
@@ -0,0 +1 @@
+%include <typemaps/cpointer.swg>
diff --git a/contrib/tools/swig/Lib/python/cstring.i b/contrib/tools/swig/Lib/python/cstring.i
new file mode 100644
index 00000000000..ede9c596aef
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/cstring.i
@@ -0,0 +1 @@
+%include <typemaps/cstring.swg>
diff --git a/contrib/tools/swig/Lib/python/cwstring.i b/contrib/tools/swig/Lib/python/cwstring.i
new file mode 100644
index 00000000000..2824d9c7b0f
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/cwstring.i
@@ -0,0 +1,3 @@
+%include <pywstrings.swg>
+%include <typemaps/cwstring.swg>
+
diff --git a/contrib/tools/swig/Lib/python/director.swg b/contrib/tools/swig/Lib/python/director.swg
new file mode 100644
index 00000000000..c5935695ea2
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/director.swg
@@ -0,0 +1,359 @@
+/* -----------------------------------------------------------------------------
+ * director.swg
+ *
+ * This file contains support for director classes so that Python proxy
+ * methods can be called from C++.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DIRECTOR_PYTHON_HEADER_
+#define SWIG_DIRECTOR_PYTHON_HEADER_
+
+#include <string>
+#include <iostream>
+#include <exception>
+#include <vector>
+#include <map>
+
+/*
+ Use -DSWIG_PYTHON_DIRECTOR_NO_VTABLE if you don't want to generate a 'virtual
+ table', and avoid multiple GetAttr calls to retrieve the python
+ methods.
+*/
+
+#ifndef SWIG_PYTHON_DIRECTOR_NO_VTABLE
+#ifndef SWIG_PYTHON_DIRECTOR_VTABLE
+#define SWIG_PYTHON_DIRECTOR_VTABLE
+#endif
+#endif
+
+
+
+/*
+ Use -DSWIG_DIRECTOR_NO_UEH if you prefer to avoid the use of the
+ Undefined Exception Handler provided by swig.
+*/
+#ifndef SWIG_DIRECTOR_NO_UEH
+#ifndef SWIG_DIRECTOR_UEH
+#define SWIG_DIRECTOR_UEH
+#endif
+#endif
+
+
+/*
+ Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the
+ native C++ RTTI and dynamic_cast<>. But be aware that directors
+ could stop working when using this option.
+*/
+#ifdef SWIG_DIRECTOR_NORTTI
+/*
+ When we don't use the native C++ RTTI, we implement a minimal one
+ only for Directors.
+*/
+# ifndef SWIG_DIRECTOR_RTDIR
+# define SWIG_DIRECTOR_RTDIR
+
+namespace Swig {
+ class Director;
+ SWIGINTERN std::map<void *, Director *>& get_rtdir_map() {
+ static std::map<void *, Director *> rtdir_map;
+ return rtdir_map;
+ }
+
+ SWIGINTERNINLINE void set_rtdir(void *vptr, Director *rtdir) {
+ get_rtdir_map()[vptr] = rtdir;
+ }
+
+ SWIGINTERNINLINE Director *get_rtdir(void *vptr) {
+ std::map<void *, Director *>::const_iterator pos = get_rtdir_map().find(vptr);
+ Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0;
+ return rtdir;
+ }
+}
+# endif /* SWIG_DIRECTOR_RTDIR */
+
+# define SWIG_DIRECTOR_CAST(ARG) Swig::get_rtdir(static_cast<void *>(ARG))
+# define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast<void *>(ARG1), ARG2)
+
+#else
+
+# define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG)
+# define SWIG_DIRECTOR_RGTR(ARG1, ARG2)
+
+#endif /* SWIG_DIRECTOR_NORTTI */
+
+extern "C" {
+ struct swig_type_info;
+}
+
+namespace Swig {
+
+ /* memory handler */
+ struct GCItem {
+ virtual ~GCItem() {}
+
+ virtual int get_own() const {
+ return 0;
+ }
+ };
+
+ struct GCItem_var {
+ GCItem_var(GCItem *item = 0) : _item(item) {
+ }
+
+ GCItem_var& operator=(GCItem *item) {
+ GCItem *tmp = _item;
+ _item = item;
+ delete tmp;
+ return *this;
+ }
+
+ ~GCItem_var() {
+ delete _item;
+ }
+
+ GCItem * operator->() const {
+ return _item;
+ }
+
+ private:
+ GCItem *_item;
+ };
+
+ struct GCItem_Object : GCItem {
+ GCItem_Object(int own) : _own(own) {
+ }
+
+ virtual ~GCItem_Object() {
+ }
+
+ int get_own() const {
+ return _own;
+ }
+
+ private:
+ int _own;
+ };
+
+ template <typename Type>
+ struct GCItem_T : GCItem {
+ GCItem_T(Type *ptr) : _ptr(ptr) {
+ }
+
+ virtual ~GCItem_T() {
+ delete _ptr;
+ }
+
+ private:
+ Type *_ptr;
+ };
+
+ template <typename Type>
+ struct GCArray_T : GCItem {
+ GCArray_T(Type *ptr) : _ptr(ptr) {
+ }
+
+ virtual ~GCArray_T() {
+ delete[] _ptr;
+ }
+
+ private:
+ Type *_ptr;
+ };
+
+ /* base class for director exceptions */
+ class DirectorException : public std::exception {
+ protected:
+ std::string swig_msg;
+ public:
+ DirectorException(PyObject *error, const char *hdr ="", const char *msg ="") : swig_msg(hdr) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (msg[0]) {
+ swig_msg += " ";
+ swig_msg += msg;
+ }
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(error, swig_msg.c_str());
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ }
+
+ virtual ~DirectorException() throw() {
+ }
+
+ /* Deprecated, use what() instead */
+ const char *getMessage() const {
+ return what();
+ }
+
+ const char *what() const throw() {
+ return swig_msg.c_str();
+ }
+
+ static void raise(PyObject *error, const char *msg) {
+ throw DirectorException(error, msg);
+ }
+
+ static void raise(const char *msg) {
+ raise(PyExc_RuntimeError, msg);
+ }
+ };
+
+ /* type mismatch in the return value from a python method call */
+ class DirectorTypeMismatchException : public DirectorException {
+ public:
+ DirectorTypeMismatchException(PyObject *error, const char *msg="")
+ : DirectorException(error, "SWIG director type mismatch", msg) {
+ }
+
+ DirectorTypeMismatchException(const char *msg="")
+ : DirectorException(PyExc_TypeError, "SWIG director type mismatch", msg) {
+ }
+
+ static void raise(PyObject *error, const char *msg) {
+ throw DirectorTypeMismatchException(error, msg);
+ }
+
+ static void raise(const char *msg) {
+ throw DirectorTypeMismatchException(msg);
+ }
+ };
+
+ /* any python exception that occurs during a director method call */
+ class DirectorMethodException : public DirectorException {
+ public:
+ DirectorMethodException(const char *msg = "")
+ : DirectorException(PyExc_RuntimeError, "SWIG director method error.", msg) {
+ }
+
+ static void raise(const char *msg) {
+ throw DirectorMethodException(msg);
+ }
+ };
+
+ /* attempt to call a pure virtual method via a director method */
+ class DirectorPureVirtualException : public DirectorException {
+ public:
+ DirectorPureVirtualException(const char *msg = "")
+ : DirectorException(PyExc_RuntimeError, "SWIG director pure virtual method called", msg) {
+ }
+
+ static void raise(const char *msg) {
+ throw DirectorPureVirtualException(msg);
+ }
+ };
+
+
+
+ /* director base class */
+ class Director {
+ private:
+ /* pointer to the wrapped python object */
+ PyObject *swig_self;
+ /* flag indicating whether the object is owned by python or c++ */
+ mutable bool swig_disown_flag;
+
+ /* decrement the reference count of the wrapped python object */
+ void swig_decref() const {
+ if (swig_disown_flag) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ SWIG_Py_DECREF(swig_self);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ }
+ }
+
+ public:
+ /* wrap a python object. */
+ Director(PyObject *self) : swig_self(self), swig_disown_flag(false) {
+ }
+
+ /* discard our reference at destruction */
+ virtual ~Director() {
+ swig_decref();
+ }
+
+ /* return a pointer to the wrapped python object */
+ PyObject *swig_get_self() const {
+ return swig_self;
+ }
+
+ /* acquire ownership of the wrapped python object (the sense of "disown" is from python) */
+ void swig_disown() const {
+ if (!swig_disown_flag) {
+ swig_disown_flag=true;
+ swig_incref();
+ }
+ }
+
+ /* increase the reference count of the wrapped python object */
+ void swig_incref() const {
+ if (swig_disown_flag) {
+ SWIG_Py_INCREF(swig_self);
+ }
+ }
+
+ /* methods to implement pseudo protected director members */
+ virtual bool swig_get_inner(const char * /* swig_protected_method_name */) const {
+ return true;
+ }
+
+ virtual void swig_set_inner(const char * /* swig_protected_method_name */, bool /* swig_val */) const {
+ }
+
+ /* ownership management */
+ private:
+ typedef std::map<void *, GCItem_var> swig_ownership_map;
+ mutable swig_ownership_map swig_owner;
+ SWIG_GUARD_DECLARATION(swig_mutex_own);
+
+ public:
+ template <typename Type>
+ void swig_acquire_ownership_array(Type *vptr) const {
+ if (vptr) {
+ SWIG_GUARD(swig_mutex_own);
+ swig_owner[vptr] = new GCArray_T<Type>(vptr);
+ }
+ }
+
+ template <typename Type>
+ void swig_acquire_ownership(Type *vptr) const {
+ if (vptr) {
+ SWIG_GUARD(swig_mutex_own);
+ swig_owner[vptr] = new GCItem_T<Type>(vptr);
+ }
+ }
+
+ void swig_acquire_ownership_obj(void *vptr, int own) const {
+ if (vptr && own) {
+ SWIG_GUARD(swig_mutex_own);
+ swig_owner[vptr] = new GCItem_Object(own);
+ }
+ }
+
+ int swig_release_ownership(void *vptr) const {
+ int own = 0;
+ if (vptr) {
+ SWIG_GUARD(swig_mutex_own);
+ swig_ownership_map::iterator iter = swig_owner.find(vptr);
+ if (iter != swig_owner.end()) {
+ own = iter->second->get_own();
+ swig_owner.erase(iter);
+ }
+ }
+ return own;
+ }
+
+ template <typename Type>
+ static PyObject *swig_pyobj_disown(PyObject *pyobj, PyObject *SWIGUNUSEDPARM(args)) {
+ SwigPyObject *sobj = (SwigPyObject *)pyobj;
+ sobj->own = 0;
+ Director *d = SWIG_DIRECTOR_CAST(reinterpret_cast<Type *>(sobj->ptr));
+ if (d)
+ d->swig_disown();
+ return PyWeakref_NewProxy(pyobj, NULL);
+ }
+ };
+
+ SWIG_GUARD_DEFINITION(Director, swig_mutex_own);
+}
+
+#endif
diff --git a/contrib/tools/swig/Lib/python/director_py_mutex.swg b/contrib/tools/swig/Lib/python/director_py_mutex.swg
new file mode 100644
index 00000000000..5bb0f83f26b
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/director_py_mutex.swg
@@ -0,0 +1,24 @@
+/* -----------------------------------------------------------------------------
+ * director_py_mutex.swg
+ *
+ * contains python mutex for threads
+ * ----------------------------------------------------------------------------- */
+
+#if defined(SWIG_PYTHON_THREADS) && !defined(SWIG_THREADS)
+#define SWIG_THREADS 1
+#endif
+#if defined(SWIG_THREADS) && !defined(Py_LIMITED_API)
+#include "pythread.h"
+#define SWIG_HAVE_MUTEX
+namespace Swig {
+ class Mutex
+ {
+ PyThread_type_lock mutex_;
+ public:
+ Mutex() : mutex_(PyThread_allocate_lock()) {}
+ ~Mutex() { PyThread_free_lock(mutex_); }
+ void lock() { PyThread_acquire_lock(mutex_, WAIT_LOCK); }
+ void unlock() { PyThread_release_lock(mutex_); }
+ };
+}
+#endif
diff --git a/contrib/tools/swig/Lib/python/embed.i b/contrib/tools/swig/Lib/python/embed.i
new file mode 100644
index 00000000000..e5ee601d92f
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/embed.i
@@ -0,0 +1,113 @@
+//
+// embed.i
+// SWIG file embedding the Python interpreter in something else.
+// This file is deprecated and no longer actively maintained, but it still
+// seems to work with Python 2.7. It doesn't work with Python 3.
+//
+// This file makes it possible to extend Python and all of its
+// built-in functions without having to hack its setup script.
+//
+// This module provides support for building a new version of the
+// Python executable. This will be necessary on systems that do
+// not support shared libraries and may be necessary with C++
+// extensions. This file contains everything you need to build
+// a new version of Python from include files and libraries normally
+// installed with the Python language.
+//
+// This module will automatically grab all of the Python modules
+// present in your current Python executable (including any special
+// purpose modules you have enabled such as Tkinter). Thus, you
+// may need to provide additional link libraries when compiling.
+//
+// As far as I know, this module is C++ safe.
+
+%wrapper %{
+#if !defined(PY_SSIZE_T_CLEAN) && !defined(SWIG_NO_PY_SSIZE_T_CLEAN)
+#define PY_SSIZE_T_CLEAN
+#endif
+
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#if defined(__cplusplus) && __cplusplus >=201703L
+#pragma GCC diagnostic ignored "-Wregister" /* For python-2.7 headers that use register */
+#endif
+#endif
+
+#include <Python.h>
+
+#if __GNUC__ >= 7
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void SWIG_init(); /* Forward reference */
+
+#define _PyImport_Inittab swig_inittab
+
+/* Grab Python's inittab[] structure */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <config.c>
+
+#undef _PyImport_Inittab
+
+/* Now define our own version of it.
+ Hopefully someone does not have more than 1000 built-in modules */
+
+struct _inittab SWIG_Import_Inittab[1000];
+
+static int swig_num_modules = 0;
+
+/* Function for adding modules to Python */
+
+static void swig_add_module(char *name, void (*initfunc)()) {
+ SWIG_Import_Inittab[swig_num_modules].name = name;
+ SWIG_Import_Inittab[swig_num_modules].initfunc = initfunc;
+ swig_num_modules++;
+ SWIG_Import_Inittab[swig_num_modules].name = (char *) 0;
+ SWIG_Import_Inittab[swig_num_modules].initfunc = 0;
+}
+
+/* Function to add all of Python's built-in modules to our interpreter */
+
+static void swig_add_builtin() {
+ int i = 0;
+ while (swig_inittab[i].name) {
+ swig_add_module(swig_inittab[i].name, swig_inittab[i].initfunc);
+ i++;
+ }
+#ifdef SWIGMODINIT
+ SWIGMODINIT
+#endif
+ /* Add SWIG builtin function */
+ swig_add_module(SWIG_name, SWIG_init);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int Py_Main(int, char **);
+
+#ifdef __cplusplus
+}
+#endif
+
+extern struct _inittab *PyImport_Inittab;
+
+int
+main(int argc, char **argv) {
+ swig_add_builtin();
+ PyImport_Inittab = SWIG_Import_Inittab;
+ return Py_Main(argc,argv);
+}
+
+%}
diff --git a/contrib/tools/swig/Lib/python/exception.i b/contrib/tools/swig/Lib/python/exception.i
new file mode 100644
index 00000000000..bb0b15c9dde
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/exception.i
@@ -0,0 +1,6 @@
+%include <typemaps/exception.swg>
+
+
+%insert("runtime") {
+ %define_as(SWIG_exception(code, msg), %block(%error(code, msg); SWIG_fail; ))
+}
diff --git a/contrib/tools/swig/Lib/python/factory.i b/contrib/tools/swig/Lib/python/factory.i
new file mode 100644
index 00000000000..46a0a8733e7
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/factory.i
@@ -0,0 +1 @@
+%include <typemaps/factory.swg>
diff --git a/contrib/tools/swig/Lib/python/file.i b/contrib/tools/swig/Lib/python/file.i
new file mode 100644
index 00000000000..359c34d2c50
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/file.i
@@ -0,0 +1,41 @@
+/* -----------------------------------------------------------------------------
+ * file.i
+ *
+ * Typemaps for FILE*
+ * ----------------------------------------------------------------------------- */
+
+%types(FILE *);
+
+/* defining basic methods */
+%fragment("SWIG_AsValFilePtr","header") {
+SWIGINTERN int
+SWIG_AsValFilePtr(PyObject *obj, FILE **val) {
+ static swig_type_info* desc = 0;
+ void *vptr = 0;
+ if (!desc) desc = SWIG_TypeQuery("FILE *");
+ if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
+ if (val) *val = (FILE *)vptr;
+ return SWIG_OK;
+ }
+%#if PY_VERSION_HEX < 0x03000000
+ if (PyFile_Check(obj)) {
+ if (val) *val = PyFile_AsFile(obj);
+ return SWIG_OK;
+ }
+%#endif
+ return SWIG_TypeError;
+}
+}
+
+
+%fragment("SWIG_AsFilePtr","header",fragment="SWIG_AsValFilePtr") {
+SWIGINTERNINLINE FILE*
+SWIG_AsFilePtr(PyObject *obj) {
+ FILE *val = 0;
+ SWIG_AsValFilePtr(obj, &val);
+ return val;
+}
+}
+
+/* defining the typemaps */
+%typemaps_asval(%checkcode(POINTER), SWIG_AsValFilePtr, "SWIG_AsValFilePtr", FILE*);
diff --git a/contrib/tools/swig/Lib/python/implicit.i b/contrib/tools/swig/Lib/python/implicit.i
new file mode 100644
index 00000000000..152c2b0566b
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/implicit.i
@@ -0,0 +1,7 @@
+%include <std_common.i>
+%include <typemaps/implicit.swg>
+
+#warning "This file provides the %implicit directive, which is an old and fragile"
+#warning "way to implement the C++ implicit conversion mechanism."
+#warning "Try using the more robust '%implicitconv Type;' directive instead."
+
diff --git a/contrib/tools/swig/Lib/python/pyabc.i b/contrib/tools/swig/Lib/python/pyabc.i
new file mode 100644
index 00000000000..cae1e7032ff
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyabc.i
@@ -0,0 +1,14 @@
+%define %pythonabc(Type, Abc)
+ %feature("python:abc", Abc) Type;
+%enddef
+%pythoncode %{if _swig_python_version_info[0:2] >= (3, 3):
+ import collections.abc
+else:
+ import collections
+%}
+%pythonabc(std::vector, "collections.abc.MutableSequence if _swig_python_version_info >= (3, 3) else collections.MutableSequence");
+%pythonabc(std::list, "collections.abc.MutableSequence if _swig_python_version_info >= (3, 3) else collections.MutableSequence");
+%pythonabc(std::map, "collections.abc.MutableMapping if _swig_python_version_info >= (3, 3) else collections.MutableMapping");
+%pythonabc(std::multimap, "collections.abc.MutableMapping if _swig_python_version_info >= (3, 3) else collections.MutableMapping");
+%pythonabc(std::set, "collections.abc.MutableSet if _swig_python_version_info >= (3, 3) else collections.MutableSet");
+%pythonabc(std::multiset, "collections.abc.MutableSet if _swig_python_version_info >= (3, 3) else collections.MutableSet");
diff --git a/contrib/tools/swig/Lib/python/pyapi.swg b/contrib/tools/swig/Lib/python/pyapi.swg
new file mode 100644
index 00000000000..19e6979b56d
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyapi.swg
@@ -0,0 +1,30 @@
+/* -----------------------------------------------------------------------------
+ * Python API portion that goes into the runtime
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Constant declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Constant Types */
+#define SWIG_PY_POINTER 4
+#define SWIG_PY_BINARY 5
+
+/* Constant information structure */
+typedef struct swig_const_info {
+ int type;
+ const char *name;
+ long lvalue;
+ double dvalue;
+ void *pvalue;
+ swig_type_info **ptype;
+} swig_const_info;
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/contrib/tools/swig/Lib/python/pybackward.swg b/contrib/tools/swig/Lib/python/pybackward.swg
new file mode 100644
index 00000000000..8305fc78b7c
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pybackward.swg
@@ -0,0 +1,45 @@
+/*
+ adding backward compatibility macros
+*/
+
+#define SWIG_arg(x...) %arg(x)
+#define SWIG_Mangle(x...) %mangle(x)
+
+#define SWIG_As_frag(Type...) %fragment_name(As, Type)
+#define SWIG_As_name(Type...) %symbol_name(As, Type)
+#define SWIG_As(Type...) SWIG_As_name(Type) SWIG_AS_CALL_ARGS
+
+#define SWIG_Check_frag(Type...) %fragment_name(Check, Type)
+#define SWIG_Check_name(Type...) %symbol_name(Check, Type)
+#define SWIG_Check(Type...) SWIG_Check_name(Type) SWIG_AS_CALL_ARGS
+
+%define %ascheck_methods(Code, Type...)
+%fragment(SWIG_As_frag(Type),"header", fragment=SWIG_AsVal_frag(Type)) {
+SWIGINTERNINLINE Type
+SWIG_As(Type)(PyObject* obj)
+{
+ Type v;
+ int res = SWIG_AsVal(Type)(obj, &v);
+ if (!SWIG_IsOK(res)) {
+ /*
+ this is needed to make valgrind/purify happier.
+ */
+ memset((void*)&v, 0, sizeof(Type));
+ SWIG_Error(res, "");
+ }
+ return v;
+}
+}
+
+%fragment(SWIG_Check_frag(Type),"header",fragment=SWIG_AsVal_frag(Type)) {
+SWIGINTERNINLINE int
+SWIG_Check(Type)(PyObject* obj)
+{
+ int res = SWIG_AsVal(Type)(obj, (Type*)0);
+ return SWIG_IsOK(res);
+}
+}
+%enddef
+
+%apply_checkctypes(%ascheck_methods)
+
diff --git a/contrib/tools/swig/Lib/python/pybuffer.i b/contrib/tools/swig/Lib/python/pybuffer.i
new file mode 100644
index 00000000000..9ebc36a8c4e
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pybuffer.i
@@ -0,0 +1,203 @@
+/* Implementing buffer protocol typemaps */
+
+/* %pybuffer_mutable_binary(TYPEMAP, SIZE)
+ *
+ * Macro for functions accept mutable buffer pointer with a size.
+ * This can be used for both input and output. For example:
+ *
+ * %pybuffer_mutable_binary(char *buff, int size);
+ * void foo(char *buff, int size) {
+ * for(int i=0; i<size; ++i)
+ * buff[i]++;
+ * }
+ */
+
+/* Note that in Py_LIMITED_API case we have no choice, but to use deprecated
+ * functions, as they provides the only way to access buffer data with limited
+ * API, which doesn't include Py_buffer definition. We also disable the
+ * warnings about doing this because they're not useful in our case.
+ */
+
+%define %pybuffer_mutable_binary(TYPEMAP, SIZE)
+%typemap(in) (TYPEMAP, SIZE) {
+ int res; Py_ssize_t size = 0; void *buf = 0;
+%#ifndef Py_LIMITED_API
+ Py_buffer view;
+ res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE);
+%#else
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic push
+ %#pragma GCC diagnostic ignored "-Wdeprecated"
+ %#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ %#elif defined(_MSC_VER)
+ %#pragma warning(push)
+ %#pragma warning(disable: 4996)
+ %#endif
+ res = PyObject_AsWriteBuffer($input, &buf, &size);
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic pop
+ %#elif defined(_MSC_VER)
+ %#pragma warning(pop)
+ %#endif
+%#endif
+ if (res < 0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+%#ifndef Py_LIMITED_API
+ size = view.len;
+ buf = view.buf;
+ PyBuffer_Release(&view);
+%#endif
+ $1 = ($1_ltype) buf;
+ $2 = ($2_ltype) (size/sizeof($*1_type));
+}
+%enddef
+
+/* %pybuffer_mutable_string(TYPEMAP)
+ *
+ * Macro for functions accept mutable zero terminated string pointer.
+ * This can be used for both input and output. For example:
+ *
+ * %pybuffer_mutable_string(char *str);
+ * void foo(char *str) {
+ * while(*str) {
+ * *str = toupper(*str);
+ * str++;
+ * }
+ */
+
+%define %pybuffer_mutable_string(TYPEMAP)
+%typemap(in) (TYPEMAP) {
+ int res; void *buf = 0;
+%#ifndef Py_LIMITED_API
+ Py_buffer view;
+ res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE);
+%#else
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic push
+ %#pragma GCC diagnostic ignored "-Wdeprecated"
+ %#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ %#elif defined(_MSC_VER)
+ %#pragma warning(push)
+ %#pragma warning(disable: 4996)
+ %#endif
+ Py_ssize_t size;
+ res = PyObject_AsWriteBuffer($input, &buf, &size);
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic pop
+ %#elif defined(_MSC_VER)
+ %#pragma warning(pop)
+ %#endif
+%#endif
+ if (res < 0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP)", $symname, $argnum);
+ }
+%#ifndef Py_LIMITED_API
+ buf = view.buf;
+ PyBuffer_Release(&view);
+%#endif
+ $1 = ($1_ltype) buf;
+}
+%enddef
+
+/* pybuffer_binary(TYPEMAP, SIZE)
+ *
+ * Macro for functions accept read only buffer pointer with a size.
+ * This must be used for input. For example:
+ *
+ * %pybuffer_binary(char *buff, int size);
+ * int foo(char *buff, int size) {
+ * int count = 0;
+ * for(int i=0; i<size; ++i)
+ * if (0==buff[i]) count++;
+ * return count;
+ * }
+ */
+
+%define %pybuffer_binary(TYPEMAP, SIZE)
+%typemap(in) (TYPEMAP, SIZE) {
+ int res; Py_ssize_t size = 0; const void *buf = 0;
+%#ifndef Py_LIMITED_API
+ Py_buffer view;
+ res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO);
+%#else
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic push
+ %#pragma GCC diagnostic ignored "-Wdeprecated"
+ %#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ %#elif defined(_MSC_VER)
+ %#pragma warning(push)
+ %#pragma warning(disable: 4996)
+ %#endif
+ res = PyObject_AsReadBuffer($input, &buf, &size);
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic pop
+ %#elif defined(_MSC_VER)
+ %#pragma warning(pop)
+ %#endif
+%#endif
+ if (res < 0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+%#ifndef Py_LIMITED_API
+ size = view.len;
+ buf = view.buf;
+ PyBuffer_Release(&view);
+%#endif
+ $1 = ($1_ltype) buf;
+ $2 = ($2_ltype) (size / sizeof($*1_type));
+}
+%enddef
+
+/* %pybuffer_string(TYPEMAP)
+ *
+ * Macro for functions accept read only zero terminated string pointer.
+ * This can be used for input. For example:
+ *
+ * %pybuffer_string(char *str);
+ * int foo(char *str) {
+ * int count = 0;
+ * while(*str) {
+ * if (isalnum(*str))
+ * count++;
+ * str++;
+ * }
+ */
+
+%define %pybuffer_string(TYPEMAP)
+%typemap(in) (TYPEMAP) {
+ int res; const void *buf = 0;
+%#ifndef Py_LIMITED_API
+ Py_buffer view;
+ res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO);
+%#else
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic push
+ %#pragma GCC diagnostic ignored "-Wdeprecated"
+ %#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ %#elif defined(_MSC_VER)
+ %#pragma warning(push)
+ %#pragma warning(disable: 4996)
+ %#endif
+ Py_ssize_t size;
+ res = PyObject_AsReadBuffer($input, &buf, &size);
+ %#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+ %#pragma GCC diagnostic pop
+ %#elif defined(_MSC_VER)
+ %#pragma warning(pop)
+ %#endif
+%#endif
+ if (res < 0) {
+ PyErr_Clear();
+ %argument_fail(res, "(TYPEMAP)", $symname, $argnum);
+ }
+%#ifndef Py_LIMITED_API
+ buf = view.buf;
+ PyBuffer_Release(&view);
+%#endif
+ $1 = ($1_ltype) buf;
+}
+%enddef
diff --git a/contrib/tools/swig/Lib/python/pyclasses.swg b/contrib/tools/swig/Lib/python/pyclasses.swg
new file mode 100644
index 00000000000..7a9d093657c
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyclasses.swg
@@ -0,0 +1,157 @@
+#ifdef __cplusplus
+
+/*
+ SwigPtr_PyObject is used as a replacement of PyObject *, where
+ the INCREF/DECREF are applied as needed.
+
+ You can use SwigPtr_PyObject in a container, such as
+
+ std::vector<SwigPtr_PyObject>;
+
+ or as a member variable:
+
+ struct A {
+ SwigPtr_PyObject _obj;
+ A(PyObject *o) : _obj(o) {
+ }
+ };
+
+ or as a input/output value
+
+ SwigPtr_PyObject func(SwigPtr_PyObject obj) {
+ SwigPtr_PyObject out = PyString_FromFormat("hello %s", PyObject_AsString(obj));
+ SWIG_Py_DECREF(out);
+ return out;
+ }
+
+ just remember to pair the object creation with the proper DECREF,
+ the same as with plain PyObject *ptr, since SwigPtr_PyObject always add
+ one reference at construction.
+
+ SwigPtr_PyObject is 'visible' at the wrapped side, so you can do:
+
+
+ %template(pyvector) std::vector<swig::SwigPtr_PyObject>;
+
+ and all the proper typemaps will be used.
+
+*/
+
+namespace swig {
+ %ignore SwigPtr_PyObject;
+ struct SwigPtr_PyObject {};
+ %apply PyObject * {SwigPtr_PyObject};
+ %apply PyObject * const& {SwigPtr_PyObject const&};
+
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_SWIGOBJECT,noblock=1) SwigPtr_PyObject const& "$1 = ($input != 0);"
+
+
+ /* For output */
+ %typemap(out,noblock=1) SwigPtr_PyObject {
+ $result = (PyObject *)$1;
+ SWIG_Py_INCREF($result);
+ }
+
+ %typemap(out,noblock=1) SwigPtr_PyObject const & {
+ $result = (PyObject *)*$1;
+ SWIG_Py_INCREF($result);
+ }
+
+}
+
+%{
+namespace swig {
+ class SwigPtr_PyObject {
+ protected:
+ PyObject *_obj;
+
+ public:
+ SwigPtr_PyObject() :_obj(0)
+ {
+ }
+
+ SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
+ {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ SWIG_Py_XINCREF(_obj);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ }
+
+ SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
+ {
+ if (initial_ref) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ SWIG_Py_XINCREF(_obj);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ }
+ }
+
+ SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item)
+ {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ SWIG_Py_XINCREF(item._obj);
+ SWIG_Py_XDECREF(_obj);
+ _obj = item._obj;
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return *this;
+ }
+
+ ~SwigPtr_PyObject()
+ {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ SWIG_Py_XDECREF(_obj);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ }
+
+ operator PyObject *() const
+ {
+ return _obj;
+ }
+
+ PyObject *operator->() const
+ {
+ return _obj;
+ }
+ };
+}
+%}
+
+/*
+ SwigVar_PyObject is used to manage 'in the scope' PyObject * variables,
+ as in
+
+ int func () {
+ SwigVar_PyObject obj = PyString_FromString("hello");
+ }
+
+ ie, 'obj' is created and destructed in the same scope from
+ a python object that carries at least one reference value.
+
+ SwigVar_PyObject just take care of applying the proper Py_DECREF.
+
+ Hence, this class is purely internal and not visible at the wrapped side.
+ */
+namespace swig {
+ %ignore SwigVar_PyObject;
+ struct SwigVar_PyObject {};
+ %apply PyObject * {SwigVar_PyObject};
+ %apply PyObject * const& {SwigVar_PyObject const&};
+}
+
+%{
+namespace swig {
+ struct SwigVar_PyObject : SwigPtr_PyObject {
+ SwigVar_PyObject(PyObject* obj = 0) : SwigPtr_PyObject(obj, false) { }
+
+ SwigVar_PyObject & operator = (PyObject* obj)
+ {
+ SWIG_Py_XDECREF(_obj);
+ _obj = obj;
+ return *this;
+ }
+ };
+}
+%}
+
+
+#endif
diff --git a/contrib/tools/swig/Lib/python/pycomplex.swg b/contrib/tools/swig/Lib/python/pycomplex.swg
new file mode 100644
index 00000000000..eeb9af7be07
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pycomplex.swg
@@ -0,0 +1,90 @@
+/*
+ Defines the As/From converters for double/float complex, you need to
+ provide complex Type, the Name you want to use in the converters,
+ the complex Constructor method, and the Real and Imag complex
+ accessor methods.
+
+ See the std_complex.i and ccomplex.i for concrete examples.
+*/
+
+/* the common from converter */
+%define %swig_fromcplx_conv(Type, Real, Imag)
+%fragment(SWIG_From_frag(Type),"header")
+{
+SWIGINTERNINLINE PyObject*
+#if defined(__cplusplus)
+SWIG_From_dec(Type)(const Type& c)
+#else
+SWIG_From_dec(Type)(Type c)
+#endif
+{
+ return PyComplex_FromDoubles(Real(c), Imag(c));
+}
+}
+%enddef
+
+/* the double case */
+%define %swig_cplxdbl_conv(Type, Constructor, Real, Imag)
+%fragment(SWIG_AsVal_frag(Type),"header",
+ fragment=SWIG_AsVal_frag(double))
+{
+SWIGINTERN int
+SWIG_AsVal(Type) (PyObject *o, Type* val)
+{
+ if (PyComplex_Check(o)) {
+ if (val) *val = Constructor(PyComplex_RealAsDouble(o), PyComplex_ImagAsDouble(o));
+ return SWIG_OK;
+ } else {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(o, &d));
+ if (SWIG_IsOK(res)) {
+ if (val) *val = Constructor(d, 0.0);
+ return res;
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+%swig_fromcplx_conv(Type, Real, Imag);
+%enddef
+
+/* the float case */
+%define %swig_cplxflt_conv(Type, Constructor, Real, Imag)
+%fragment(SWIG_AsVal_frag(Type),"header",
+ fragment=SWIG_AsVal_frag(float)) {
+SWIGINTERN int
+SWIG_AsVal(Type)(PyObject *o, Type *val)
+{
+ if (PyComplex_Check(o)) {
+ double re = PyComplex_RealAsDouble(o);
+ double im = PyComplex_ImagAsDouble(o);
+ if ((-FLT_MAX <= re && re <= FLT_MAX) && (-FLT_MAX <= im && im <= FLT_MAX)) {
+ if (val) *val = Constructor(%numeric_cast(re, float),
+ %numeric_cast(im, float));
+ return SWIG_OK;
+ } else {
+ return SWIG_OverflowError;
+ }
+ } else {
+ float re;
+ int res = SWIG_AddCast(SWIG_AsVal(float)(o, &re));
+ if (SWIG_IsOK(res)) {
+ if (val) *val = Constructor(re, 0.0f);
+ return res;
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+
+%swig_fromcplx_conv(Type, Real, Imag);
+%enddef
+
+#define %swig_cplxflt_convn(Type, Constructor, Real, Imag) \
+%swig_cplxflt_conv(Type, Constructor, Real, Imag)
+
+
+#define %swig_cplxdbl_convn(Type, Constructor, Real, Imag) \
+%swig_cplxdbl_conv(Type, Constructor, Real, Imag)
+
+
diff --git a/contrib/tools/swig/Lib/python/pycontainer.swg b/contrib/tools/swig/Lib/python/pycontainer.swg
new file mode 100644
index 00000000000..12a45bfc89d
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pycontainer.swg
@@ -0,0 +1,871 @@
+/* -----------------------------------------------------------------------------
+ * pycontainer.swg
+ *
+ * Python sequence <-> C++ container wrapper
+ *
+ * This wrapper, and its iterator, allows a general use (and reuse) of
+ * the mapping between C++ and Python, thanks to the C++ templates.
+ *
+ * Of course, it needs the C++ compiler to support templates, but
+ * since we will use this wrapper with the STL containers, that should
+ * be the case.
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <iostream>
+
+#if PY_VERSION_HEX >= 0x03020000
+# define SWIGPY_SLICEOBJECT PyObject
+#else
+# define SWIGPY_SLICEOBJECT PySliceObject
+#endif
+%}
+
+
+#if !defined(SWIG_NO_EXPORT_ITERATOR_METHODS)
+# if !defined(SWIG_EXPORT_ITERATOR_METHODS)
+# define SWIG_EXPORT_ITERATOR_METHODS SWIG_EXPORT_ITERATOR_METHODS
+# endif
+#endif
+
+%include <pyiterators.swg>
+
+/**** The PySequence C++ Wrap ***/
+
+%fragment("<stdexcept>");
+
+%include <std_except.i>
+
+%fragment("container_owner_attribute_init", "init") {
+ // thread safe initialization
+ swig::container_owner_attribute();
+}
+
+%fragment("reference_container_owner", "header", fragment="container_owner_attribute_init") {
+namespace swig {
+ static PyObject* container_owner_attribute() {
+ static PyObject* attr = SWIG_Python_str_FromChar("__swig_container");
+ return attr;
+ }
+
+ template <typename T>
+ struct container_owner {
+ // By default, do not add the back-reference (for value types)
+ // Specialization below will check the reference for pointer types.
+ static bool back_reference(PyObject* /*child*/, PyObject* /*owner*/) {
+ return false;
+ }
+ };
+
+ template <>
+ struct container_owner<swig::pointer_category> {
+ /*
+ * Call to add a back-reference to the owning object when returning a
+ * reference from a container. Will only set the reference if child
+ * is a SWIG wrapper object that does not own the pointer.
+ *
+ * returns whether the reference was set or not
+ */
+ static bool back_reference(PyObject* child, PyObject* owner) {
+ SwigPyObject* swigThis = SWIG_Python_GetSwigThis(child);
+ if (swigThis && (swigThis->own & SWIG_POINTER_OWN) != SWIG_POINTER_OWN) {
+ return PyObject_SetAttr(child, container_owner_attribute(), owner) != -1;
+ }
+ return false;
+ }
+ };
+}
+}
+
+%fragment(SWIG_Traits_frag(swig::SwigPtr_PyObject),"header",fragment="StdTraits") {
+namespace swig {
+ template <> struct traits<SwigPtr_PyObject > {
+ typedef value_category category;
+ static const char* type_name() { return "SwigPtr_PyObject"; }
+ };
+
+ template <> struct traits_from<SwigPtr_PyObject> {
+ typedef SwigPtr_PyObject value_type;
+ static PyObject *from(const value_type& val) {
+ PyObject *obj = static_cast<PyObject *>(val);
+ SWIG_Py_XINCREF(obj);
+ return obj;
+ }
+ };
+
+ template <>
+ struct traits_check<SwigPtr_PyObject, value_category> {
+ static bool check(SwigPtr_PyObject) {
+ return true;
+ }
+ };
+
+ template <> struct traits_asval<SwigPtr_PyObject > {
+ typedef SwigPtr_PyObject value_type;
+ static int asval(PyObject *obj, value_type *val) {
+ if (val) *val = obj;
+ return SWIG_OK;
+ }
+ };
+}
+}
+
+%fragment(SWIG_Traits_frag(swig::SwigVar_PyObject),"header",fragment="StdTraits") {
+namespace swig {
+ template <> struct traits<SwigVar_PyObject > {
+ typedef value_category category;
+ static const char* type_name() { return "SwigVar_PyObject"; }
+ };
+
+ template <> struct traits_from<SwigVar_PyObject> {
+ typedef SwigVar_PyObject value_type;
+ static PyObject *from(const value_type& val) {
+ PyObject *obj = static_cast<PyObject *>(val);
+ SWIG_Py_XINCREF(obj);
+ return obj;
+ }
+ };
+
+ template <>
+ struct traits_check<SwigVar_PyObject, value_category> {
+ static bool check(SwigVar_PyObject) {
+ return true;
+ }
+ };
+
+ template <> struct traits_asval<SwigVar_PyObject > {
+ typedef SwigVar_PyObject value_type;
+ static int asval(PyObject *obj, value_type *val) {
+ if (val) *val = obj;
+ return SWIG_OK;
+ }
+ };
+}
+}
+
+%fragment("SwigPySequence_Base","header",fragment="<stddef.h>",fragment="StdTraits")
+{
+%#include <functional>
+
+namespace std {
+ template <>
+ struct less <PyObject *>
+ {
+ bool
+ operator()(PyObject * v, PyObject *w) const
+ {
+ bool res;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ res = PyObject_RichCompareBool(v, w, Py_LT) ? true : false;
+ /* This may fall into a case of inconsistent
+ eg. ObjA > ObjX > ObjB
+ but ObjA < ObjB
+ */
+ if( PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_TypeError) )
+ {
+ /* Objects can't be compared, this mostly occurred in Python 3.0 */
+ /* Compare their ptr directly for a workaround */
+ res = (v < w);
+ PyErr_Clear();
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return res;
+ }
+ };
+
+ template <>
+ struct less <swig::SwigPtr_PyObject>
+ {
+ bool
+ operator()(const swig::SwigPtr_PyObject& v, const swig::SwigPtr_PyObject& w) const
+ {
+ return std::less<PyObject *>()(v, w);
+ }
+ };
+
+ template <>
+ struct less <swig::SwigVar_PyObject>
+ {
+ bool
+ operator()(const swig::SwigVar_PyObject& v, const swig::SwigVar_PyObject& w) const
+ {
+ return std::less<PyObject *>()(v, w);
+ }
+ };
+
+}
+
+namespace swig {
+ template <> struct traits<PyObject *> {
+ typedef value_category category;
+ static const char* type_name() { return "PyObject *"; }
+ };
+
+ template <> struct traits_asval<PyObject * > {
+ typedef PyObject * value_type;
+ static int asval(PyObject *obj, value_type *val) {
+ if (val) *val = obj;
+ return SWIG_OK;
+ }
+ };
+
+ template <>
+ struct traits_check<PyObject *, value_category> {
+ static bool check(PyObject *) {
+ return true;
+ }
+ };
+
+ template <> struct traits_from<PyObject *> {
+ typedef PyObject * value_type;
+ static PyObject *from(const value_type& val) {
+ SWIG_Py_XINCREF(val);
+ return val;
+ }
+ };
+
+}
+
+namespace swig {
+ template <class Difference>
+ inline size_t
+ check_index(Difference i, size_t size, bool insert = false) {
+ if ( i < 0 ) {
+ if ((size_t) (-i) <= size)
+ return (size_t) (i + size);
+ } else if ( (size_t) i < size ) {
+ return (size_t) i;
+ } else if (insert && ((size_t) i == size)) {
+ return size;
+ }
+ throw std::out_of_range("index out of range");
+ }
+
+ template <class Difference>
+ void
+ slice_adjust(Difference i, Difference j, Py_ssize_t step, size_t size, Difference &ii, Difference &jj, bool insert = false) {
+ if (step == 0) {
+ throw std::invalid_argument("slice step cannot be zero");
+ } else if (step > 0) {
+ // Required range: 0 <= i < size, 0 <= j < size, i <= j
+ if (i < 0) {
+ ii = 0;
+ } else if (i < (Difference)size) {
+ ii = i;
+ } else if (insert && (i >= (Difference)size)) {
+ ii = (Difference)size;
+ }
+ if (j < 0) {
+ jj = 0;
+ } else {
+ jj = (j < (Difference)size) ? j : (Difference)size;
+ }
+ if (jj < ii)
+ jj = ii;
+ } else {
+ // Required range: -1 <= i < size-1, -1 <= j < size-1, i >= j
+ if (i < -1) {
+ ii = -1;
+ } else if (i < (Difference) size) {
+ ii = i;
+ } else if (i >= (Difference)(size-1)) {
+ ii = (Difference)(size-1);
+ }
+ if (j < -1) {
+ jj = -1;
+ } else {
+ jj = (j < (Difference)size ) ? j : (Difference)(size-1);
+ }
+ if (ii < jj)
+ ii = jj;
+ }
+ }
+
+ template <class Sequence, class Difference>
+ inline typename Sequence::iterator
+ getpos(Sequence* self, Difference i) {
+ typename Sequence::iterator pos = self->begin();
+ std::advance(pos, check_index(i,self->size()));
+ return pos;
+ }
+
+ template <class Sequence, class Difference>
+ inline typename Sequence::const_iterator
+ cgetpos(const Sequence* self, Difference i) {
+ typename Sequence::const_iterator pos = self->begin();
+ std::advance(pos, check_index(i,self->size()));
+ return pos;
+ }
+
+ template <class Sequence>
+ inline void
+ erase(Sequence* seq, const typename Sequence::iterator& position) {
+ seq->erase(position);
+ }
+
+ template <class Sequence>
+ struct traits_reserve {
+ static void reserve(Sequence & /*seq*/, typename Sequence::size_type /*n*/) {
+ // This should be specialized for types that support reserve
+ }
+ };
+
+ template <class Sequence, class Difference>
+ inline Sequence*
+ getslice(const Sequence* self, Difference i, Difference j, Py_ssize_t step) {
+ typename Sequence::size_type size = self->size();
+ Difference ii = 0;
+ Difference jj = 0;
+ swig::slice_adjust(i, j, step, size, ii, jj);
+
+ if (step > 0) {
+ typename Sequence::const_iterator sb = self->begin();
+ typename Sequence::const_iterator se = self->begin();
+ std::advance(sb,ii);
+ std::advance(se,jj);
+ if (step == 1) {
+ return new Sequence(sb, se);
+ } else {
+ Sequence *sequence = new Sequence();
+ swig::traits_reserve<Sequence>::reserve(*sequence, (jj - ii + step - 1) / step);
+ typename Sequence::const_iterator it = sb;
+ while (it!=se) {
+ sequence->push_back(*it);
+ for (Py_ssize_t c=0; c<step && it!=se; ++c)
+ it++;
+ }
+ return sequence;
+ }
+ } else {
+ Sequence *sequence = new Sequence();
+ swig::traits_reserve<Sequence>::reserve(*sequence, (ii - jj - step - 1) / -step);
+ typename Sequence::const_reverse_iterator sb = self->rbegin();
+ typename Sequence::const_reverse_iterator se = self->rbegin();
+ std::advance(sb,size-ii-1);
+ std::advance(se,size-jj-1);
+ typename Sequence::const_reverse_iterator it = sb;
+ while (it!=se) {
+ sequence->push_back(*it);
+ for (Py_ssize_t c=0; c<-step && it!=se; ++c)
+ it++;
+ }
+ return sequence;
+ }
+ }
+
+ template <class Sequence, class Difference, class InputSeq>
+ inline void
+ setslice(Sequence* self, Difference i, Difference j, Py_ssize_t step, const InputSeq& is = InputSeq()) {
+ typename Sequence::size_type size = self->size();
+ Difference ii = 0;
+ Difference jj = 0;
+ swig::slice_adjust(i, j, step, size, ii, jj, true);
+ if (step > 0) {
+ if (step == 1) {
+ size_t ssize = jj - ii;
+ if (ssize <= is.size()) {
+ // expanding/staying the same size
+ swig::traits_reserve<Sequence>::reserve(*self, self->size() - ssize + is.size());
+ typename Sequence::iterator sb = self->begin();
+ typename InputSeq::const_iterator isit = is.begin();
+ std::advance(sb,ii);
+ std::advance(isit, jj - ii);
+ self->insert(std::copy(is.begin(), isit, sb), isit, is.end());
+ } else {
+ // shrinking
+ typename Sequence::iterator sb = self->begin();
+ typename Sequence::iterator se = self->begin();
+ std::advance(sb,ii);
+ std::advance(se,jj);
+ self->erase(sb,se);
+ sb = self->begin();
+ std::advance(sb,ii);
+ self->insert(sb, is.begin(), is.end());
+ }
+ } else {
+ size_t replacecount = (jj - ii + step - 1) / step;
+ if (is.size() != replacecount) {
+ char msg[1024];
+ PyOS_snprintf(msg, sizeof(msg), "attempt to assign sequence of size %lu to extended slice of size %lu", (unsigned long)is.size(), (unsigned long)replacecount);
+ throw std::invalid_argument(msg);
+ }
+ typename Sequence::const_iterator isit = is.begin();
+ typename Sequence::iterator it = self->begin();
+ std::advance(it,ii);
+ for (size_t rc=0; rc<replacecount && it != self->end(); ++rc) {
+ *it++ = *isit++;
+ for (Py_ssize_t c=0; c<(step-1) && it != self->end(); ++c)
+ it++;
+ }
+ }
+ } else {
+ size_t replacecount = (ii - jj - step - 1) / -step;
+ if (is.size() != replacecount) {
+ char msg[1024];
+ PyOS_snprintf(msg, sizeof(msg), "attempt to assign sequence of size %lu to extended slice of size %lu", (unsigned long)is.size(), (unsigned long)replacecount);
+ throw std::invalid_argument(msg);
+ }
+ typename Sequence::const_iterator isit = is.begin();
+ typename Sequence::reverse_iterator it = self->rbegin();
+ std::advance(it,size-ii-1);
+ for (size_t rc=0; rc<replacecount && it != self->rend(); ++rc) {
+ *it++ = *isit++;
+ for (Py_ssize_t c=0; c<(-step-1) && it != self->rend(); ++c)
+ it++;
+ }
+ }
+ }
+
+ template <class Sequence, class Difference>
+ inline void
+ delslice(Sequence* self, Difference i, Difference j, Py_ssize_t step) {
+ typename Sequence::size_type size = self->size();
+ Difference ii = 0;
+ Difference jj = 0;
+ swig::slice_adjust(i, j, step, size, ii, jj, true);
+ if (step > 0) {
+ typename Sequence::iterator sb = self->begin();
+ std::advance(sb,ii);
+ if (step == 1) {
+ typename Sequence::iterator se = self->begin();
+ std::advance(se,jj);
+ self->erase(sb,se);
+ } else {
+ typename Sequence::iterator it = sb;
+ size_t delcount = (jj - ii + step - 1) / step;
+ while (delcount) {
+ it = self->erase(it);
+ for (Py_ssize_t c=0; c<(step-1) && it != self->end(); ++c)
+ it++;
+ delcount--;
+ }
+ }
+ } else {
+ typename Sequence::reverse_iterator sb = self->rbegin();
+ std::advance(sb,size-ii-1);
+ typename Sequence::reverse_iterator it = sb;
+ size_t delcount = (ii - jj - step - 1) / -step;
+ while (delcount) {
+ it = typename Sequence::reverse_iterator(self->erase((++it).base()));
+ for (Py_ssize_t c=0; c<(-step-1) && it != self->rend(); ++c)
+ it++;
+ delcount--;
+ }
+ }
+ }
+}
+}
+
+%define %swig_sequence_iterator(Sequence...)
+ %swig_sequence_iterator_with_making_function(swig::make_output_iterator,Sequence...)
+%enddef
+
+%define %swig_sequence_forward_iterator(Sequence...)
+ %swig_sequence_iterator_with_making_function(swig::make_output_forward_iterator,Sequence...)
+%enddef
+
+%define %swig_sequence_iterator_with_making_function(Make_output_iterator,Sequence...)
+#if defined(SWIG_EXPORT_ITERATOR_METHODS)
+ class iterator;
+ class reverse_iterator;
+ class const_iterator;
+ class const_reverse_iterator;
+
+ %typemap(out,noblock=1,fragment="SwigPyIterator_T")
+ iterator, reverse_iterator, const_iterator, const_reverse_iterator {
+ $result = SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &)),
+ swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN);
+ }
+ %typemap(out,noblock=1,fragment="SwigPyIterator_T")
+ std::pair<iterator, iterator>, std::pair<const_iterator, const_iterator> {
+ $result = PyTuple_New(2);
+ PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first),
+ swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN));
+ PyTuple_SetItem($result,1,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).second),
+ swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN));
+ }
+
+ %fragment("SwigPyPairBoolOutputIterator","header",fragment=SWIG_From_frag(bool),fragment="SwigPyIterator_T") {}
+
+ %typemap(out,noblock=1,fragment="SwigPyPairBoolOutputIterator")
+ std::pair<iterator, bool>, std::pair<const_iterator, bool> {
+ $result = PyTuple_New(2);
+ PyTuple_SetItem($result,0,SWIG_NewPointerObj(Make_output_iterator(%static_cast($1,const $type &).first),
+ swig::SwigPyIterator::descriptor(),SWIG_POINTER_OWN));
+ PyTuple_SetItem($result,1,SWIG_From(bool)(%static_cast($1,const $type &).second));
+ }
+
+ %typemap(in,noblock=1,fragment="SwigPyIterator_T")
+ iterator(swig::SwigPyIterator *iter = 0, int res),
+ reverse_iterator(swig::SwigPyIterator *iter = 0, int res),
+ const_iterator(swig::SwigPyIterator *iter = 0, int res),
+ const_reverse_iterator(swig::SwigPyIterator *iter = 0, int res) {
+ res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::SwigPyIterator::descriptor(), 0);
+ if (!SWIG_IsOK(res) || !iter) {
+ %argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
+ } else {
+ swig::SwigPyIterator_T<$type > *iter_t = dynamic_cast<swig::SwigPyIterator_T<$type > *>(iter);
+ if (iter_t) {
+ $1 = iter_t->get_current();
+ } else {
+ %argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
+ }
+ }
+ }
+
+ %typecheck(%checkcode(ITERATOR),noblock=1,fragment="SwigPyIterator_T")
+ iterator, reverse_iterator, const_iterator, const_reverse_iterator {
+ swig::SwigPyIterator *iter = 0;
+ int res = SWIG_ConvertPtr($input, %as_voidptrptr(&iter), swig::SwigPyIterator::descriptor(), 0);
+ $1 = (SWIG_IsOK(res) && iter && (dynamic_cast<swig::SwigPyIterator_T<$type > *>(iter) != 0));
+ }
+
+ %fragment("SwigPyIterator_T");
+
+ %newobject iterator(PyObject **PYTHON_SELF);
+ %extend {
+ swig::SwigPyIterator* iterator(PyObject **PYTHON_SELF) {
+ return Make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "tp_iter", functype="getiterfunc") iterator;
+#else
+ %pythoncode %{def __iter__(self):
+ return self.iterator()%}
+#endif
+ }
+
+#endif //SWIG_EXPORT_ITERATOR_METHODS
+%enddef
+
+
+/**** The python container methods ****/
+
+%define %swig_container_methods(Container...)
+
+/* deprecated in Python 2 */
+#if 1
+ %newobject __getslice__;
+#endif
+ %newobject __getitem__(SWIGPY_SLICEOBJECT *slice);
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "nb_nonzero", functype="inquiry") __nonzero__;
+ %feature("python:slot", "sq_length", functype="lenfunc") __len__;
+#endif // SWIGPYTHON_BUILTIN
+
+ %extend {
+ bool __nonzero__() const {
+ return !(self->empty());
+ }
+
+ /* Alias for Python 3 compatibility */
+ bool __bool__() const {
+ return !(self->empty());
+ }
+
+ size_type __len__() const {
+ return self->size();
+ }
+
+ // Although __getitem__, front, back actually use a const value_type& return type, the typemaps below
+ // use non-const so that they can be easily overridden by users if necessary.
+ %typemap(ret, fragment="reference_container_owner", noblock=1) value_type& __getitem__, value_type& front, value_type& back {
+ (void)swig::container_owner<swig::traits<$*1_ltype>::category>::back_reference($result, $self);
+ }
+ }
+%enddef
+
+
+
+%define %swig_sequence_methods_common(Sequence...)
+ %swig_sequence_iterator(%arg(Sequence))
+ %swig_container_methods(%arg(Sequence))
+
+ %fragment("SwigPySequence_Base");
+
+#if defined(SWIGPYTHON_BUILTIN)
+ //%feature("python:slot", "sq_item", functype="ssizeargfunc") __getitem__;
+ //%feature("python:slot", "sq_slice", functype="ssizessizeargfunc") __getslice__;
+ //%feature("python:slot", "sq_ass_item", functype="ssizeobjargproc") __setitem__;
+ //%feature("python:slot", "sq_ass_slice", functype="ssizessizeobjargproc") __setslice__;
+ %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
+ %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__;
+#endif // SWIGPYTHON_BUILTIN
+
+ %extend {
+ /* typemap for slice object support */
+ %typemap(in) SWIGPY_SLICEOBJECT* {
+ if (!PySlice_Check($input)) {
+ %argument_fail(SWIG_TypeError, "$type", $symname, $argnum);
+ }
+ $1 = (SWIGPY_SLICEOBJECT *) $input;
+ }
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) SWIGPY_SLICEOBJECT* {
+ $1 = PySlice_Check($input);
+ }
+
+/* deprecated in Python 2 */
+#if 1
+ Sequence* __getslice__(difference_type i, difference_type j) throw (std::out_of_range, std::invalid_argument) {
+ return swig::getslice(self, i, j, 1);
+ }
+
+ void __setslice__(difference_type i, difference_type j) throw (std::out_of_range, std::invalid_argument) {
+ swig::setslice(self, i, j, 1, Sequence());
+ }
+
+ void __setslice__(difference_type i, difference_type j, const Sequence& v) throw (std::out_of_range, std::invalid_argument) {
+ swig::setslice(self, i, j, 1, v);
+ }
+
+ void __delslice__(difference_type i, difference_type j) throw (std::out_of_range, std::invalid_argument) {
+ swig::delslice(self, i, j, 1);
+ }
+#endif
+
+ void __delitem__(difference_type i) throw (std::out_of_range, std::invalid_argument) {
+ swig::erase(self, swig::getpos(self, i));
+ }
+
+ /* Overloaded methods for Python 3 compatibility
+ * (Also useful in Python 2.x)
+ */
+ Sequence* __getitem__(SWIGPY_SLICEOBJECT *slice) throw (std::out_of_range, std::invalid_argument) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return NULL;
+ }
+ PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step);
+ Sequence::difference_type id = i;
+ Sequence::difference_type jd = j;
+ return swig::getslice(self, id, jd, step);
+ }
+
+ void __setitem__(SWIGPY_SLICEOBJECT *slice, const Sequence& v) throw (std::out_of_range, std::invalid_argument) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return;
+ }
+ PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step);
+ Sequence::difference_type id = i;
+ Sequence::difference_type jd = j;
+ swig::setslice(self, id, jd, step, v);
+ }
+
+ void __setitem__(SWIGPY_SLICEOBJECT *slice) throw (std::out_of_range, std::invalid_argument) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return;
+ }
+ PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step);
+ Sequence::difference_type id = i;
+ Sequence::difference_type jd = j;
+ swig::delslice(self, id, jd, step);
+ }
+
+ void __delitem__(SWIGPY_SLICEOBJECT *slice) throw (std::out_of_range, std::invalid_argument) {
+ Py_ssize_t i, j, step;
+ if( !PySlice_Check(slice) ) {
+ SWIG_Error(SWIG_TypeError, "Slice object expected.");
+ return;
+ }
+ PySlice_GetIndices(slice, (Py_ssize_t)self->size(), &i, &j, &step);
+ Sequence::difference_type id = i;
+ Sequence::difference_type jd = j;
+ swig::delslice(self, id, jd, step);
+ }
+
+ }
+%enddef
+
+%define %swig_sequence_methods_non_resizable(Sequence...)
+ %swig_sequence_methods_common(%arg(Sequence))
+ %extend {
+ const value_type& __getitem__(difference_type i) const throw (std::out_of_range) {
+ return *(swig::cgetpos(self, i));
+ }
+
+ void __setitem__(difference_type i, const value_type& x) throw (std::out_of_range) {
+ *(swig::getpos(self,i)) = x;
+ }
+
+#if defined(SWIGPYTHON_BUILTIN)
+ // This will be called through the mp_ass_subscript slot to delete an entry.
+ void __setitem__(difference_type i) throw (std::out_of_range, std::invalid_argument) {
+ swig::erase(self, swig::getpos(self, i));
+ }
+#endif
+
+ }
+%enddef
+
+%define %swig_sequence_methods(Sequence...)
+ %swig_sequence_methods_non_resizable(%arg(Sequence))
+ %extend {
+ value_type pop() throw (std::out_of_range) {
+ if (self->size() == 0)
+ throw std::out_of_range("pop from empty container");
+ Sequence::value_type x = self->back();
+ self->pop_back();
+ return x;
+ }
+
+ void append(const value_type& x) {
+ self->push_back(x);
+ }
+ }
+%enddef
+
+%define %swig_sequence_methods_non_resizable_val(Sequence...)
+ %swig_sequence_methods_common(%arg(Sequence))
+ %extend {
+ value_type __getitem__(difference_type i) throw (std::out_of_range) {
+ return *(swig::cgetpos(self, i));
+ }
+
+ void __setitem__(difference_type i, value_type x) throw (std::out_of_range) {
+ *(swig::getpos(self,i)) = x;
+ }
+
+#if defined(SWIGPYTHON_BUILTIN)
+ // This will be called through the mp_ass_subscript slot to delete an entry.
+ void __setitem__(difference_type i) throw (std::out_of_range, std::invalid_argument) {
+ swig::erase(self, swig::getpos(self, i));
+ }
+#endif
+ }
+%enddef
+
+%define %swig_sequence_methods_val(Sequence...)
+ %swig_sequence_methods_non_resizable_val(%arg(Sequence))
+ %extend {
+ value_type pop() throw (std::out_of_range) {
+ if (self->size() == 0)
+ throw std::out_of_range("pop from empty container");
+ Sequence::value_type x = self->back();
+ self->pop_back();
+ return x;
+ }
+
+ void append(value_type x) {
+ self->push_back(x);
+ }
+ }
+%enddef
+
+
+
+//
+// Common fragments
+//
+
+%fragment("StdSequenceTraits","header",
+ fragment="StdTraits",
+ fragment="SwigPySequence_Base")
+{
+namespace swig {
+ template <class Seq, class T = typename Seq::value_type >
+ struct IteratorProtocol {
+ static void assign(PyObject *obj, Seq *seq) {
+ SwigVar_PyObject iter = PyObject_GetIter(obj);
+ if (iter) {
+ SwigVar_PyObject item = PyIter_Next(iter);
+ while (item) {
+ seq->insert(seq->end(), swig::as<T>(item));
+ item = PyIter_Next(iter);
+ }
+ }
+ }
+
+ static bool check(PyObject *obj) {
+ bool ret = false;
+ SwigVar_PyObject iter = PyObject_GetIter(obj);
+ if (iter) {
+ SwigVar_PyObject item = PyIter_Next(iter);
+ ret = true;
+ while (item) {
+ ret = swig::check<T>(item);
+ item = ret ? PyIter_Next(iter) : 0;
+ }
+ }
+ return ret;
+ }
+ };
+
+ template <class Seq, class T = typename Seq::value_type >
+ struct traits_asptr_stdseq {
+ typedef Seq sequence;
+ typedef T value_type;
+
+ static bool is_iterable(PyObject *obj) {
+ SwigVar_PyObject iter = PyObject_GetIter(obj);
+ PyErr_Clear();
+ return iter != 0;
+ }
+
+ static int asptr(PyObject *obj, sequence **seq) {
+ int ret = SWIG_ERROR;
+ if (obj == Py_None || SWIG_Python_GetSwigThis(obj)) {
+ sequence *p;
+ swig_type_info *descriptor = swig::type_info<sequence>();
+ if (descriptor && SWIG_IsOK(::SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0))) {
+ if (seq) *seq = p;
+ return SWIG_OLDOBJ;
+ }
+ } else if (is_iterable(obj)) {
+ try {
+ if (seq) {
+ *seq = new sequence();
+ IteratorProtocol<Seq, T>::assign(obj, *seq);
+ if (!PyErr_Occurred())
+ return SWIG_NEWOBJ;
+ } else {
+ return IteratorProtocol<Seq, T>::check(obj) ? SWIG_OK : SWIG_ERROR;
+ }
+ } catch (std::exception& e) {
+ if (seq && !PyErr_Occurred())
+ PyErr_SetString(PyExc_TypeError, e.what());
+ }
+ if (seq)
+ delete *seq;
+ return SWIG_ERROR;
+ }
+ return ret;
+ }
+ };
+
+ template <class Seq, class T = typename Seq::value_type >
+ struct traits_from_stdseq {
+ typedef Seq sequence;
+ typedef T value_type;
+ typedef typename Seq::size_type size_type;
+ typedef typename sequence::const_iterator const_iterator;
+
+ static PyObject *from(const sequence& seq) {
+%#ifdef SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS
+ swig_type_info *desc = swig::type_info<sequence>();
+ if (desc && desc->clientdata) {
+ return SWIG_InternalNewPointerObj(new sequence(seq), desc, SWIG_POINTER_OWN);
+ }
+%#endif
+ size_type size = seq.size();
+ if (size <= (size_type)INT_MAX) {
+ PyObject *obj = PyTuple_New((Py_ssize_t)size);
+ Py_ssize_t i = 0;
+ for (const_iterator it = seq.begin(); it != seq.end(); ++it, ++i) {
+ PyTuple_SetItem(obj,i,swig::from<value_type>(*it));
+ }
+ return obj;
+ } else {
+ PyErr_SetString(PyExc_OverflowError,"sequence size not valid in python");
+ return NULL;
+ }
+ }
+ };
+}
+}
diff --git a/contrib/tools/swig/Lib/python/pydocs.swg b/contrib/tools/swig/Lib/python/pydocs.swg
new file mode 100644
index 00000000000..5a25423d4ca
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pydocs.swg
@@ -0,0 +1,45 @@
+
+// Documentation for use with the autodoc feature.
+
+#ifdef SWIG_DOC_DOXYGEN_STYLE
+%typemap(doc) SWIGTYPE "@param $1_name $1_type"
+%typemap(doc) SWIGTYPE * "@param $1_name $1_type"
+%typemap(doc) const SWIGTYPE & "@param $1_name $1_type"
+%typemap(doc) const SWIGTYPE && "@param $1_name $1_type"
+%typemap(doc) enum SWIGTYPE "@param $1_name enum $1_type"
+
+%typemap(doc) SWIGTYPE *INOUT, SWIGTYPE &INOUT "@param $1_name $1_type (input/output)"
+%typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "@param $1_name $1_type (input)"
+%typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "@param $1_name $1_type (output)"
+#else
+%typemap(doc) SWIGTYPE "$1_name: $1_type"
+%typemap(doc) SWIGTYPE * "$1_name: $1_type"
+%typemap(doc) const SWIGTYPE & "$1_name: $1_type"
+%typemap(doc) const SWIGTYPE && "$1_name: $1_type"
+%typemap(doc) enum SWIGTYPE "$1_name: enum $1_type"
+
+%typemap(doc) SWIGTYPE *INOUT, SWIGTYPE &INOUT "$1_name: $1_type (input/output)"
+%typemap(doc) SWIGTYPE *INPUT, SWIGTYPE &INPUT "$1_name: $1_type (input)"
+%typemap(doc) SWIGTYPE *OUTPUT, SWIGTYPE &OUTPUT "$1_name: $1_type (output)"
+#endif
+
+
+// Types to use in Python documentation for the parameters of the given C++ type.
+%typemap(doctype) bool "boolean"
+
+%define int_doctype_for_cppint_type(cppint_type)
+ %typemap(doctype) cppint_type, unsigned cppint_type "int"
+%enddef
+%formacro(int_doctype_for_cppint_type, short, int, long, long long)
+
+%typemap(doctype) size_t "int"
+
+%typemap(doctype) enum SWIGTYPE "int"
+
+%typemap(doctype) float, double, long double "float"
+
+%typemap(doctype) char*, std::string "string"
+
+%typemap(doctype) SWIGTYPE "$1_basetype"
+%typemap(doctype) SWIGTYPE * "$typemap(doctype, $*1_ltype)"
+%typemap(doctype) SWIGTYPE & "$typemap(doctype, $*1_ltype)"
diff --git a/contrib/tools/swig/Lib/python/pyerrors.swg b/contrib/tools/swig/Lib/python/pyerrors.swg
new file mode 100644
index 00000000000..e7fe688d193
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyerrors.swg
@@ -0,0 +1,112 @@
+/* -----------------------------------------------------------------------------
+ * error manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIME PyObject*
+SWIG_Python_ErrorType(int code) {
+ PyObject* type = 0;
+ switch(code) {
+ case SWIG_MemoryError:
+ type = PyExc_MemoryError;
+ break;
+ case SWIG_IOError:
+ type = PyExc_IOError;
+ break;
+ case SWIG_RuntimeError:
+ type = PyExc_RuntimeError;
+ break;
+ case SWIG_IndexError:
+ type = PyExc_IndexError;
+ break;
+ case SWIG_TypeError:
+ type = PyExc_TypeError;
+ break;
+ case SWIG_DivisionByZero:
+ type = PyExc_ZeroDivisionError;
+ break;
+ case SWIG_OverflowError:
+ type = PyExc_OverflowError;
+ break;
+ case SWIG_SyntaxError:
+ type = PyExc_SyntaxError;
+ break;
+ case SWIG_ValueError:
+ type = PyExc_ValueError;
+ break;
+ case SWIG_SystemError:
+ type = PyExc_SystemError;
+ break;
+ case SWIG_AttributeError:
+ type = PyExc_AttributeError;
+ break;
+ case SWIG_NullReferenceError:
+ type = PyExc_TypeError;
+ break;
+ default:
+ type = PyExc_RuntimeError;
+ }
+ return type;
+}
+
+
+SWIGRUNTIME void
+SWIG_Python_AddErrorMsg(const char* mesg)
+{
+ PyObject *type = 0;
+ PyObject *value = 0;
+ PyObject *traceback = 0;
+
+ if (PyErr_Occurred())
+ PyErr_Fetch(&type, &value, &traceback);
+ if (value) {
+ PyObject *old_str = PyObject_Str(value);
+ PyObject *bytes = NULL;
+ const char *tmp = SWIG_PyUnicode_AsUTF8AndSize(old_str, NULL, &bytes);
+ PyErr_Clear();
+ SWIG_Py_XINCREF(type);
+ if (tmp)
+ PyErr_Format(type, "%s %s", tmp, mesg);
+ else
+ PyErr_Format(type, "%s", mesg);
+ SWIG_Py_XDECREF(bytes);
+ SWIG_Py_DECREF(old_str);
+ SWIG_Py_DECREF(value);
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, mesg);
+ }
+}
+
+SWIGRUNTIME int
+SWIG_Python_TypeErrorOccurred(PyObject *obj)
+{
+ PyObject *error;
+ if (obj)
+ return 0;
+ error = PyErr_Occurred();
+ return error && PyErr_GivenExceptionMatches(error, PyExc_TypeError);
+}
+
+SWIGRUNTIME void
+SWIG_Python_RaiseOrModifyTypeError(const char *message)
+{
+ if (SWIG_Python_TypeErrorOccurred(NULL)) {
+ /* Use existing TypeError to preserve stacktrace and enhance with given message */
+ PyObject *newvalue;
+ PyObject *type = NULL, *value = NULL, *traceback = NULL;
+ PyErr_Fetch(&type, &value, &traceback);
+#if PY_VERSION_HEX >= 0x03000000
+ newvalue = PyUnicode_FromFormat("%S\nAdditional information:\n%s", value, message);
+#else
+ newvalue = PyString_FromFormat("%s\nAdditional information:\n%s", PyString_AsString(value), message);
+#endif
+ if (newvalue) {
+ SWIG_Py_XDECREF(value);
+ PyErr_Restore(type, newvalue, traceback);
+ } else {
+ PyErr_Restore(type, value, traceback);
+ }
+ } else {
+ /* Raise TypeError using given message */
+ PyErr_SetString(PyExc_TypeError, message);
+ }
+}
diff --git a/contrib/tools/swig/Lib/python/pyfragments.swg b/contrib/tools/swig/Lib/python/pyfragments.swg
new file mode 100644
index 00000000000..535a45bdf2d
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyfragments.swg
@@ -0,0 +1,23 @@
+/*
+
+ Create a file with this name, 'pyfragments.swg', in your working
+ directory and add all the %fragments you want to take precedence
+ over the default ones defined by swig.
+
+ For example, if you add:
+
+ %fragment(SWIG_AsVal_frag(int),"header") {
+ SWIGINTERNINLINE int
+ SWIG_AsVal(int)(PyObject *obj, int *val)
+ {
+ <your code here>;
+ }
+ }
+
+ this will replace the code used to retrieve an integer value for all
+ the typemaps that need it, including:
+
+ int, std::vector<int>, std::list<std::pair<int,int> >, etc.
+
+
+*/
diff --git a/contrib/tools/swig/Lib/python/pyhead.swg b/contrib/tools/swig/Lib/python/pyhead.swg
new file mode 100644
index 00000000000..938224123f0
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyhead.swg
@@ -0,0 +1,105 @@
+/* Compatibility macros for Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+
+#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type)
+#define PyInt_Check(x) PyLong_Check(x)
+#define PyInt_AsLong(x) PyLong_AsLong(x)
+#define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyInt_FromSize_t(x) PyLong_FromSize_t(x)
+#define PyString_Check(name) PyBytes_Check(name)
+#define PyString_FromString(x) PyUnicode_FromString(x)
+#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args)
+#define PyString_AsString(str) PyBytes_AsString(str)
+#define PyString_Size(str) PyBytes_Size(str)
+#define PyString_InternFromString(key) PyUnicode_InternFromString(key)
+#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE
+#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x)
+
+#endif
+
+/* SWIG APIs for compatibility of both Python 2 & 3 */
+
+#if PY_VERSION_HEX >= 0x03000000
+# define SWIG_Python_str_FromFormat PyUnicode_FromFormat
+#else
+# define SWIG_Python_str_FromFormat PyString_FromFormat
+#endif
+
+
+/* Wrapper around PyUnicode_AsUTF8AndSize - call Py_XDECREF on the returned pbytes when finished with the returned string */
+SWIGINTERN const char *
+SWIG_PyUnicode_AsUTF8AndSize(PyObject *str, Py_ssize_t *psize, PyObject **pbytes)
+{
+#if PY_VERSION_HEX >= 0x03030000
+# if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
+ *pbytes = NULL;
+ return PyUnicode_AsUTF8AndSize(str, psize);
+# else
+ const char *chars;
+ *pbytes = PyUnicode_AsUTF8String(str);
+ chars = *pbytes ? PyBytes_AsString(*pbytes) : NULL;
+ if (chars && psize)
+ *psize = PyBytes_Size(*pbytes);
+ return chars;
+# endif
+#else
+ char *chars = NULL;
+ *pbytes = NULL;
+ PyString_AsStringAndSize(str, &chars, psize);
+ return chars;
+#endif
+}
+
+SWIGINTERN PyObject*
+SWIG_Python_str_FromChar(const char *c)
+{
+#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_FromString(c);
+#else
+ return PyString_FromString(c);
+#endif
+}
+
+#define SWIG_RUNTIME_MODULE "swig_runtime_data" SWIG_RUNTIME_VERSION
+
+/* SWIGPY_USE_CAPSULE is no longer used within SWIG itself, but some user interface files check for it. */
+# define SWIGPY_USE_CAPSULE
+#ifdef SWIGPYTHON_BUILTIN
+# define SWIGPY_CAPSULE_ATTR_NAME "type_pointer_capsule_builtin" SWIG_TYPE_TABLE_NAME
+#else
+# define SWIGPY_CAPSULE_ATTR_NAME "type_pointer_capsule" SWIG_TYPE_TABLE_NAME
+#endif
+#define SWIGPY_CAPSULE_NAME SWIG_RUNTIME_MODULE "." SWIGPY_CAPSULE_ATTR_NAME
+
+#if PY_VERSION_HEX < 0x03020000
+#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name)
+#define Py_hash_t long
+#endif
+
+#ifdef Py_LIMITED_API
+# define PyTuple_GET_ITEM PyTuple_GetItem
+/* Note that PyTuple_SetItem() has different semantics from PyTuple_SET_ITEM as it decref's the original tuple item, so in general they cannot be used
+ interchangeably. However in SWIG-generated code PyTuple_SET_ITEM is only used with newly initialized tuples without any items and for them this does work. */
+# define PyTuple_SET_ITEM PyTuple_SetItem
+# define PyTuple_GET_SIZE PyTuple_Size
+# define PyCFunction_GET_FLAGS PyCFunction_GetFlags
+# define PyCFunction_GET_FUNCTION PyCFunction_GetFunction
+# define PyCFunction_GET_SELF PyCFunction_GetSelf
+# define PyList_GET_ITEM PyList_GetItem
+# define PyList_SET_ITEM PyList_SetItem
+# define PySliceObject PyObject
+#endif
+
+/* Increment and Decrement wrappers - for portability when using the stable abi and for performance otherwise */
+#ifdef Py_LIMITED_API
+# define SWIG_Py_INCREF Py_IncRef
+# define SWIG_Py_XINCREF Py_IncRef
+# define SWIG_Py_DECREF Py_DecRef
+# define SWIG_Py_XDECREF Py_DecRef
+#else
+# define SWIG_Py_INCREF Py_INCREF
+# define SWIG_Py_XINCREF Py_XINCREF
+# define SWIG_Py_DECREF Py_DECREF
+# define SWIG_Py_XDECREF Py_XDECREF
+#endif
diff --git a/contrib/tools/swig/Lib/python/pyinit.swg b/contrib/tools/swig/Lib/python/pyinit.swg
new file mode 100644
index 00000000000..5070762ebd0
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyinit.swg
@@ -0,0 +1,326 @@
+/* ------------------------------------------------------------
+ * The start of the Python initialization function
+ * ------------------------------------------------------------ */
+
+%insert(init) "swiginit.swg"
+
+#if defined(SWIGPYTHON_BUILTIN)
+%fragment("<stddef.h>"); // For offsetof
+#endif
+
+#if defined SWIGPYTHON_FASTPROXY && !defined SWIGPYTHON_BUILTIN
+
+%insert(runtime) %{
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Method creation and docstring support functions */
+
+SWIGINTERN PyMethodDef *SWIG_PythonGetProxyDoc(const char *name);
+SWIGINTERN PyObject *SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func);
+SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func);
+
+#ifdef __cplusplus
+}
+#endif
+%}
+
+#endif
+
+%init %{
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -----------------------------------------------------------------------------
+ * constants/methods manipulation
+ * ----------------------------------------------------------------------------- */
+
+/* Install Constants */
+SWIGINTERN void
+SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) {
+ PyObject *obj = 0;
+ size_t i;
+ for (i = 0; constants[i].type; ++i) {
+ switch(constants[i].type) {
+ case SWIG_PY_POINTER:
+ obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+ break;
+ case SWIG_PY_BINARY:
+ obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
+ break;
+ default:
+ obj = 0;
+ break;
+ }
+ if (obj) {
+ PyDict_SetItemString(d, constants[i].name, obj);
+ SWIG_Py_DECREF(obj);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Patch %callback methods' docstrings to hold the callback ptrs
+ * -----------------------------------------------------------------------------*/
+
+SWIGINTERN void
+SWIG_Python_FixMethods(PyMethodDef *methods, const swig_const_info *const_table, swig_type_info **types, swig_type_info **types_initial) {
+ size_t i;
+ for (i = 0; methods[i].ml_name; ++i) {
+ const char *c = methods[i].ml_doc;
+ if (!c) continue;
+ c = strstr(c, "swig_ptr: ");
+ if (c) {
+ int j;
+ const swig_const_info *ci = 0;
+ const char *name = c + 10;
+ for (j = 0; const_table[j].type; ++j) {
+ if (strncmp(const_table[j].name, name,
+ strlen(const_table[j].name)) == 0) {
+ ci = &(const_table[j]);
+ break;
+ }
+ }
+ if (ci) {
+ void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+ if (ptr) {
+ size_t shift = (ci->ptype) - types;
+ swig_type_info *ty = types_initial[shift];
+ size_t ldoc = (c - methods[i].ml_doc);
+ size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+ char *ndoc = (char*)malloc(ldoc + lptr + 10);
+ if (ndoc) {
+ char *buff = ndoc;
+ memcpy(buff, methods[i].ml_doc, ldoc);
+ buff += ldoc;
+ memcpy(buff, "swig_ptr: ", 10);
+ buff += 10;
+ SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
+ methods[i].ml_doc = ndoc;
+ }
+ }
+ }
+ }
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+%}
+
+#if defined SWIGPYTHON_FASTPROXY && !defined SWIGPYTHON_BUILTIN
+
+%init %{
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Method creation and docstring support functions
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * Function to find the method definition with the correct docstring for the
+ * proxy module as opposed to the low-level API
+ * ----------------------------------------------------------------------------- */
+
+SWIGINTERN PyMethodDef *SWIG_PythonGetProxyDoc(const char *name) {
+ /* Find the function in the modified method table */
+ size_t offset = 0;
+ int found = 0;
+ while (SwigMethods_proxydocs[offset].ml_meth != NULL) {
+ if (strcmp(SwigMethods_proxydocs[offset].ml_name, name) == 0) {
+ found = 1;
+ break;
+ }
+ offset++;
+ }
+ /* Use the copy with the modified docstring if available */
+ return found ? &SwigMethods_proxydocs[offset] : NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper of PyInstanceMethod_New() used in Python 3
+ * It is exported to the generated module, used for -fastproxy
+ * ----------------------------------------------------------------------------- */
+
+SWIGINTERN PyObject *SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) {
+ if (PyCFunction_Check(func)) {
+ PyCFunctionObject *funcobj = (PyCFunctionObject *)func;
+ PyMethodDef *ml = SWIG_PythonGetProxyDoc(funcobj->m_ml->ml_name);
+ if (ml)
+ func = PyCFunction_NewEx(ml, funcobj->m_self, funcobj->m_module);
+ }
+#if PY_VERSION_HEX >= 0x03000000
+ return PyInstanceMethod_New(func);
+#else
+ return PyMethod_New(func, NULL, NULL);
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper of PyStaticMethod_New()
+ * It is exported to the generated module, used for -fastproxy
+ * ----------------------------------------------------------------------------- */
+
+SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) {
+ if (PyCFunction_Check(func)) {
+ PyCFunctionObject *funcobj = (PyCFunctionObject *)func;
+ PyMethodDef *ml = SWIG_PythonGetProxyDoc(funcobj->m_ml->ml_name);
+ if (ml)
+ func = PyCFunction_NewEx(ml, funcobj->m_self, funcobj->m_module);
+ }
+ return PyStaticMethod_New(func);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+%}
+
+#endif
+
+%init %{
+
+/* -----------------------------------------------------------------------------*
+ * Partial Init method
+ * -----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+SWIGEXPORT
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject*
+#else
+ void
+#endif
+SWIG_init(void) {
+ PyObject *m, *d, *md, *globals;
+
+#if PY_VERSION_HEX >= 0x03000000
+ static struct PyModuleDef SWIG_module = {
+ PyModuleDef_HEAD_INIT,
+ SWIG_name,
+ NULL,
+ -1,
+ SwigMethods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+#endif
+
+#if defined(SWIGPYTHON_BUILTIN)
+ static SwigPyClientData SwigPyObject_clientdata = {0, 0, 0, 0, 0, 0, 0};
+ static PyGetSetDef this_getset_def = {
+ (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL
+ };
+ static SwigPyGetSet thisown_getset_closure = {
+ SwigPyObject_own,
+ SwigPyObject_own
+ };
+ static PyGetSetDef thisown_getset_def = {
+ (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure
+ };
+ PyTypeObject *builtin_pytype;
+ int builtin_base_count;
+ swig_type_info *builtin_basetype;
+ PyObject *tuple;
+ PyGetSetDescrObject *static_getset;
+ PyTypeObject *metatype;
+ PyTypeObject *swigpyobject;
+ SwigPyClientData *cd;
+ PyObject *public_interface, *public_symbol;
+ PyObject *this_descr;
+ PyObject *thisown_descr;
+ PyObject *self = 0;
+ int i;
+
+ (void)builtin_pytype;
+ (void)builtin_base_count;
+ (void)builtin_basetype;
+ (void)tuple;
+ (void)static_getset;
+ (void)self;
+
+ /* Metaclass is used to implement static member variables */
+ metatype = SwigPyObjectType();
+ assert(metatype);
+#endif
+
+ (void)globals;
+
+ /* Create singletons now to avoid potential deadlocks with multi-threaded usage after module initialization */
+ SWIG_runtime_data_module();
+ SWIG_This();
+ SWIG_Python_TypeCache();
+ SwigPyPacked_type();
+#ifndef SWIGPYTHON_BUILTIN
+ SwigPyObject_type();
+#endif
+
+ /* Fix SwigMethods to carry the callback ptrs when needed */
+ SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
+
+#if PY_VERSION_HEX >= 0x03000000
+ m = PyModule_Create(&SWIG_module);
+#else
+ m = Py_InitModule(SWIG_name, SwigMethods);
+#endif
+
+ md = d = PyModule_GetDict(m);
+ (void)md;
+
+ SWIG_InitializeModule(0);
+
+#ifdef SWIGPYTHON_BUILTIN
+ swigpyobject = SwigPyObject_TypeOnce();
+
+ SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject");
+ assert(SwigPyObject_stype);
+ cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+ if (!cd) {
+ SwigPyObject_stype->clientdata = &SwigPyObject_clientdata;
+ SwigPyObject_clientdata.pytype = swigpyobject;
+ } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) {
+ PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules.");
+# if PY_VERSION_HEX >= 0x03000000
+ return NULL;
+# else
+ return;
+# endif
+ }
+
+ /* All objects have a 'this' attribute */
+ this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def);
+ (void)this_descr;
+
+ /* All objects have a 'thisown' attribute */
+ thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def);
+ (void)thisown_descr;
+
+ public_interface = PyList_New(0);
+ public_symbol = 0;
+ (void)public_symbol;
+
+ PyDict_SetItemString(md, "__all__", public_interface);
+ SWIG_Py_DECREF(public_interface);
+ for (i = 0; SwigMethods[i].ml_name != NULL; ++i)
+ SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name);
+ for (i = 0; swig_const_table[i].name != 0; ++i)
+ SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name);
+#endif
+
+ SWIG_InstallConstants(d,swig_const_table);
+%}
+
diff --git a/contrib/tools/swig/Lib/python/pyiterators.swg b/contrib/tools/swig/Lib/python/pyiterators.swg
new file mode 100644
index 00000000000..53f22b9fe03
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyiterators.swg
@@ -0,0 +1,453 @@
+/* -----------------------------------------------------------------------------
+ * pyiterators.swg
+ *
+ * Implement a python 'output' iterator for Python 2.2 or higher.
+ *
+ * Users can derive form the SwigPyIterator to implement their
+ * own iterators. As an example (real one since we use it for STL/STD
+ * containers), the template SwigPyIterator_T does the
+ * implementation for generic C++ iterators.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+
+%fragment("SwigPyIterator","header",fragment="<stddef.h>") {
+namespace swig {
+ struct stop_iteration {
+ };
+
+ struct SwigPyIterator {
+ private:
+ SwigPtr_PyObject _seq;
+
+ protected:
+ SwigPyIterator(PyObject *seq) : _seq(seq)
+ {
+ }
+
+ public:
+ virtual ~SwigPyIterator() {}
+
+ // Access iterator method, required by Python
+ virtual PyObject *value() const = 0;
+
+ // Forward iterator method, required by Python
+ virtual SwigPyIterator *incr(size_t n = 1) = 0;
+
+ // Backward iterator method, very common in C++, but not required in Python
+ virtual SwigPyIterator *decr(size_t /*n*/ = 1)
+ {
+ throw stop_iteration();
+ }
+
+ // Random access iterator methods, but not required in Python
+ virtual ptrdiff_t distance(const SwigPyIterator &/*x*/) const
+ {
+ throw std::invalid_argument("operation not supported");
+ }
+
+ virtual bool equal (const SwigPyIterator &/*x*/) const
+ {
+ throw std::invalid_argument("operation not supported");
+ }
+
+ // C++ common/needed methods
+ virtual SwigPyIterator *copy() const = 0;
+
+ PyObject *next()
+ {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads
+ PyObject *obj = value();
+ incr();
+ SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads
+ return obj;
+ }
+
+ /* Make an alias for Python 3.x */
+ PyObject *__next__()
+ {
+ return next();
+ }
+
+ PyObject *previous()
+ {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK; // disable threads
+ decr();
+ PyObject *obj = value();
+ SWIG_PYTHON_THREAD_END_BLOCK; // re-enable threads
+ return obj;
+ }
+
+ SwigPyIterator *advance(ptrdiff_t n)
+ {
+ return (n > 0) ? incr(n) : decr(-n);
+ }
+
+ bool operator == (const SwigPyIterator& x) const
+ {
+ return equal(x);
+ }
+
+ bool operator != (const SwigPyIterator& x) const
+ {
+ return ! operator==(x);
+ }
+
+ SwigPyIterator& operator += (ptrdiff_t n)
+ {
+ return *advance(n);
+ }
+
+ SwigPyIterator& operator -= (ptrdiff_t n)
+ {
+ return *advance(-n);
+ }
+
+ SwigPyIterator* operator + (ptrdiff_t n) const
+ {
+ return copy()->advance(n);
+ }
+
+ SwigPyIterator* operator - (ptrdiff_t n) const
+ {
+ return copy()->advance(-n);
+ }
+
+ ptrdiff_t operator - (const SwigPyIterator& x) const
+ {
+ return x.distance(*this);
+ }
+
+ static swig_type_info* descriptor() {
+ static swig_type_info* desc = SWIG_TypeQuery("swig::SwigPyIterator *");
+ return desc;
+ }
+ };
+
+%#if defined(SWIGPYTHON_BUILTIN)
+ inline PyObject* make_output_iterator_builtin (PyObject *pyself)
+ {
+ SWIG_Py_INCREF(pyself);
+ return pyself;
+ }
+%#endif
+}
+}
+
+%fragment("SwigPyIterator_T","header",fragment="<stddef.h>",fragment="SwigPyIterator",fragment="StdTraits",fragment="StdIteratorTraits") {
+namespace swig {
+ template<typename OutIterator>
+ class SwigPyIterator_T : public SwigPyIterator
+ {
+ public:
+ typedef OutIterator out_iterator;
+ typedef typename std::iterator_traits<out_iterator>::value_type value_type;
+ typedef SwigPyIterator_T<out_iterator> self_type;
+
+ SwigPyIterator_T(out_iterator curr, PyObject *seq)
+ : SwigPyIterator(seq), current(curr)
+ {
+ }
+
+ const out_iterator& get_current() const
+ {
+ return current;
+ }
+
+
+ bool equal (const SwigPyIterator &iter) const
+ {
+ const self_type *iters = dynamic_cast<const self_type *>(&iter);
+ if (iters) {
+ return (current == iters->get_current());
+ } else {
+ throw std::invalid_argument("bad iterator type");
+ }
+ }
+
+ ptrdiff_t distance(const SwigPyIterator &iter) const
+ {
+ const self_type *iters = dynamic_cast<const self_type *>(&iter);
+ if (iters) {
+ return std::distance(current, iters->get_current());
+ } else {
+ throw std::invalid_argument("bad iterator type");
+ }
+ }
+
+ protected:
+ out_iterator current;
+ };
+
+ template <class ValueType>
+ struct from_oper
+ {
+ typedef const ValueType& argument_type;
+ typedef PyObject *result_type;
+ result_type operator()(argument_type v) const
+ {
+ return swig::from(v);
+ }
+ };
+
+ template<typename OutIterator,
+ typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
+ typename FromOper = from_oper<ValueType> >
+ class SwigPyForwardIteratorOpen_T : public SwigPyIterator_T<OutIterator>
+ {
+ public:
+ FromOper from;
+ typedef OutIterator out_iterator;
+ typedef ValueType value_type;
+ typedef SwigPyIterator_T<out_iterator> base;
+ typedef SwigPyForwardIteratorOpen_T<OutIterator, ValueType, FromOper> self_type;
+
+ SwigPyForwardIteratorOpen_T(out_iterator curr, PyObject *seq)
+ : SwigPyIterator_T<OutIterator>(curr, seq)
+ {
+ }
+
+ PyObject *value() const {
+ return from(static_cast<const value_type&>(*(base::current)));
+ }
+
+ SwigPyIterator *copy() const
+ {
+ return new self_type(*this);
+ }
+
+ SwigPyIterator *incr(size_t n = 1)
+ {
+ while (n--) {
+ ++base::current;
+ }
+ return this;
+ }
+
+ };
+
+ template<typename OutIterator,
+ typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
+ typename FromOper = from_oper<ValueType> >
+ class SwigPyIteratorOpen_T : public SwigPyForwardIteratorOpen_T<OutIterator, ValueType, FromOper>
+ {
+ public:
+ FromOper from;
+ typedef OutIterator out_iterator;
+ typedef ValueType value_type;
+ typedef SwigPyIterator_T<out_iterator> base;
+ typedef SwigPyIteratorOpen_T<OutIterator, ValueType, FromOper> self_type;
+
+ SwigPyIteratorOpen_T(out_iterator curr, PyObject *seq)
+ : SwigPyForwardIteratorOpen_T<OutIterator>(curr, seq)
+ {
+ }
+
+ SwigPyIterator *decr(size_t n = 1)
+ {
+ while (n--) {
+ --base::current;
+ }
+ return this;
+ }
+ };
+
+ template<typename OutIterator,
+ typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
+ typename FromOper = from_oper<ValueType> >
+ class SwigPyForwardIteratorClosed_T : public SwigPyIterator_T<OutIterator>
+ {
+ public:
+ FromOper from;
+ typedef OutIterator out_iterator;
+ typedef ValueType value_type;
+ typedef SwigPyIterator_T<out_iterator> base;
+ typedef SwigPyForwardIteratorClosed_T<OutIterator, ValueType, FromOper> self_type;
+
+ SwigPyForwardIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq)
+ : SwigPyIterator_T<OutIterator>(curr, seq), begin(first), end(last)
+ {
+ }
+
+ PyObject *value() const {
+ if (base::current == end) {
+ throw stop_iteration();
+ } else {
+ return from(static_cast<const value_type&>(*(base::current)));
+ }
+ }
+
+ SwigPyIterator *copy() const
+ {
+ return new self_type(*this);
+ }
+
+ SwigPyIterator *incr(size_t n = 1)
+ {
+ while (n--) {
+ if (base::current == end) {
+ throw stop_iteration();
+ } else {
+ ++base::current;
+ }
+ }
+ return this;
+ }
+
+ protected:
+ out_iterator begin;
+ out_iterator end;
+ };
+
+ template<typename OutIterator,
+ typename ValueType = typename std::iterator_traits<OutIterator>::value_type,
+ typename FromOper = from_oper<ValueType> >
+ class SwigPyIteratorClosed_T : public SwigPyForwardIteratorClosed_T<OutIterator,ValueType,FromOper>
+ {
+ public:
+ FromOper from;
+ typedef OutIterator out_iterator;
+ typedef ValueType value_type;
+ typedef SwigPyIterator_T<out_iterator> base;
+ typedef SwigPyForwardIteratorClosed_T<OutIterator, ValueType, FromOper> base0;
+ typedef SwigPyIteratorClosed_T<OutIterator, ValueType, FromOper> self_type;
+
+ SwigPyIteratorClosed_T(out_iterator curr, out_iterator first, out_iterator last, PyObject *seq)
+ : SwigPyForwardIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq)
+ {
+ }
+
+ SwigPyIterator *decr(size_t n = 1)
+ {
+ while (n--) {
+ if (base::current == base0::begin) {
+ throw stop_iteration();
+ } else {
+ --base::current;
+ }
+ }
+ return this;
+ }
+ };
+
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_forward_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0)
+ {
+ return new SwigPyForwardIteratorClosed_T<OutIter>(current, begin, end, seq);
+ }
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_iterator(const OutIter& current, const OutIter& begin,const OutIter& end, PyObject *seq = 0)
+ {
+ return new SwigPyIteratorClosed_T<OutIter>(current, begin, end, seq);
+ }
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_forward_iterator(const OutIter& current, PyObject *seq = 0)
+ {
+ return new SwigPyForwardIteratorOpen_T<OutIter>(current, seq);
+ }
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_iterator(const OutIter& current, PyObject *seq = 0)
+ {
+ return new SwigPyIteratorOpen_T<OutIter>(current, seq);
+ }
+
+}
+}
+
+
+%fragment("SwigPyIterator");
+namespace swig
+{
+ /*
+ Throw a StopIteration exception
+ */
+ %ignore stop_iteration;
+ struct stop_iteration {};
+
+ %typemap(throws) stop_iteration {
+ (void)$1;
+ SWIG_SetErrorObj(PyExc_StopIteration, SWIG_Py_Void());
+ SWIG_fail;
+ }
+
+ /*
+ Mark methods that return new objects
+ */
+ %newobject SwigPyIterator::copy;
+ %newobject SwigPyIterator::operator + (ptrdiff_t n) const;
+ %newobject SwigPyIterator::operator - (ptrdiff_t n) const;
+
+ %nodirector SwigPyIterator;
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:tp_iter") SwigPyIterator "&swig::make_output_iterator_builtin";
+ %feature("python:slot", "tp_iternext", functype="iternextfunc") SwigPyIterator::__next__;
+#else
+ %extend SwigPyIterator {
+ %pythoncode %{def __iter__(self):
+ return self%}
+ }
+#endif
+
+ %catches(swig::stop_iteration) SwigPyIterator::value() const;
+ %catches(swig::stop_iteration) SwigPyIterator::incr(size_t n = 1);
+ %catches(swig::stop_iteration) SwigPyIterator::decr(size_t n = 1);
+ %catches(std::invalid_argument) SwigPyIterator::distance(const SwigPyIterator &x) const;
+ %catches(std::invalid_argument) SwigPyIterator::equal (const SwigPyIterator &x) const;
+ %catches(swig::stop_iteration) SwigPyIterator::__next__();
+ %catches(swig::stop_iteration) SwigPyIterator::next();
+ %catches(swig::stop_iteration) SwigPyIterator::previous();
+ %catches(swig::stop_iteration) SwigPyIterator::advance(ptrdiff_t n);
+ %catches(swig::stop_iteration) SwigPyIterator::operator += (ptrdiff_t n);
+ %catches(swig::stop_iteration) SwigPyIterator::operator -= (ptrdiff_t n);
+ %catches(swig::stop_iteration) SwigPyIterator::operator + (ptrdiff_t n) const;
+ %catches(swig::stop_iteration) SwigPyIterator::operator - (ptrdiff_t n) const;
+
+ struct SwigPyIterator
+ {
+ protected:
+ SwigPyIterator(PyObject *seq);
+
+ public:
+ virtual ~SwigPyIterator();
+
+ // Access iterator method, required by Python
+ virtual PyObject *value() const = 0;
+
+ // Forward iterator method, required by Python
+ virtual SwigPyIterator *incr(size_t n = 1) = 0;
+
+ // Backward iterator method, very common in C++, but not required in Python
+ virtual SwigPyIterator *decr(size_t n = 1);
+
+ // Random access iterator methods, but not required in Python
+ virtual ptrdiff_t distance(const SwigPyIterator &x) const;
+
+ virtual bool equal (const SwigPyIterator &x) const;
+
+ // C++ common/needed methods
+ virtual SwigPyIterator *copy() const = 0;
+
+ PyObject *next();
+ PyObject *__next__();
+ PyObject *previous();
+ SwigPyIterator *advance(ptrdiff_t n);
+
+ bool operator == (const SwigPyIterator& x) const;
+ bool operator != (const SwigPyIterator& x) const;
+ SwigPyIterator& operator += (ptrdiff_t n);
+ SwigPyIterator& operator -= (ptrdiff_t n);
+ SwigPyIterator* operator + (ptrdiff_t n) const;
+ SwigPyIterator* operator - (ptrdiff_t n) const;
+ ptrdiff_t operator - (const SwigPyIterator& x) const;
+ };
+}
+
diff --git a/contrib/tools/swig/Lib/python/pymacros.swg b/contrib/tools/swig/Lib/python/pymacros.swg
new file mode 100644
index 00000000000..ab7bace5bac
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pymacros.swg
@@ -0,0 +1,4 @@
+%include <typemaps/swigmacros.swg>
+
+
+
diff --git a/contrib/tools/swig/Lib/python/pyname_compat.i b/contrib/tools/swig/Lib/python/pyname_compat.i
new file mode 100644
index 00000000000..789b2844351
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyname_compat.i
@@ -0,0 +1,78 @@
+/*
+* From SWIG 1.3.37 we deprecated all SWIG symbols that start with Py,
+* since they are inappropriate and discouraged in Python documentation
+* (from http://www.python.org/doc/2.5.2/api/includes.html):
+*
+* "All user visible names defined by Python.h (except those defined by the included
+* standard headers) have one of the prefixes "Py" or "_Py". Names beginning with
+* "_Py" are for internal use by the Python implementation and should not be used
+* by extension writers. Structure member names do not have a reserved prefix.
+*
+* Important: user code should never define names that begin with "Py" or "_Py".
+* This confuses the reader, and jeopardizes the portability of the user code to
+* future Python versions, which may define additional names beginning with one
+* of these prefixes."
+*
+* This file defined macros to provide backward compatibility for these deprecated
+* symbols. In the case you have these symbols in your interface file, you can simply
+* include this file at beginning of it.
+*
+* However, this file may be removed in future release of SWIG, so using this file to
+* keep these inappropriate names in your SWIG interface file is also not recommended.
+* Instead, we provide a simple tool for converting your interface files to
+* the new naming convention. You can get the tool from the SWIG distribution:
+* Tools/pyname_patch.py
+*/
+
+%fragment("PySequence_Base", "header", fragment="SwigPySequence_Base") {}
+%fragment("PySwigIterator_T", "header", fragment="SwigPyIterator_T") {}
+%fragment("PyPairBoolOutputIterator", "header", fragment="SwigPyPairBoolOutputIterator") {}
+%fragment("PySwigIterator", "header", fragment="SwigPyIterator") {}
+%fragment("PySwigIterator_T", "header", fragment="SwigPyIterator_T") {}
+
+%inline %{
+#define PyMapIterator_T SwigPyMapIterator_T
+#define PyMapKeyIterator_T SwigPyMapKeyIterator_T
+#define PyMapValueIterator_T SwigPyMapValueIterator_T
+#define PyObject_ptr SwigPtr_PyObject
+#define PyObject_var SwigVar_PyObject
+#define PyOper SwigPyOper
+#define PySwigClientData SwigPyClientData
+#define PySwigClientData_Del SwigPyClientData_Del
+#define PySwigClientData_New SwigPyClientData_New
+#define PySwigIterator SwigPyIterator
+#define PySwigIteratorClosed_T SwigPyIteratorClosed_T
+#define PySwigIteratorOpen_T SwigPyIteratorOpen_T
+#define PySwigIterator_T SwigPyIterator_T
+#define PySwigObject SwigPyObject
+#define PySwigObject_Check SwigPyObject_Check
+#define PySwigObject_GetDesc SwigPyObject_GetDesc
+#define PySwigObject_New SwigPyObject_New
+#define PySwigObject_acquire SwigPyObject_acquire
+#define PySwigObject_append SwigPyObject_append
+#define PySwigObject_as_number SwigPyObject_as_number
+#define PySwigObject_compare SwigPyObject_compare
+#define PySwigObject_dealloc SwigPyObject_dealloc
+#define PySwigObject_disown SwigPyObject_disown
+#define PySwigObject_format SwigPyObject_format
+#define PySwigObject_getattr SwigPyObject_getattr
+#define PySwigObject_hex SwigPyObject_hex
+#define PySwigObject_long SwigPyObject_long
+#define PySwigObject_next SwigPyObject_next
+#define PySwigObject_oct SwigPyObject_oct
+#define PySwigObject_own SwigPyObject_own
+#define PySwigObject_repr SwigPyObject_repr
+#define PySwigObject_richcompare SwigPyObject_richcompare
+#define PySwigObject_type SwigPyObject_type
+#define PySwigPacked SwigPyPacked
+#define PySwigPacked_Check SwigPyPacked_Check
+#define PySwigPacked_New SwigPyPacked_New
+#define PySwigPacked_UnpackData SwigPyPacked_UnpackData
+#define PySwigPacked_compare SwigPyPacked_compare
+#define PySwigPacked_dealloc SwigPyPacked_dealloc
+#define PySwigPacked_repr SwigPyPacked_repr
+#define PySwigPacked_str SwigPyPacked_str
+#define PySwigPacked_type SwigPyPacked_type
+#define pyswigobject_type swigpyobject_type
+#define pyswigpacked_type swigpypacked_type
+%}
diff --git a/contrib/tools/swig/Lib/python/pyopers.swg b/contrib/tools/swig/Lib/python/pyopers.swg
new file mode 100644
index 00000000000..fd2fcc58120
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyopers.swg
@@ -0,0 +1,264 @@
+/* ------------------------------------------------------------
+ * Overloaded operator support
+
+ The directives in this file apply whether or not you use the
+ -builtin option to SWIG, but operator overloads are particularly
+ attractive when using -builtin, because they are much faster
+ than named methods.
+
+ If you're using the -builtin option to SWIG, and you want to define
+ python operator overloads beyond the defaults defined in this file,
+ here's what you need to know:
+
+ There are two ways to define a python slot function: dispatch to a
+ statically defined function; or dispatch to a method defined on the
+ operand.
+
+ To dispatch to a statically defined function, use %feature("python:<slot>"),
+ where <slot> is the name of a field in a PyTypeObject, PyNumberMethods,
+ PyMappingMethods, PySequenceMethods, or PyBufferProcs. For example:
+
+ %feature("python:tp_hash") MyClass "myHashFunc";
+
+ class MyClass {
+ public:
+ ...
+ };
+
+ %{
+ // Note: Py_hash_t was introduced in Python 3.2
+ static Py_hash_t myHashFunc(PyObject *pyobj) {
+ MyClass *cobj;
+ // Convert pyobj to cobj
+ return (cobj->field1 * (cobj->field2 << 7));
+ }
+ %}
+
+ NOTE: It is the responsibility of the programmer (that's you) to ensure
+ that a statically defined slot function has the correct signature.
+
+ If, instead, you want to dispatch to an instance method, you can
+ use %feature("python:slot"). For example:
+
+ %feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc;
+
+ class MyClass {
+ public:
+ Py_hash_t myHashFunc () const;
+ ...
+ };
+
+ NOTE: Some python slots use a method signature which does not
+ match the signature of SWIG-wrapped methods. For those slots,
+ SWIG will automatically generate a "closure" function to re-marshall
+ the arguments before dispatching to the wrapped method. Setting
+ the "functype" attribute of the feature enables SWIG to generate
+ a correct closure function.
+
+ --------------------------------------------------------------
+
+ The tp_richcompare slot is a special case: SWIG automatically generates
+ a rich compare function for all wrapped types. If a type defines C++
+ operator overloads for comparison (operator==, operator<, etc.), they
+ will be called from the generated rich compare function. If you
+ want to explicitly choose a method to handle a certain comparison
+ operation, you may use a different feature, %feature("python:compare")
+ like this:
+
+ %feature("python:compare", "Py_LT") MyClass::lessThan;
+
+ class MyClass {
+ public:
+ bool lessThan(const MyClass& other) const;
+ ...
+ };
+
+ ... where "Py_LT" is one of the rich comparison opcodes defined in the
+ python header file object.h.
+
+ If there's no method defined to handle a particular comparison operation,
+ the default behavior is to compare pointer values of the wrapped
+ C++ objects.
+
+ --------------------------------------------------------------
+
+
+ For more information about python slots, including their names and
+ signatures, you may refer to the python documentation :
+
+ http://docs.python.org/c-api/typeobj.html
+
+ * ------------------------------------------------------------ */
+
+
+#ifdef __cplusplus
+
+#if defined(SWIGPYTHON_BUILTIN)
+#define %pybinoperator(pyname,oper,functp,slt) %rename(pyname) oper; %pythonmaybecall oper; %feature("python:slot", #slt, functype=#functp) oper; %feature("python:slot", #slt, functype=#functp) pyname;
+#define %pycompare(pyname,oper,comptype) %rename(pyname) oper; %pythonmaybecall oper; %feature("python:compare", #comptype) oper; %feature("python:compare", #comptype) pyname;
+#else
+#define %pybinoperator(pyname,oper,functp,slt) %rename(pyname) oper; %pythonmaybecall oper
+#define %pycompare(pyname,oper,comptype) %pybinoperator(pyname,oper,,comptype)
+#endif
+
+%pybinoperator(__add__, *::operator+, binaryfunc, nb_add);
+%pybinoperator(__pos__, *::operator+(), unaryfunc, nb_positive);
+%pybinoperator(__pos__, *::operator+() const, unaryfunc, nb_positive);
+%pybinoperator(__sub__, *::operator-, binaryfunc, nb_subtract);
+%pybinoperator(__neg__, *::operator-(), unaryfunc, nb_negative);
+%pybinoperator(__neg__, *::operator-() const, unaryfunc, nb_negative);
+%pybinoperator(__mul__, *::operator*, binaryfunc, nb_multiply);
+%pybinoperator(__mod__, *::operator%, binaryfunc, nb_remainder);
+%pybinoperator(__lshift__, *::operator<<, binaryfunc, nb_lshift);
+%pybinoperator(__rshift__, *::operator>>, binaryfunc, nb_rshift);
+%pybinoperator(__and__, *::operator&, binaryfunc, nb_and);
+%pybinoperator(__or__, *::operator|, binaryfunc, nb_or);
+%pybinoperator(__xor__, *::operator^, binaryfunc, nb_xor);
+%pycompare(__lt__, *::operator<, Py_LT);
+%pycompare(__le__, *::operator<=, Py_LE);
+%pycompare(__gt__, *::operator>, Py_GT);
+%pycompare(__ge__, *::operator>=, Py_GE);
+%pycompare(__eq__, *::operator==, Py_EQ);
+%pycompare(__ne__, *::operator!=, Py_NE);
+
+/* Special cases */
+%rename(__invert__) *::operator~;
+%feature("python:slot", "nb_invert", functype="unaryfunc") *::operator~;
+%rename(__call__) *::operator();
+%feature("python:slot", "tp_call", functype="ternarycallfunc") *::operator();
+
+#if defined(SWIGPYTHON_BUILTIN)
+%pybinoperator(__nonzero__, *::operator bool, inquiry, nb_nonzero);
+%pybinoperator(__truediv__, *::operator/ , binaryfunc, nb_divide);
+#else
+%feature("shadow") *::operator bool %{
+def __nonzero__(self):
+ return $action(self)
+__bool__ = __nonzero__
+%};
+%rename(__nonzero__) *::operator bool;
+%feature("shadow") *::operator/ %{
+def __truediv__(self, *args):
+ return $action(self, *args)
+__div__ = __truediv__
+%};
+%rename(__truediv__) *::operator/;
+%pythonmaybecall *::operator/;
+#endif
+
+/* Ignored operators */
+%ignoreoperator(LNOT) operator!;
+%ignoreoperator(LAND) operator&&;
+%ignoreoperator(LOR) operator||;
+%ignoreoperator(EQ) *::operator=;
+%ignoreoperator(PLUSPLUS) *::operator++;
+%ignoreoperator(MINUSMINUS) *::operator--;
+%ignoreoperator(ARROWSTAR) *::operator->*;
+%ignoreoperator(INDEX) *::operator[];
+
+/*
+ Inplace operator declarations.
+
+ They translate the inplace C++ operators (+=, -=, ...) into the
+ corresponding python equivalents(__iadd__,__isub__), etc,
+ disabling the ownership of the input 'this' pointer, and assigning
+ it to the returning object:
+
+ %feature("del") *::Operator; // disables ownership by generating SWIG_POINTER_DISOWN
+ %feature("new") *::Operator; // claims ownership by generating SWIG_POINTER_OWN
+
+ This makes the most common case safe, ie:
+
+ A& A::operator+=(int i) { ...; return *this; }
+ ^^^^ ^^^^^^
+
+ will work fine, even when the resulting python object shares the
+ 'this' pointer with the input one. The input object is usually
+ deleted after the operation, including the shared 'this' pointer,
+ producing 'strange' seg faults, as reported by Lucriz
+
+ If you have an interface that already takes care of that, ie, you
+ already are using inplace operators and you are not getting
+ seg. faults, with the new scheme you could end with 'free' elements
+ that never get deleted (maybe, not sure, it depends). But if that is
+ the case, you could recover the old behaviour using
+
+ %feature("del","0") A::operator+=;
+ %feature("new","0") A::operator+=;
+
+ which recovers the old behaviour for the class 'A', or if you are
+ 100% sure your entire system works fine in the old way, use:
+
+ %feature("del","") *::operator+=;
+ %feature("new","") *::operator+=;
+
+ The default behaviour assumes that the 'this' pointer's memory is
+ already owned by the SWIG object; it relinquishes ownership then
+ takes it back. This may not be the case though as the SWIG object
+ might be owned by memory managed elsewhere, eg after calling a
+ function that returns a C++ reference. In such case you will need
+ to use the features above to recover the old behaviour too.
+*/
+
+#if defined(SWIGPYTHON_BUILTIN)
+#define %pyinplaceoper(SwigPyOper, Oper, functp, slt) %delobject Oper; %newobject Oper; %feature("python:slot", #slt, functype=#functp) Oper; %rename(SwigPyOper) Oper
+#else
+#define %pyinplaceoper(SwigPyOper, Oper, functp, slt) %delobject Oper; %newobject Oper; %rename(SwigPyOper) Oper
+#endif
+
+%pyinplaceoper(__iadd__ , *::operator +=, binaryfunc, nb_inplace_add);
+%pyinplaceoper(__isub__ , *::operator -=, binaryfunc, nb_inplace_subtract);
+%pyinplaceoper(__imul__ , *::operator *=, binaryfunc, nb_inplace_multiply);
+%pyinplaceoper(__imod__ , *::operator %=, binaryfunc, nb_inplace_remainder);
+%pyinplaceoper(__iand__ , *::operator &=, binaryfunc, nb_inplace_and);
+%pyinplaceoper(__ior__ , *::operator |=, binaryfunc, nb_inplace_or);
+%pyinplaceoper(__ixor__ , *::operator ^=, binaryfunc, nb_inplace_xor);
+%pyinplaceoper(__ilshift__, *::operator <<=, binaryfunc, nb_inplace_lshift);
+%pyinplaceoper(__irshift__, *::operator >>=, binaryfunc, nb_inplace_rshift);
+
+/* Special cases */
+#if defined(SWIGPYTHON_BUILTIN)
+%pyinplaceoper(__itruediv__ , *::operator /=, binaryfunc, nb_inplace_divide);
+#else
+%delobject *::operator /=;
+%newobject *::operator /=;
+%feature("shadow") *::operator /= %{
+def __itruediv__(self, *args):
+ return $action(self, *args)
+__idiv__ = __itruediv__
+%};
+%rename(__itruediv__) *::operator /=;
+#endif
+
+/* Finally, in python we need to mark the binary operations to fail as
+ 'maybecall' methods */
+
+#define %pybinopermaybecall(oper) %pythonmaybecall __ ## oper ## __; %pythonmaybecall __r ## oper ## __
+
+%pybinopermaybecall(add);
+%pybinopermaybecall(pos);
+%pybinopermaybecall(pos);
+%pybinopermaybecall(sub);
+%pybinopermaybecall(neg);
+%pybinopermaybecall(neg);
+%pybinopermaybecall(mul);
+%pybinopermaybecall(div);
+%pybinopermaybecall(truediv);
+%pybinopermaybecall(mod);
+%pybinopermaybecall(lshift);
+%pybinopermaybecall(rshift);
+%pybinopermaybecall(and);
+%pybinopermaybecall(or);
+%pybinopermaybecall(xor);
+%pybinopermaybecall(lt);
+%pybinopermaybecall(le);
+%pybinopermaybecall(gt);
+%pybinopermaybecall(ge);
+%pybinopermaybecall(eq);
+%pybinopermaybecall(ne);
+
+#endif
+
+
+
diff --git a/contrib/tools/swig/Lib/python/pyprimtypes.swg b/contrib/tools/swig/Lib/python/pyprimtypes.swg
new file mode 100644
index 00000000000..7f372753fb3
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyprimtypes.swg
@@ -0,0 +1,362 @@
+/* ------------------------------------------------------------
+ * Primitive Types
+ * ------------------------------------------------------------ */
+
+/* boolean */
+
+%fragment(SWIG_From_frag(bool),"header") {
+SWIGINTERNINLINE PyObject*
+ SWIG_From_dec(bool)(bool value)
+{
+ return PyBool_FromLong(value ? 1 : 0);
+}
+}
+
+#ifdef SWIG_PYTHON_LEGACY_BOOL
+// Default prior to SWIG 3.0.0
+%fragment(SWIG_AsVal_frag(bool),"header",
+ fragment=SWIG_AsVal_frag(long)) {
+SWIGINTERN int
+SWIG_AsVal_dec(bool)(PyObject *obj, bool *val)
+{
+ int r = PyObject_IsTrue(obj);
+ if (r == -1)
+ return SWIG_ERROR;
+ if (val) *val = r ? true : false;
+ return SWIG_OK;
+}
+}
+#else
+%fragment(SWIG_AsVal_frag(bool),"header",
+ fragment=SWIG_AsVal_frag(long)) {
+SWIGINTERN int
+SWIG_AsVal_dec(bool)(PyObject *obj, bool *val)
+{
+ int r;
+ if (!PyBool_Check(obj))
+ return SWIG_ERROR;
+ r = PyObject_IsTrue(obj);
+ if (r == -1)
+ return SWIG_ERROR;
+ if (val) *val = r ? true : false;
+ return SWIG_OK;
+}
+}
+#endif
+
+/* int */
+
+%fragment(SWIG_From_frag(int),"header") {
+SWIGINTERNINLINE PyObject*
+ SWIG_From_dec(int)(int value)
+{
+ return PyInt_FromLong((long) value);
+}
+}
+
+/* unsigned int */
+
+%fragment(SWIG_From_frag(unsigned int),"header") {
+SWIGINTERNINLINE PyObject*
+ SWIG_From_dec(unsigned int)(unsigned int value)
+{
+ return PyInt_FromSize_t((size_t) value);
+}
+}
+
+/* long */
+
+%fragment(SWIG_From_frag(long),"header") {
+ %define_as(SWIG_From_dec(long), PyInt_FromLong)
+}
+
+%fragment(SWIG_AsVal_frag(long),"header",
+ fragment="SWIG_CanCastAsInteger") {
+SWIGINTERN int
+SWIG_AsVal_dec(long)(PyObject *obj, long* val)
+{
+%#if PY_VERSION_HEX < 0x03000000
+ if (PyInt_Check(obj)) {
+ if (val) *val = PyInt_AsLong(obj);
+ return SWIG_OK;
+ } else
+%#endif
+ if (PyLong_Check(obj)) {
+ long v = PyLong_AsLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ return SWIG_OverflowError;
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ long v = PyInt_AsLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ // Largest double not larger than LONG_MAX (not portably calculated easily)
+ // Note that double(LONG_MAX) is stored in a double rounded up by one (for 64-bit long)
+ // 0x7ffffffffffffc00LL == (int64_t)std::nextafter(double(__uint128_t(LONG_MAX)+1), double(0))
+ const double long_max = sizeof(long) == 8 ? 0x7ffffffffffffc00LL : LONG_MAX;
+ // No equivalent needed for 64-bit double(LONG_MIN) is exactly LONG_MIN
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, long_max)) {
+ if (val) *val = (long)(d);
+ return res;
+ }
+ }
+ }
+%#endif
+ return SWIG_TypeError;
+}
+}
+
+/* unsigned long */
+
+%fragment(SWIG_From_frag(unsigned long),"header",
+ fragment=SWIG_From_frag(long)) {
+SWIGINTERNINLINE PyObject*
+SWIG_From_dec(unsigned long)(unsigned long value)
+{
+ return (value > LONG_MAX) ?
+ PyLong_FromUnsignedLong(value) : PyInt_FromLong(%numeric_cast(value,long));
+}
+}
+
+%fragment(SWIG_AsVal_frag(unsigned long),"header",
+ fragment="SWIG_CanCastAsInteger") {
+SWIGINTERN int
+SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val)
+{
+%#if PY_VERSION_HEX < 0x03000000
+ if (PyInt_Check(obj)) {
+ long v = PyInt_AsLong(obj);
+ if (v >= 0) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ return SWIG_OverflowError;
+ }
+ } else
+%#endif
+ if (PyLong_Check(obj)) {
+ unsigned long v = PyLong_AsUnsignedLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ return SWIG_OverflowError;
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ unsigned long v = PyLong_AsUnsignedLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ double d;
+ int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
+ // Largest double not larger than ULONG_MAX (not portably calculated easily)
+ // Note that double(ULONG_MAX) is stored in a double rounded up by one (for 64-bit unsigned long)
+ // 0xfffffffffffff800ULL == (uint64_t)std::nextafter(double(__uint128_t(ULONG_MAX)+1), double(0))
+ const double ulong_max = sizeof(unsigned long) == 8 ? 0xfffffffffffff800ULL : ULONG_MAX;
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ulong_max)) {
+ if (val) *val = (unsigned long)(d);
+ return res;
+ }
+ }
+ }
+%#endif
+ return SWIG_TypeError;
+}
+}
+
+/* long long */
+
+%fragment(SWIG_From_frag(long long),"header",
+ fragment="SWIG_LongLongAvailable") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERNINLINE PyObject*
+SWIG_From_dec(long long)(long long value)
+{
+ return ((value < LONG_MIN) || (value > LONG_MAX)) ?
+ PyLong_FromLongLong(value) : PyInt_FromLong(%numeric_cast(value,long));
+}
+%#endif
+}
+
+%fragment(SWIG_AsVal_frag(long long),"header",
+ fragment=SWIG_AsVal_frag(long),
+ fragment="SWIG_CanCastAsInteger",
+ fragment="SWIG_LongLongAvailable") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERN int
+SWIG_AsVal_dec(long long)(PyObject *obj, long long *val)
+{
+ int res = SWIG_TypeError;
+ if (PyLong_Check(obj)) {
+ long long v = PyLong_AsLongLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ res = SWIG_OverflowError;
+ }
+ } else {
+ long v;
+ res = SWIG_AsVal(long)(obj,&v);
+ if (SWIG_IsOK(res)) {
+ if (val) *val = v;
+ return res;
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ const double mant_max = 1LL << DBL_MANT_DIG;
+ const double mant_min = -mant_max;
+ double d;
+ res = SWIG_AsVal(double)(obj,&d);
+ if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, mant_min, mant_max))
+ return SWIG_OverflowError;
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, mant_min, mant_max)) {
+ if (val) *val = (long long)(d);
+ return SWIG_AddCast(res);
+ }
+ res = SWIG_TypeError;
+ }
+%#endif
+ return res;
+}
+%#endif
+}
+
+/* unsigned long long */
+
+%fragment(SWIG_From_frag(unsigned long long),"header",
+ fragment="SWIG_LongLongAvailable") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERNINLINE PyObject*
+SWIG_From_dec(unsigned long long)(unsigned long long value)
+{
+ return (value > LONG_MAX) ?
+ PyLong_FromUnsignedLongLong(value) : PyInt_FromLong(%numeric_cast(value,long));
+}
+%#endif
+}
+
+%fragment(SWIG_AsVal_frag(unsigned long long),"header",
+ fragment=SWIG_AsVal_frag(unsigned long),
+ fragment="SWIG_CanCastAsInteger",
+ fragment="SWIG_LongLongAvailable") {
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+SWIGINTERN int
+SWIG_AsVal_dec(unsigned long long)(PyObject *obj, unsigned long long *val)
+{
+ int res = SWIG_TypeError;
+ if (PyLong_Check(obj)) {
+ unsigned long long v = PyLong_AsUnsignedLongLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ res = SWIG_OverflowError;
+ }
+ } else {
+ unsigned long v;
+ res = SWIG_AsVal(unsigned long)(obj,&v);
+ if (SWIG_IsOK(res)) {
+ if (val) *val = v;
+ return res;
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ const double mant_max = 1LL << DBL_MANT_DIG;
+ double d;
+ res = SWIG_AsVal(double)(obj,&d);
+ if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, 0, mant_max))
+ return SWIG_OverflowError;
+ if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) {
+ if (val) *val = (unsigned long long)(d);
+ return SWIG_AddCast(res);
+ }
+ res = SWIG_TypeError;
+ }
+%#endif
+ return res;
+}
+%#endif
+}
+
+/* double */
+
+%fragment(SWIG_From_frag(double),"header") {
+ %define_as(SWIG_From_dec(double), PyFloat_FromDouble)
+}
+
+%fragment(SWIG_AsVal_frag(double),"header") {
+SWIGINTERN int
+SWIG_AsVal_dec(double)(PyObject *obj, double *val)
+{
+ int res = SWIG_TypeError;
+ if (PyFloat_Check(obj)) {
+ if (val) *val = PyFloat_AsDouble(obj);
+ return SWIG_OK;
+%#if PY_VERSION_HEX < 0x03000000
+ } else if (PyInt_Check(obj)) {
+ if (val) *val = (double) PyInt_AsLong(obj);
+ return SWIG_OK;
+%#endif
+ } else if (PyLong_Check(obj)) {
+ double v = PyLong_AsDouble(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_OK;
+ } else {
+ PyErr_Clear();
+ }
+ }
+%#ifdef SWIG_PYTHON_CAST_MODE
+ {
+ int dispatch = 0;
+ double d = PyFloat_AsDouble(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = d;
+ return SWIG_AddCast(SWIG_OK);
+ } else {
+ PyErr_Clear();
+ }
+ if (!dispatch) {
+ long v = PyLong_AsLong(obj);
+ if (!PyErr_Occurred()) {
+ if (val) *val = v;
+ return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
+ } else {
+ PyErr_Clear();
+ }
+ }
+ }
+%#endif
+ return res;
+}
+}
+
+
+
diff --git a/contrib/tools/swig/Lib/python/pyrun.swg b/contrib/tools/swig/Lib/python/pyrun.swg
new file mode 100644
index 00000000000..e7164725dbf
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyrun.swg
@@ -0,0 +1,2108 @@
+/* -----------------------------------------------------------------------------
+ * pyrun.swg
+ *
+ * This file contains the runtime support for Python modules
+ * and includes code for managing global variables and pointer
+ * type checking.
+ *
+ * ----------------------------------------------------------------------------- */
+
+#if PY_VERSION_HEX < 0x02070000 /* 2.7.0 */
+# error "This version of SWIG only supports Python >= 2.7"
+#endif
+
+#if PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03030000
+# error "This version of SWIG only supports Python 3 >= 3.3"
+#endif
+
+/* Common SWIG API */
+
+/* for raw pointers */
+#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
+#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
+
+#ifdef SWIGPYTHON_BUILTIN
+#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags)
+#else
+#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+#endif
+
+#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags)
+
+#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty)
+#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src)
+#define swig_owntype int
+
+/* for raw packed data */
+#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type)
+
+/* for class or struct pointers */
+#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
+
+/* for C or C++ function pointers */
+#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
+#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0)
+
+/* for C++ member pointers, ie, member methods */
+#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type)
+
+
+/* Runtime API */
+
+#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata)
+#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer)
+#define SWIG_NewClientData(obj) SwigPyClientData_New(obj)
+
+#define SWIG_SetErrorObj SWIG_Python_SetErrorObj
+#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg
+#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code)
+#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg)
+#define SWIG_fail goto fail
+
+
+/* Runtime API implementation */
+
+/* Error manipulation */
+
+SWIGINTERN void
+SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyErr_SetObject(errtype, obj);
+ SWIG_Py_DECREF(obj);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+SWIGINTERN void
+SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyErr_SetString(errtype, msg);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj)
+
+/* Set a constant value */
+
+#if defined(SWIGPYTHON_BUILTIN)
+
+SWIGINTERN void
+SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) {
+ PyObject *s = PyString_InternFromString(key);
+ PyList_Append(seq, s);
+ SWIG_Py_DECREF(s);
+}
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) {
+ PyDict_SetItemString(d, name, obj);
+ SWIG_Py_DECREF(obj);
+ if (public_interface)
+ SwigPyBuiltin_AddPublicSymbol(public_interface, name);
+}
+
+#else
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {
+ PyDict_SetItemString(d, name, obj);
+ SWIG_Py_DECREF(obj);
+}
+
+#endif
+
+/* SWIG runtime data Python module */
+static PyObject *Swig_runtime_data_module_global = NULL;
+
+/* Create/obtain the single swig_runtime_data module which is used across different SWIG generated modules */
+SWIGINTERN PyObject *
+SWIG_runtime_data_module() {
+ if (!Swig_runtime_data_module_global) {
+#if PY_VERSION_HEX >= 0x03000000
+ Swig_runtime_data_module_global = PyImport_AddModule(SWIG_RUNTIME_MODULE);
+#else
+ static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+ Swig_runtime_data_module_global = Py_InitModule(SWIG_RUNTIME_MODULE, swig_empty_runtime_method_table);
+#endif
+ SWIG_Py_XINCREF(Swig_runtime_data_module_global);
+ }
+ return Swig_runtime_data_module_global;
+}
+
+/* Append a value to the result obj */
+SWIGINTERN PyObject*
+SWIG_Python_AppendOutput(PyObject* result, PyObject* obj, int is_void) {
+ if (!result) {
+ result = obj;
+ } else if (result == Py_None && is_void) {
+ SWIG_Py_DECREF(result);
+ result = obj;
+ } else {
+ if (!PyList_Check(result)) {
+ PyObject *o2 = result;
+ result = PyList_New(1);
+ if (result) {
+ PyList_SET_ITEM(result, 0, o2);
+ } else {
+ SWIG_Py_DECREF(obj);
+ return o2;
+ }
+ }
+ PyList_Append(result,obj);
+ SWIG_Py_DECREF(obj);
+ }
+ return result;
+}
+
+/* Unpack the argument tuple */
+
+SWIGINTERN Py_ssize_t
+SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
+{
+ if (!args) {
+ if (!min && !max) {
+ return 1;
+ } else {
+ PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none",
+ name, (min == max ? "" : "at least "), (int)min);
+ return 0;
+ }
+ }
+ if (!PyTuple_Check(args)) {
+ if (min <= 1 && max >= 1) {
+ Py_ssize_t i;
+ objs[0] = args;
+ for (i = 1; i < max; ++i) {
+ objs[i] = 0;
+ }
+ return 2;
+ }
+ PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
+ return 0;
+ } else {
+ Py_ssize_t l = PyTuple_GET_SIZE(args);
+ if (l < min) {
+ PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d",
+ name, (min == max ? "" : "at least "), (int)min, (int)l);
+ return 0;
+ } else if (l > max) {
+ PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d",
+ name, (min == max ? "" : "at most "), (int)max, (int)l);
+ return 0;
+ } else {
+ Py_ssize_t i;
+ for (i = 0; i < l; ++i) {
+ objs[i] = PyTuple_GET_ITEM(args, i);
+ }
+ for (; l < max; ++l) {
+ objs[l] = 0;
+ }
+ return i + 1;
+ }
+ }
+}
+
+SWIGINTERN int
+SWIG_Python_CheckNoKeywords(PyObject *kwargs, const char *name) {
+ int no_kwargs = 1;
+ if (kwargs) {
+ assert(PyDict_Check(kwargs));
+ if (PyDict_Size(kwargs) > 0) {
+ PyErr_Format(PyExc_TypeError, "%s() does not take keyword arguments", name);
+ no_kwargs = 0;
+ }
+ }
+ return no_kwargs;
+}
+
+/* A functor is a function object with one single object argument */
+#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL);
+
+/*
+ Helper for static pointer initialization for both C and C++ code, for example
+ static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...);
+*/
+#ifdef __cplusplus
+#define SWIG_STATIC_POINTER(var) var
+#else
+#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Python-specific SWIG API */
+#define SWIG_newvarlink() SWIG_Python_newvarlink()
+#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr)
+#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants)
+
+/* -----------------------------------------------------------------------------
+ * global variable support code.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct swig_globalvar {
+ char *name; /* Name of global variable */
+ PyObject *(*get_attr)(void); /* Return the current value */
+ int (*set_attr)(PyObject *); /* Set the value */
+ struct swig_globalvar *next;
+} swig_globalvar;
+
+typedef struct swig_varlinkobject {
+ PyObject_HEAD
+ swig_globalvar *vars;
+} swig_varlinkobject;
+
+SWIGINTERN PyObject *
+SwigVarLink_repr(PyObject *SWIGUNUSEDPARM(v)) {
+#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_InternFromString("<Swig global variables>");
+#else
+ return PyString_FromString("<Swig global variables>");
+#endif
+}
+
+SWIGINTERN PyObject *
+SwigVarLink_str(PyObject *o) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject *str = PyUnicode_InternFromString("(");
+ PyObject *tail;
+ PyObject *joined;
+ swig_globalvar *var;
+ for (var = v->vars; var; var=var->next) {
+ tail = PyUnicode_FromString(var->name);
+ joined = PyUnicode_Concat(str, tail);
+ SWIG_Py_DECREF(str);
+ SWIG_Py_DECREF(tail);
+ str = joined;
+ if (var->next) {
+ tail = PyUnicode_InternFromString(", ");
+ joined = PyUnicode_Concat(str, tail);
+ SWIG_Py_DECREF(str);
+ SWIG_Py_DECREF(tail);
+ str = joined;
+ }
+ }
+ tail = PyUnicode_InternFromString(")");
+ joined = PyUnicode_Concat(str, tail);
+ SWIG_Py_DECREF(str);
+ SWIG_Py_DECREF(tail);
+ str = joined;
+#else
+ PyObject *str = PyString_FromString("(");
+ swig_globalvar *var;
+ for (var = v->vars; var; var=var->next) {
+ PyString_ConcatAndDel(&str,PyString_FromString(var->name));
+ if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", "));
+ }
+ PyString_ConcatAndDel(&str,PyString_FromString(")"));
+#endif
+ return str;
+}
+
+SWIGINTERN void
+SwigVarLink_dealloc(PyObject *o) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ swig_globalvar *var = v->vars;
+ while (var) {
+ swig_globalvar *n = var->next;
+ free(var->name);
+ free(var);
+ var = n;
+ }
+}
+
+SWIGINTERN PyObject *
+SwigVarLink_getattr(PyObject *o, char *n) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ PyObject *res = NULL;
+ swig_globalvar *var = v->vars;
+ while (var) {
+ if (strcmp(var->name,n) == 0) {
+ res = (*var->get_attr)();
+ break;
+ }
+ var = var->next;
+ }
+ if (res == NULL && !PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
+ }
+ return res;
+}
+
+SWIGINTERN int
+SwigVarLink_setattr(PyObject *o, char *n, PyObject *p) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ int res = 1;
+ swig_globalvar *var = v->vars;
+ while (var) {
+ if (strcmp(var->name,n) == 0) {
+ res = (*var->set_attr)(p);
+ break;
+ }
+ var = var->next;
+ }
+ if (res == 1 && !PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
+ }
+ return res;
+}
+
+#if !defined(SWIGPYTHON_BUILTIN) && PY_VERSION_HEX >= 0x03030000
+#define SWIG_HEAPTYPES
+#endif
+
+SWIGINTERN PyTypeObject*
+swig_varlink_type(void) {
+ static char SwigVarLink_doc[] = "Swig variable link object";
+#ifndef SWIG_HEAPTYPES
+ static PyTypeObject varlink_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp = {
+#if PY_VERSION_HEX >= 0x03000000
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+#endif
+ SWIG_RUNTIME_MODULE ".SwigVarLink", /* tp_name */
+ sizeof(swig_varlinkobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) SwigVarLink_dealloc, /* tp_dealloc */
+#if PY_VERSION_HEX < 0x030800b4
+ (printfunc)0, /* tp_print */
+#else
+ (Py_ssize_t)0, /* tp_vectorcall_offset */
+#endif
+ (getattrfunc) SwigVarLink_getattr, /* tp_getattr */
+ (setattrfunc) SwigVarLink_setattr, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc) SwigVarLink_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ (reprfunc) SwigVarLink_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+ SwigVarLink_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+#if PY_VERSION_HEX >= 0x03040000
+ 0, /* tp_finalize */
+#endif
+#if PY_VERSION_HEX >= 0x03080000
+ 0, /* tp_vectorcall */
+#endif
+#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)
+ 0, /* tp_print */
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ 0, /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d00a4
+ 0, /* tp_versions_used */
+#endif
+#ifdef COUNT_ALLOCS
+ 0, /* tp_allocs */
+ 0, /* tp_frees */
+ 0, /* tp_maxalloc */
+ 0, /* tp_prev */
+ 0 /* tp_next */
+#endif
+ };
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ varlink_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&varlink_type) < 0)
+ return NULL;
+ if (PyModule_AddObject(runtime_data_module, "SwigVarLink", (PyObject *)&varlink_type) == 0)
+ SWIG_Py_INCREF((PyObject *)&varlink_type);
+ }
+ return &varlink_type;
+#else
+ PyType_Slot slots[] = {
+ { Py_tp_dealloc, (void *)SwigVarLink_dealloc },
+ { Py_tp_repr, (void *)SwigVarLink_repr },
+ { Py_tp_getattr, (void *)SwigVarLink_getattr },
+ { Py_tp_setattr, (void *)SwigVarLink_setattr },
+ { Py_tp_str, (void *)SwigVarLink_str },
+ { Py_tp_doc, (void *)SwigVarLink_doc },
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+ SWIG_RUNTIME_MODULE ".SwigVarLink",
+ sizeof(swig_varlinkobject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ slots
+ };
+ PyObject *pytype = PyType_FromSpec(&spec);
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ if (pytype && PyModule_AddObject(runtime_data_module, "SwigVarLink", pytype) == 0)
+ SWIG_Py_INCREF(pytype);
+ return (PyTypeObject *)pytype;
+#endif
+}
+
+/* Create a variable linking object for use later */
+SWIGINTERN PyObject *
+SWIG_Python_newvarlink(void) {
+ swig_varlinkobject *result = PyObject_New(swig_varlinkobject, swig_varlink_type());
+ if (result) {
+ result->vars = 0;
+ }
+ return ((PyObject*) result);
+}
+
+SWIGINTERN void
+SWIG_Python_addvarlink(PyObject *p, const char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+ swig_varlinkobject *v = (swig_varlinkobject *) p;
+ swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+ if (gv) {
+ size_t size = strlen(name)+1;
+ gv->name = (char *)malloc(size);
+ if (gv->name) {
+ memcpy(gv->name, name, size);
+ gv->get_attr = get_attr;
+ gv->set_attr = set_attr;
+ gv->next = v->vars;
+ }
+ }
+ v->vars = gv;
+}
+
+
+static PyObject *Swig_Globals_global = NULL;
+
+SWIGINTERN PyObject *
+SWIG_globals(void) {
+ if (Swig_Globals_global == NULL) {
+ Swig_Globals_global = SWIG_newvarlink();
+ }
+ return Swig_Globals_global;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Pointer declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1)
+#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN)
+
+#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1)
+
+#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2)
+#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The python void return value */
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Py_Void(void)
+{
+ PyObject *none = Py_None;
+ SWIG_Py_INCREF(none);
+ return none;
+}
+
+/* SwigPyClientData */
+
+typedef struct {
+ PyObject *klass;
+ PyObject *newraw;
+ PyObject *newargs;
+ PyObject *destroy;
+ int delargs;
+ int implicitconv;
+ PyTypeObject *pytype;
+} SwigPyClientData;
+
+SWIGRUNTIMEINLINE int
+SWIG_Python_CheckImplicit(swig_type_info *ty)
+{
+ SwigPyClientData *data = (SwigPyClientData *)ty->clientdata;
+ int fail = data ? data->implicitconv : 0;
+ if (fail)
+ PyErr_SetString(PyExc_TypeError, "Implicit conversion is prohibited for explicit constructors.");
+ return fail;
+}
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_ExceptionType(swig_type_info *desc) {
+ SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0;
+ PyObject *klass = data ? data->klass : 0;
+ return (klass ? klass : PyExc_RuntimeError);
+}
+
+
+SWIGRUNTIME SwigPyClientData *
+SwigPyClientData_New(PyObject* obj)
+{
+ if (!obj) {
+ return 0;
+ } else {
+ SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData));
+ /* the klass element */
+ data->klass = obj;
+ SWIG_Py_INCREF(data->klass);
+ /* the newraw method and newargs arguments used to create a new raw instance */
+ if (PyClass_Check(obj)) {
+ data->newraw = 0;
+ SWIG_Py_INCREF(obj);
+ data->newargs = obj;
+ } else {
+ data->newraw = PyObject_GetAttrString(data->klass, "__new__");
+ if (data->newraw) {
+ data->newargs = PyTuple_New(1);
+ if (data->newargs) {
+ SWIG_Py_INCREF(obj);
+ PyTuple_SET_ITEM(data->newargs, 0, obj);
+ } else {
+ SWIG_Py_DECREF(data->newraw);
+ SWIG_Py_DECREF(data->klass);
+ free(data);
+ return 0;
+ }
+ } else {
+ SWIG_Py_INCREF(obj);
+ data->newargs = obj;
+ }
+ }
+ /* the destroy method, aka as the C++ delete method */
+ data->destroy = PyObject_GetAttrString(data->klass, "__swig_destroy__");
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ data->destroy = 0;
+ }
+ if (data->destroy) {
+ data->delargs = !(PyCFunction_GET_FLAGS(data->destroy) & METH_O);
+ } else {
+ data->delargs = 0;
+ }
+ data->implicitconv = 0;
+ data->pytype = 0;
+ return data;
+ }
+}
+
+SWIGRUNTIME void
+SwigPyClientData_Del(SwigPyClientData *data)
+{
+ SWIG_Py_XDECREF(data->klass);
+ SWIG_Py_XDECREF(data->newraw);
+ SWIG_Py_XDECREF(data->newargs);
+ SWIG_Py_XDECREF(data->destroy);
+ free(data);
+}
+
+/* =============== SwigPyObject =====================*/
+
+typedef struct {
+ PyObject_HEAD
+ void *ptr;
+ swig_type_info *ty;
+ int own;
+ PyObject *next;
+#ifdef SWIGPYTHON_BUILTIN
+ PyObject *dict;
+#endif
+} SwigPyObject;
+
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+ SwigPyObject *sobj = (SwigPyObject *)v;
+
+ if (!sobj->dict)
+ sobj->dict = PyDict_New();
+
+ SWIG_Py_XINCREF(sobj->dict);
+ return sobj->dict;
+}
+
+#endif
+
+SWIGRUNTIME PyObject *
+SwigPyObject_long(SwigPyObject *v)
+{
+ return PyLong_FromVoidPtr(v->ptr);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_format(const char* fmt, SwigPyObject *v)
+{
+ PyObject *res = NULL;
+ PyObject *args = PyTuple_New(1);
+ if (args) {
+ PyObject *val = SwigPyObject_long(v);
+ if (val) {
+ PyObject *ofmt;
+ PyTuple_SET_ITEM(args, 0, val);
+ ofmt = SWIG_Python_str_FromChar(fmt);
+ if (ofmt) {
+#if PY_VERSION_HEX >= 0x03000000
+ res = PyUnicode_Format(ofmt,args);
+#else
+ res = PyString_Format(ofmt,args);
+#endif
+ SWIG_Py_DECREF(ofmt);
+ }
+ }
+ SWIG_Py_DECREF(args);
+ }
+ return res;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_oct(SwigPyObject *v)
+{
+ return SwigPyObject_format("%o",v);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_hex(SwigPyObject *v)
+{
+ return SwigPyObject_format("%x",v);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_repr(SwigPyObject *v)
+{
+ const char *name = SWIG_TypePrettyName(v->ty);
+ PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", (name ? name : "unknown"), (void *)v);
+ if (repr && v->next) {
+ PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
+ if (nrep) {
+# if PY_VERSION_HEX >= 0x03000000
+ PyObject *joined = PyUnicode_Concat(repr, nrep);
+ SWIG_Py_DECREF(repr);
+ SWIG_Py_DECREF(nrep);
+ repr = joined;
+# else
+ PyString_ConcatAndDel(&repr,nrep);
+# endif
+ } else {
+ SWIG_Py_DECREF(repr);
+ repr = NULL;
+ }
+ }
+ return repr;
+}
+
+/* We need a version taking two PyObject* parameters so it's a valid
+ * PyCFunction to use in SwigPyObject_methods[]. */
+SWIGRUNTIME PyObject *
+SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+ return SwigPyObject_repr((SwigPyObject*)v);
+}
+
+SWIGRUNTIME int
+SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
+{
+ void *i = v->ptr;
+ void *j = w->ptr;
+ return (i < j) ? -1 : ((i > j) ? 1 : 0);
+}
+
+/* Added for Python 3.x, would it also be useful for Python 2.x? */
+SWIGRUNTIME PyObject*
+SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
+{
+ PyObject* res = NULL;
+ if (!PyErr_Occurred()) {
+ if (op != Py_EQ && op != Py_NE) {
+ SWIG_Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+ res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0);
+ }
+ return res;
+}
+
+
+SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void);
+
+#ifdef SWIGPYTHON_BUILTIN
+static swig_type_info *SwigPyObject_stype = 0;
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+ SwigPyClientData *cd;
+ assert(SwigPyObject_stype);
+ cd = (SwigPyClientData*) SwigPyObject_stype->clientdata;
+ assert(cd);
+ assert(cd->pytype);
+ return cd->pytype;
+}
+#else
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+ static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce();
+ return type;
+}
+#endif
+
+SWIGRUNTIMEINLINE int
+SwigPyObject_Check(PyObject *op) {
+ PyTypeObject *target_tp = SwigPyObject_type();
+ PyTypeObject *op_type = Py_TYPE(op);
+#ifdef SWIGPYTHON_BUILTIN
+ if (PyType_IsSubtype(op_type, target_tp))
+ return 1;
+ return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyObject") == 0);
+#else
+# ifdef Py_LIMITED_API
+ int cmp;
+ PyObject *tp_name;
+#endif
+ if (op_type == target_tp)
+ return 1;
+# ifdef Py_LIMITED_API
+ tp_name = PyObject_GetAttrString((PyObject *)op_type, "__name__");
+ if (!tp_name)
+ return 0;
+ cmp = PyUnicode_CompareWithASCIIString(tp_name, "SwigPyObject");
+ SWIG_Py_DECREF(tp_name);
+ return cmp == 0;
+# else
+ return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyObject") == 0);
+# endif
+#endif
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_New(void *ptr, swig_type_info *ty, int own);
+
+static PyObject* Swig_Capsule_global = NULL;
+
+SWIGRUNTIME void
+SwigPyObject_dealloc(PyObject *v)
+{
+ SwigPyObject *sobj = (SwigPyObject *) v;
+ PyObject *next = sobj->next;
+ if (sobj->own == SWIG_POINTER_OWN) {
+ swig_type_info *ty = sobj->ty;
+ SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+ PyObject *destroy = data ? data->destroy : 0;
+ if (destroy) {
+ /* destroy is always a VARARGS method */
+ PyObject *res;
+
+ /* PyObject_CallFunction() has the potential to silently drop
+ the active exception. In cases of unnamed temporary
+ variable or where we just finished iterating over a generator
+ StopIteration will be active right now, and this needs to
+ remain true upon return from SwigPyObject_dealloc. So save
+ and restore. */
+
+ PyObject *type = NULL, *value = NULL, *traceback = NULL;
+ PyErr_Fetch(&type, &value, &traceback);
+
+ if (data->delargs) {
+ /* we need to create a temporary object to carry the destroy operation */
+ PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+ if (tmp) {
+ res = SWIG_Python_CallFunctor(destroy, tmp);
+ } else {
+ res = 0;
+ }
+ SWIG_Py_XDECREF(tmp);
+ } else {
+ PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+ PyObject *mself = PyCFunction_GET_SELF(destroy);
+ res = ((*meth)(mself, v));
+ }
+ if (!res)
+ PyErr_WriteUnraisable(destroy);
+
+ PyErr_Restore(type, value, traceback);
+
+ SWIG_Py_XDECREF(res);
+ }
+#if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
+ else {
+ const char *name = SWIG_TypePrettyName(ty);
+ printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown"));
+ }
+#endif
+ SWIG_Py_XDECREF(Swig_Capsule_global);
+ }
+ SWIG_Py_XDECREF(next);
+#ifdef SWIGPYTHON_BUILTIN
+ SWIG_Py_XDECREF(sobj->dict);
+#endif
+ PyObject_Free(v);
+}
+
+SWIGRUNTIME PyObject*
+SwigPyObject_append(PyObject* v, PyObject* next)
+{
+ SwigPyObject *sobj = (SwigPyObject *) v;
+ if (!SwigPyObject_Check(next)) {
+ PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
+ return NULL;
+ }
+ ((SwigPyObject *)next)->next = sobj->next;
+ sobj->next = next;
+ SWIG_Py_INCREF(next);
+ return SWIG_Py_Void();
+}
+
+SWIGRUNTIME PyObject*
+SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+{
+ SwigPyObject *sobj = (SwigPyObject *) v;
+ if (sobj->next) {
+ SWIG_Py_INCREF(sobj->next);
+ return sobj->next;
+ } else {
+ return SWIG_Py_Void();
+ }
+}
+
+SWIGINTERN PyObject*
+SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+{
+ SwigPyObject *sobj = (SwigPyObject *)v;
+ sobj->own = 0;
+ return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+{
+ SwigPyObject *sobj = (SwigPyObject *)v;
+ sobj->own = SWIG_POINTER_OWN;
+ return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+SwigPyObject_own(PyObject *v, PyObject *args)
+{
+ PyObject *val = 0;
+ if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) {
+ return NULL;
+ } else {
+ SwigPyObject *sobj = (SwigPyObject *)v;
+ PyObject *obj = PyBool_FromLong(sobj->own);
+ if (val) {
+ if (PyObject_IsTrue(val)) {
+ SWIG_Py_DECREF(SwigPyObject_acquire(v,args));
+ } else {
+ SWIG_Py_DECREF(SwigPyObject_disown(v,args));
+ }
+ }
+ return obj;
+ }
+}
+
+static PyMethodDef
+SwigPyObject_methods[] = {
+ {"disown", SwigPyObject_disown, METH_NOARGS, "releases ownership of the pointer"},
+ {"acquire", SwigPyObject_acquire, METH_NOARGS, "acquires ownership of the pointer"},
+ {"own", SwigPyObject_own, METH_VARARGS, "returns/sets ownership of the pointer"},
+ {"append", SwigPyObject_append, METH_O, "appends another 'this' object"},
+ {"next", SwigPyObject_next, METH_NOARGS, "returns the next 'this' object"},
+ {"__repr__",SwigPyObject_repr2, METH_NOARGS, "returns object representation"},
+ {0, 0, 0, 0}
+};
+
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_TypeOnce(void) {
+ static char SwigPyObject_doc[] = "Swig object holding a C/C++ pointer";
+#ifndef SWIG_HEAPTYPES
+ static PyNumberMethods SwigPyObject_as_number = {
+ (binaryfunc)0, /*nb_add*/
+ (binaryfunc)0, /*nb_subtract*/
+ (binaryfunc)0, /*nb_multiply*/
+ /* nb_divide removed in Python 3 */
+#if PY_VERSION_HEX < 0x03000000
+ (binaryfunc)0, /*nb_divide*/
+#endif
+ (binaryfunc)0, /*nb_remainder*/
+ (binaryfunc)0, /*nb_divmod*/
+ (ternaryfunc)0,/*nb_power*/
+ (unaryfunc)0, /*nb_negative*/
+ (unaryfunc)0, /*nb_positive*/
+ (unaryfunc)0, /*nb_absolute*/
+ (inquiry)0, /*nb_nonzero*/
+ 0, /*nb_invert*/
+ 0, /*nb_lshift*/
+ 0, /*nb_rshift*/
+ 0, /*nb_and*/
+ 0, /*nb_xor*/
+ 0, /*nb_or*/
+#if PY_VERSION_HEX < 0x03000000
+ 0, /*nb_coerce*/
+#endif
+ (unaryfunc)SwigPyObject_long, /*nb_int*/
+#if PY_VERSION_HEX < 0x03000000
+ (unaryfunc)SwigPyObject_long, /*nb_long*/
+#else
+ 0, /*nb_reserved*/
+#endif
+ (unaryfunc)0, /*nb_float*/
+#if PY_VERSION_HEX < 0x03000000
+ (unaryfunc)SwigPyObject_oct, /*nb_oct*/
+ (unaryfunc)SwigPyObject_hex, /*nb_hex*/
+#endif
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
+#else
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
+#endif
+ };
+
+ static PyTypeObject swigpyobject_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp = {
+#if PY_VERSION_HEX >= 0x03000000
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+#endif
+ SWIG_RUNTIME_MODULE ".SwigPyObject", /* tp_name */
+ sizeof(SwigPyObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SwigPyObject_dealloc, /* tp_dealloc */
+#if PY_VERSION_HEX < 0x030800b4
+ (printfunc)0, /* tp_print */
+#else
+ (Py_ssize_t)0, /* tp_vectorcall_offset */
+#endif
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+#if PY_VERSION_HEX >= 0x03000000
+ 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */
+#else
+ (cmpfunc)SwigPyObject_compare, /* tp_compare */
+#endif
+ (reprfunc)SwigPyObject_repr, /* tp_repr */
+ &SwigPyObject_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ SwigPyObject_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ SwigPyObject_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+#if PY_VERSION_HEX >= 0x03040000
+ 0, /* tp_finalize */
+#endif
+#if PY_VERSION_HEX >= 0x03080000
+ 0, /* tp_vectorcall */
+#endif
+#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)
+ 0, /* tp_print */
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ 0, /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d00a4
+ 0, /* tp_versions_used */
+#endif
+#ifdef COUNT_ALLOCS
+ 0, /* tp_allocs */
+ 0, /* tp_frees */
+ 0, /* tp_maxalloc */
+ 0, /* tp_prev */
+ 0 /* tp_next */
+#endif
+ };
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ swigpyobject_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&swigpyobject_type) != 0)
+ return NULL;
+ if (PyModule_AddObject(runtime_data_module, "SwigPyObject", (PyObject *)&swigpyobject_type) == 0)
+ SWIG_Py_INCREF((PyObject *)&swigpyobject_type);
+ }
+ return &swigpyobject_type;
+#else
+ PyType_Slot slots[] = {
+ { Py_tp_dealloc, (void *)SwigPyObject_dealloc },
+ { Py_tp_repr, (void *)SwigPyObject_repr },
+ { Py_tp_getattro, (void *)PyObject_GenericGetAttr },
+ { Py_tp_doc, (void *)SwigPyObject_doc },
+ { Py_tp_richcompare, (void *)SwigPyObject_richcompare },
+ { Py_tp_methods, (void *)SwigPyObject_methods },
+ { Py_nb_int, (void *)SwigPyObject_long },
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+ SWIG_RUNTIME_MODULE ".SwigPyObject",
+ sizeof(SwigPyObject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ slots
+ };
+ PyObject *pytype = PyType_FromSpec(&spec);
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ if (pytype && PyModule_AddObject(runtime_data_module, "SwigPyObject", pytype) == 0)
+ SWIG_Py_INCREF(pytype);
+ return (PyTypeObject *)pytype;
+#endif
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_New(void *ptr, swig_type_info *ty, int own)
+{
+ SwigPyObject *sobj = PyObject_New(SwigPyObject, SwigPyObject_type());
+ if (sobj) {
+ sobj->ptr = ptr;
+ sobj->ty = ty;
+ sobj->own = own;
+ sobj->next = 0;
+#ifdef SWIGPYTHON_BUILTIN
+ sobj->dict = 0;
+#endif
+ if (own == SWIG_POINTER_OWN) {
+ /* Obtain a reference to the Python capsule wrapping the module information, so that the
+ * module information is correctly destroyed after all SWIG python objects have been freed
+ * by the GC (and corresponding destructors invoked) */
+ SWIG_Py_XINCREF(Swig_Capsule_global);
+ }
+ }
+ return (PyObject *)sobj;
+}
+
+/* -----------------------------------------------------------------------------
+ * Implements a simple Swig Packed type, and use it instead of string
+ * ----------------------------------------------------------------------------- */
+
+typedef struct {
+ PyObject_HEAD
+ void *pack;
+ swig_type_info *ty;
+ size_t size;
+} SwigPyPacked;
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_repr(SwigPyPacked *v)
+{
+ char result[SWIG_BUFFER_SIZE];
+ if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+ return SWIG_Python_str_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
+ } else {
+ return SWIG_Python_str_FromFormat("<Swig Packed %s>", v->ty->name);
+ }
+}
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_str(SwigPyPacked *v)
+{
+ char result[SWIG_BUFFER_SIZE];
+ if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){
+ return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name);
+ } else {
+ return SWIG_Python_str_FromChar(v->ty->name);
+ }
+}
+
+SWIGRUNTIME int
+SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
+{
+ size_t i = v->size;
+ size_t j = w->size;
+ int s = (i < j) ? -1 : ((i > j) ? 1 : 0);
+ return s ? s : strncmp((const char *)v->pack, (const char *)w->pack, 2*v->size);
+}
+
+SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void);
+
+SWIGRUNTIME PyTypeObject*
+SwigPyPacked_type(void) {
+ static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce();
+ return type;
+}
+
+SWIGRUNTIMEINLINE int
+SwigPyPacked_Check(PyObject *op) {
+#ifdef Py_LIMITED_API
+ int cmp;
+ PyObject *tp_name;
+#endif
+ PyTypeObject* op_type = Py_TYPE(op);
+ if (op_type == SwigPyPacked_type())
+ return 1;
+#ifdef Py_LIMITED_API
+ tp_name = PyObject_GetAttrString((PyObject *)op_type, "__name__");
+ if (!tp_name)
+ return 0;
+ cmp = PyUnicode_CompareWithASCIIString(tp_name, "SwigPyPacked");
+ SWIG_Py_DECREF(tp_name);
+ return cmp == 0;
+#else
+ return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyPacked") == 0);
+#endif
+}
+
+SWIGRUNTIME void
+SwigPyPacked_dealloc(PyObject *v)
+{
+ if (SwigPyPacked_Check(v)) {
+ SwigPyPacked *sobj = (SwigPyPacked *) v;
+ free(sobj->pack);
+ }
+ PyObject_Free(v);
+}
+
+SWIGRUNTIME PyTypeObject*
+SwigPyPacked_TypeOnce(void) {
+ static char SwigPyPacked_doc[] = "Swig object holding a C/C++ function pointer";
+#ifndef SWIG_HEAPTYPES
+ static PyTypeObject swigpypacked_type;
+ static int type_init = 0;
+ if (!type_init) {
+ const PyTypeObject tmp = {
+#if PY_VERSION_HEX>=0x03000000
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+#endif
+ SWIG_RUNTIME_MODULE ".SwigPyPacked", /* tp_name */
+ sizeof(SwigPyPacked), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SwigPyPacked_dealloc, /* tp_dealloc */
+#if PY_VERSION_HEX < 0x030800b4
+ (printfunc)0, /* tp_print */
+#else
+ (Py_ssize_t)0, /* tp_vectorcall_offset */
+#endif
+ (getattrfunc)0, /* tp_getattr */
+ (setattrfunc)0, /* tp_setattr */
+#if PY_VERSION_HEX>=0x03000000
+ 0, /* tp_reserved in 3.0.1 */
+#else
+ (cmpfunc)SwigPyPacked_compare, /* tp_compare */
+#endif
+ (reprfunc)SwigPyPacked_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)0, /* tp_hash */
+ (ternaryfunc)0, /* tp_call */
+ (reprfunc)SwigPyPacked_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ SwigPyPacked_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+#if PY_VERSION_HEX >= 0x03040000
+ 0, /* tp_finalize */
+#endif
+#if PY_VERSION_HEX >= 0x03080000
+ 0, /* tp_vectorcall */
+#endif
+#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)
+ 0, /* tp_print */
+#endif
+#if PY_VERSION_HEX >= 0x030c0000
+ 0, /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d00a4
+ 0, /* tp_versions_used */
+#endif
+#ifdef COUNT_ALLOCS
+ 0, /* tp_allocs */
+ 0, /* tp_frees */
+ 0, /* tp_maxalloc */
+ 0, /* tp_prev */
+ 0 /* tp_next */
+#endif
+ };
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ swigpypacked_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&swigpypacked_type) != 0)
+ return NULL;
+ if (PyModule_AddObject(runtime_data_module, "SwigPyPacked", (PyObject *)&swigpypacked_type) == 0)
+ SWIG_Py_INCREF((PyObject *)&swigpypacked_type);
+ }
+ return &swigpypacked_type;
+#else
+ PyType_Slot slots[] = {
+ { Py_tp_dealloc, (void *)SwigPyPacked_dealloc },
+ { Py_tp_repr, (void *)SwigPyPacked_repr },
+ { Py_tp_str, (void *)SwigPyPacked_str },
+ { Py_tp_getattro, (void *)PyObject_GenericGetAttr },
+ { Py_tp_doc, (void *)SwigPyPacked_doc },
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+ SWIG_RUNTIME_MODULE ".SwigPyPacked",
+ sizeof(SwigPyPacked),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ slots
+ };
+ PyObject *pytype = PyType_FromSpec(&spec);
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ if (pytype && PyModule_AddObject(runtime_data_module, "SwigPyPacked", pytype) == 0)
+ SWIG_Py_INCREF(pytype);
+ return (PyTypeObject *)pytype;
+#endif
+}
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty)
+{
+ SwigPyPacked *sobj = PyObject_New(SwigPyPacked, SwigPyPacked_type());
+ if (sobj) {
+ void *pack = malloc(size);
+ if (pack) {
+ memcpy(pack, ptr, size);
+ sobj->pack = pack;
+ sobj->ty = ty;
+ sobj->size = size;
+ } else {
+ PyObject_Free((PyObject *)sobj);
+ sobj = 0;
+ }
+ }
+ return (PyObject *) sobj;
+}
+
+SWIGRUNTIME swig_type_info *
+SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
+{
+ if (SwigPyPacked_Check(obj)) {
+ SwigPyPacked *sobj = (SwigPyPacked *)obj;
+ if (sobj->size != size) return 0;
+ memcpy(ptr, sobj->pack, size);
+ return sobj->ty;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * pointers/data manipulation
+ * ----------------------------------------------------------------------------- */
+
+static PyObject *Swig_This_global = NULL;
+
+SWIGRUNTIME PyObject *
+SWIG_This(void)
+{
+ if (Swig_This_global == NULL)
+ Swig_This_global = SWIG_Python_str_FromChar("this");
+ return Swig_This_global;
+}
+
+/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
+
+/* TODO: I don't know how to implement the fast getset in Python 3 right now */
+#if PY_VERSION_HEX>=0x03000000
+#define SWIG_PYTHON_SLOW_GETSET_THIS
+#endif
+
+SWIGRUNTIME SwigPyObject *
+SWIG_Python_GetSwigThis(PyObject *pyobj)
+{
+ PyObject *obj;
+
+ if (SwigPyObject_Check(pyobj))
+ return (SwigPyObject *) pyobj;
+
+#ifdef SWIGPYTHON_BUILTIN
+ (void)obj;
+# ifdef PyWeakref_CheckProxy
+ if (PyWeakref_CheckProxy(pyobj)) {
+#if PY_VERSION_HEX >= 0x030d0000
+ PyWeakref_GetRef(pyobj, &pyobj);
+ Py_DECREF(pyobj);
+#else
+ pyobj = PyWeakref_GET_OBJECT(pyobj);
+#endif
+ if (pyobj && SwigPyObject_Check(pyobj))
+ return (SwigPyObject*) pyobj;
+ }
+# endif
+ return NULL;
+#else
+
+ obj = 0;
+
+#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ if (PyInstance_Check(pyobj)) {
+ obj = _PyInstance_Lookup(pyobj, SWIG_This());
+ } else {
+ PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+ if (dictptr != NULL) {
+ PyObject *dict = *dictptr;
+ obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
+ } else {
+#ifdef PyWeakref_CheckProxy
+ if (PyWeakref_CheckProxy(pyobj)) {
+ PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+ return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+ }
+#endif
+ obj = PyObject_GetAttr(pyobj,SWIG_This());
+ if (obj) {
+ SWIG_Py_DECREF(obj);
+ } else {
+ if (PyErr_Occurred()) PyErr_Clear();
+ return 0;
+ }
+ }
+ }
+#else
+ obj = PyObject_GetAttr(pyobj,SWIG_This());
+ if (obj) {
+ SWIG_Py_DECREF(obj);
+ } else {
+ if (PyErr_Occurred()) PyErr_Clear();
+ return 0;
+ }
+#endif
+ if (obj && !SwigPyObject_Check(obj)) {
+ /* a PyObject is called 'this', try to get the 'real this'
+ SwigPyObject from it */
+ return SWIG_Python_GetSwigThis(obj);
+ }
+ return (SwigPyObject *)obj;
+#endif
+}
+
+/* Acquire a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_AcquirePtr(PyObject *obj, int own) {
+ if (own == SWIG_POINTER_OWN) {
+ SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+ if (sobj) {
+ int oldown = sobj->own;
+ sobj->own = own;
+ return oldown;
+ }
+ }
+ return 0;
+}
+
+/* Convert a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
+ int res;
+ SwigPyObject *sobj;
+ int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
+
+ if (!obj)
+ return SWIG_ERROR;
+ if (obj == Py_None && !implicit_conv) {
+ if (ptr)
+ *ptr = 0;
+ return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK;
+ }
+
+ res = SWIG_ERROR;
+
+ sobj = SWIG_Python_GetSwigThis(obj);
+ if (own)
+ *own = 0;
+ while (sobj) {
+ void *vptr = sobj->ptr;
+ if (ty) {
+ swig_type_info *to = sobj->ty;
+ if (to == ty) {
+ /* no type cast needed */
+ if (ptr) *ptr = vptr;
+ break;
+ } else {
+ swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+ if (!tc) {
+ sobj = (SwigPyObject *)sobj->next;
+ } else {
+ if (ptr) {
+ int newmemory = 0;
+ *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+ if (newmemory == SWIG_CAST_NEW_MEMORY) {
+ assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */
+ if (own)
+ *own = *own | SWIG_CAST_NEW_MEMORY;
+ }
+ }
+ break;
+ }
+ }
+ } else {
+ if (ptr) *ptr = vptr;
+ break;
+ }
+ }
+ if (sobj) {
+ if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !sobj->own) {
+ res = SWIG_ERROR_RELEASE_NOT_OWNED;
+ } else {
+ if (own)
+ *own = *own | sobj->own;
+ if (flags & SWIG_POINTER_DISOWN) {
+ sobj->own = 0;
+ }
+ if (flags & SWIG_POINTER_CLEAR) {
+ sobj->ptr = 0;
+ }
+ res = SWIG_OK;
+ }
+ } else {
+ if (implicit_conv) {
+ SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+ if (data && !data->implicitconv) {
+ PyObject *klass = data->klass;
+ if (klass) {
+ PyObject *impconv;
+ data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+ impconv = SWIG_Python_CallFunctor(klass, obj);
+ data->implicitconv = 0;
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ impconv = 0;
+ }
+ if (impconv) {
+ SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+ if (iobj) {
+ void *vptr;
+ res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+ if (SWIG_IsOK(res)) {
+ if (ptr) {
+ *ptr = vptr;
+ /* transfer the ownership to 'ptr' */
+ iobj->own = 0;
+ res = SWIG_AddCast(res);
+ res = SWIG_AddNewMask(res);
+ } else {
+ res = SWIG_AddCast(res);
+ }
+ }
+ }
+ SWIG_Py_DECREF(impconv);
+ }
+ }
+ }
+ if (!SWIG_IsOK(res) && obj == Py_None) {
+ if (ptr)
+ *ptr = 0;
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ res = SWIG_OK;
+ }
+ }
+ }
+ return res;
+}
+
+/* Convert a function ptr value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
+ if (!PyCFunction_Check(obj)) {
+ return SWIG_ConvertPtr(obj, ptr, ty, 0);
+ } else {
+ void *vptr = 0;
+ swig_cast_info *tc;
+
+ /* here we get the method pointer for callbacks */
+#ifndef Py_LIMITED_API
+ const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc);
+#else
+ PyObject* pystr_doc = PyObject_GetAttrString(obj, "__doc__");
+ PyObject *bytes = NULL;
+ const char *doc = pystr_doc ? SWIG_PyUnicode_AsUTF8AndSize(pystr_doc, NULL, &bytes) : 0;
+#endif
+ const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0;
+ if (desc)
+ desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0;
+#ifdef Py_LIMITED_API
+ SWIG_Py_XDECREF(bytes);
+ SWIG_Py_XDECREF(pystr_doc);
+#endif
+ if (!desc)
+ return SWIG_ERROR;
+ tc = SWIG_TypeCheck(desc,ty);
+ if (tc) {
+ int newmemory = 0;
+ *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+ assert(!newmemory); /* newmemory handling not yet implemented */
+ } else {
+ return SWIG_ERROR;
+ }
+ return SWIG_OK;
+ }
+}
+
+/* Convert a packed pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) {
+ swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz);
+ if (!to) return SWIG_ERROR;
+ if (ty) {
+ if (to != ty) {
+ /* check type cast? */
+ swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+ if (!tc) return SWIG_ERROR;
+ }
+ }
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Create a new pointer object
+ * ----------------------------------------------------------------------------- */
+
+/*
+ Create a new instance object, without calling __init__, and set the
+ 'this' attribute.
+*/
+
+SWIGRUNTIME PyObject*
+SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
+{
+ PyObject *inst = 0;
+ PyObject *newraw = data->newraw;
+ if (newraw) {
+ inst = PyObject_Call(newraw, data->newargs, NULL);
+ if (inst) {
+#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ PyObject **dictptr = _PyObject_GetDictPtr(inst);
+ if (dictptr != NULL) {
+ PyObject *dict = *dictptr;
+ if (dict == NULL) {
+ dict = PyDict_New();
+ *dictptr = dict;
+ }
+ if (dict) {
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ } else{
+ SWIG_Py_DECREF(inst);
+ inst = 0;
+ }
+ }
+#else
+ if (PyObject_SetAttr(inst, SWIG_This(), swig_this) == -1) {
+ SWIG_Py_DECREF(inst);
+ inst = 0;
+ }
+#endif
+ }
+ } else {
+#if PY_VERSION_HEX >= 0x03000000
+ PyObject *empty_args = PyTuple_New(0);
+ if (empty_args) {
+ PyObject *empty_kwargs = PyDict_New();
+ if (empty_kwargs) {
+#ifndef Py_LIMITED_API
+ newfunc newfn = ((PyTypeObject *)data->newargs)->tp_new;
+#else
+ newfunc newfn = (newfunc)PyType_GetSlot((PyTypeObject *)data->newargs, Py_tp_new);
+#endif
+ inst = newfn((PyTypeObject *)data->newargs, empty_args, empty_kwargs);
+ SWIG_Py_DECREF(empty_kwargs);
+ if (inst) {
+ if (PyObject_SetAttr(inst, SWIG_This(), swig_this) == -1) {
+ SWIG_Py_DECREF(inst);
+ inst = 0;
+ } else {
+ PyType_Modified(Py_TYPE(inst));
+ }
+ }
+ }
+ SWIG_Py_DECREF(empty_args);
+ }
+#else
+ PyObject *dict = PyDict_New();
+ if (dict) {
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ inst = PyInstance_NewRaw(data->newargs, dict);
+ SWIG_Py_DECREF(dict);
+ }
+#endif
+ }
+ return inst;
+}
+
+SWIGRUNTIME int
+SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
+{
+#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ PyObject **dictptr = _PyObject_GetDictPtr(inst);
+ if (dictptr != NULL) {
+ PyObject *dict = *dictptr;
+ if (dict == NULL) {
+ dict = PyDict_New();
+ *dictptr = dict;
+ }
+ if (dict) {
+ return PyDict_SetItem(dict, SWIG_This(), swig_this);
+ } else{
+ return -1;
+ }
+ }
+#endif
+ return PyObject_SetAttr(inst, SWIG_This(), swig_this);
+}
+
+
+SWIGINTERN PyObject *
+SWIG_Python_InitShadowInstance(PyObject *args) {
+ PyObject *obj[2];
+ if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) {
+ return NULL;
+ } else {
+ SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
+ if (sthis) {
+ SWIG_Py_DECREF(SwigPyObject_append((PyObject*) sthis, obj[1]));
+ } else {
+ if (SWIG_Python_SetSwigThis(obj[0], obj[1]) != 0)
+ return NULL;
+ }
+ return SWIG_Py_Void();
+ }
+}
+
+/* Create a new pointer object */
+
+SWIGRUNTIME PyObject *
+SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) {
+ SwigPyClientData *clientdata;
+ PyObject * robj;
+ int own;
+
+ if (!ptr)
+ return SWIG_Py_Void();
+
+ clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+ own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+ if (clientdata && clientdata->pytype) {
+ SwigPyObject *newobj;
+ if (flags & SWIG_BUILTIN_TP_INIT) {
+ newobj = (SwigPyObject*) self;
+ if (newobj->ptr) {
+#ifndef Py_LIMITED_API
+ allocfunc alloc = clientdata->pytype->tp_alloc;
+#else
+ allocfunc alloc = (allocfunc)PyType_GetSlot(clientdata->pytype, Py_tp_alloc);
+#endif
+ PyObject *next_self = alloc(clientdata->pytype, 0);
+ while (newobj->next)
+ newobj = (SwigPyObject *) newobj->next;
+ newobj->next = next_self;
+ newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+ newobj->dict = 0;
+#endif
+ }
+ } else {
+ newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+ if (newobj) {
+ newobj->dict = 0;
+ }
+#endif
+ }
+ if (newobj) {
+ newobj->ptr = ptr;
+ newobj->ty = type;
+ newobj->own = own;
+ newobj->next = 0;
+ return (PyObject*) newobj;
+ }
+ return SWIG_Py_Void();
+ }
+
+ assert(!(flags & SWIG_BUILTIN_TP_INIT));
+
+ robj = SwigPyObject_New(ptr, type, own);
+ if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+ PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+ SWIG_Py_DECREF(robj);
+ robj = inst;
+ }
+ return robj;
+}
+
+/* Create a new packed object */
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) {
+ return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void();
+}
+
+/* -----------------------------------------------------------------------------*
+ * Get type list
+ * -----------------------------------------------------------------------------*/
+
+#ifdef SWIG_LINK_RUNTIME
+void *SWIG_ReturnGlobalTypeList(void *);
+#endif
+
+static PyObject *Swig_TypeCache_global = NULL;
+
+/* The python cached type query */
+SWIGRUNTIME PyObject *
+SWIG_Python_TypeCache(void) {
+ if (Swig_TypeCache_global == NULL) {
+ Swig_TypeCache_global = PyDict_New();
+ }
+ return Swig_TypeCache_global;
+}
+
+SWIGRUNTIME swig_module_info *
+SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
+#ifdef SWIG_LINK_RUNTIME
+ static void *type_pointer = (void *)0;
+ /* first check if module already created */
+ if (!type_pointer) {
+ type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
+ }
+#else
+ void *type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0);
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ type_pointer = (void *)0;
+ }
+#endif
+ return (swig_module_info *) type_pointer;
+}
+
+
+#if defined(SWIG_REFCNT_DEBUG)
+#define SWIG_PYOBJ_REFCNT(OBJ) fprintf(stdout, "" #OBJ " count %ld\n", (OBJ ? Py_REFCNT(OBJ) : 0))
+#else
+#define SWIG_PYOBJ_REFCNT(OBJ)
+#endif
+
+static int interpreter_counter = 0; /* how many (sub-)interpreters are using swig_module's types */
+
+SWIGRUNTIME void
+SWIG_Python_DestroyModule(PyObject *obj)
+{
+ swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME);
+ swig_type_info **types = swig_module->types;
+ size_t i;
+ if (--interpreter_counter != 0) /* another sub-interpreter may still be using the swig_module's types */
+ return;
+ for (i = 0; i < swig_module->size; ++i) {
+ swig_type_info *ty = types[i];
+ if (ty->owndata) {
+ SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
+ ty->clientdata = 0;
+ if (data) SwigPyClientData_Del(data);
+ }
+ }
+ SWIG_Py_XDECREF(Swig_This_global);
+ SWIG_PYOBJ_REFCNT(Swig_This_global);
+ Swig_This_global = NULL;
+
+ SWIG_Py_XDECREF(Swig_Globals_global);
+ SWIG_PYOBJ_REFCNT(Swig_Globals_global);
+ Swig_Globals_global = NULL;
+
+ SWIG_Py_XDECREF(Swig_TypeCache_global);
+ SWIG_PYOBJ_REFCNT(Swig_TypeCache_global);
+ Swig_TypeCache_global = NULL;
+
+ SWIG_PYOBJ_REFCNT(Swig_Capsule_global);
+ Swig_Capsule_global = NULL;
+
+ SWIG_Py_XDECREF(Swig_runtime_data_module_global);
+ SWIG_PYOBJ_REFCNT(Swig_runtime_data_module_global);
+ Swig_runtime_data_module_global = NULL;
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetModule(swig_module_info *swig_module) {
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+ if (pointer && runtime_data_module) {
+ if (PyModule_AddObject(runtime_data_module, SWIGPY_CAPSULE_ATTR_NAME, pointer) == 0) {
+ ++interpreter_counter;
+ Swig_Capsule_global = pointer;
+ } else {
+ SWIG_Py_DECREF(pointer);
+ }
+ } else {
+ SWIG_Py_XDECREF(pointer);
+ }
+}
+
+SWIGRUNTIME swig_type_info *
+SWIG_Python_TypeQuery(const char *type)
+{
+ PyObject *cache = SWIG_Python_TypeCache();
+ PyObject *key = SWIG_Python_str_FromChar(type);
+ PyObject *obj = PyDict_GetItem(cache, key);
+ swig_type_info *descriptor;
+ if (obj) {
+ descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL);
+ } else {
+ swig_module_info *swig_module = SWIG_GetModule(0);
+ descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
+ if (descriptor) {
+ obj = PyCapsule_New((void*) descriptor, NULL, NULL);
+ if (obj) {
+ PyDict_SetItem(cache, key, obj);
+ SWIG_Py_DECREF(obj);
+ }
+ }
+ }
+ SWIG_Py_DECREF(key);
+ return descriptor;
+}
+
+/*
+ For backward compatibility only
+*/
+#define SWIG_POINTER_EXCEPTION 0
+#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg)
+#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags)
+
+SWIGRUNTIME int
+SWIG_Python_AddErrMesg(const char* mesg, int infront)
+{
+ if (PyErr_Occurred()) {
+ PyObject *type = 0;
+ PyObject *value = 0;
+ PyObject *traceback = 0;
+ PyErr_Fetch(&type, &value, &traceback);
+ if (value) {
+ PyObject *old_str = PyObject_Str(value);
+ PyObject *bytes = NULL;
+ const char *tmp = SWIG_PyUnicode_AsUTF8AndSize(old_str, NULL, &bytes);
+ const char *errmesg = tmp ? tmp : "Invalid error message";
+ SWIG_Py_XINCREF(type);
+ PyErr_Clear();
+ if (infront) {
+ PyErr_Format(type, "%s %s", mesg, errmesg);
+ } else {
+ PyErr_Format(type, "%s %s", errmesg, mesg);
+ }
+ SWIG_Py_XDECREF(bytes);
+ SWIG_Py_DECREF(old_str);
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+SWIGRUNTIME int
+SWIG_Python_ArgFail(int argnum)
+{
+ if (PyErr_Occurred()) {
+ /* add information about failing argument */
+ char mesg[256];
+ PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum);
+ return SWIG_Python_AddErrMesg(mesg, 1);
+ } else {
+ return 0;
+ }
+}
+
+SWIGRUNTIMEINLINE const char *
+SwigPyObject_GetDesc(PyObject *self)
+{
+ SwigPyObject *v = (SwigPyObject *)self;
+ swig_type_info *ty = v ? v->ty : 0;
+ return ty ? ty->str : "";
+}
+
+SWIGRUNTIME void
+SWIG_Python_TypeError(const char *type, PyObject *obj)
+{
+ (void) obj;
+ if (type) {
+#if defined(SWIG_COBJECT_TYPES)
+ if (obj && SwigPyObject_Check(obj)) {
+ const char *otype = (const char *) SwigPyObject_GetDesc(obj);
+ if (otype) {
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received",
+ type, otype);
+ return;
+ }
+ } else
+#endif
+ {
+#ifndef Py_LIMITED_API
+ /* tp_name is not accessible */
+ const char *otype = (obj ? obj->ob_type->tp_name : 0);
+ if (otype) {
+ PyObject *str = PyObject_Str(obj);
+ PyObject *bytes = NULL;
+ const char *cstr = str ? SWIG_PyUnicode_AsUTF8AndSize(str, NULL, &bytes) : 0;
+ if (cstr) {
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
+ type, otype, cstr);
+ } else {
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received",
+ type, otype);
+ }
+ SWIG_Py_XDECREF(bytes);
+ SWIG_Py_XDECREF(str);
+ return;
+ }
+#endif
+ }
+ PyErr_Format(PyExc_TypeError, "a '%s' is expected", type);
+ } else {
+ PyErr_Format(PyExc_TypeError, "unexpected type is received");
+ }
+}
+
+
+/* Convert a pointer value, signal an exception on a type mismatch */
+SWIGRUNTIME void *
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) {
+ void *result;
+ if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
+ PyErr_Clear();
+ }
+ return result;
+}
+
+#ifdef SWIGPYTHON_BUILTIN
+SWIGRUNTIME int
+SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
+ PyTypeObject *tp = obj->ob_type;
+ PyObject *descr;
+ PyObject *encoded_name;
+ descrsetfunc f;
+ int res = -1;
+
+# ifdef Py_USING_UNICODE
+ if (PyString_Check(name)) {
+ name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL);
+ if (!name)
+ return -1;
+ } else if (!PyUnicode_Check(name))
+# else
+ if (!PyString_Check(name))
+# endif
+ {
+ PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name);
+ return -1;
+ } else {
+ SWIG_Py_INCREF(name);
+ }
+
+ if (!tp->tp_dict) {
+ if (PyType_Ready(tp) != 0)
+ goto done;
+ }
+
+ descr = _PyType_Lookup(tp, name);
+ f = NULL;
+ if (descr != NULL)
+ f = descr->ob_type->tp_descr_set;
+ if (!f) {
+ if (PyString_Check(name)) {
+ encoded_name = name;
+ SWIG_Py_INCREF(name);
+ } else {
+ encoded_name = PyUnicode_AsUTF8String(name);
+ if (!encoded_name)
+ goto done;
+ }
+ PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name));
+ SWIG_Py_DECREF(encoded_name);
+ } else {
+ res = f(descr, obj, value);
+ }
+
+ done:
+ SWIG_Py_DECREF(name);
+ return res;
+}
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/tools/swig/Lib/python/pyruntime.swg b/contrib/tools/swig/Lib/python/pyruntime.swg
new file mode 100644
index 00000000000..b9210a84b59
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyruntime.swg
@@ -0,0 +1,61 @@
+%insert(runtime) %{
+#if defined(__GNUC__) && defined(_WIN32) && !defined(SWIG_PYTHON_NO_HYPOT_WORKAROUND)
+/* Workaround for '::hypot' has not been declared', see https://bugs.python.org/issue11566 */
+# include <math.h>
+#endif
+
+#if !defined(PY_SSIZE_T_CLEAN) && !defined(SWIG_NO_PY_SSIZE_T_CLEAN)
+#define PY_SSIZE_T_CLEAN
+#endif
+
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#if defined(__cplusplus) && __cplusplus >=201703L
+#pragma GCC diagnostic ignored "-Wregister" /* For python-2.7 headers that use register */
+#endif
+#endif
+
+#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
+/* Use debug wrappers with the Python release dll */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1929
+/* Workaround compilation errors when redefining _DEBUG in MSVC 2019 version 16.10 and later
+ * See https://github.com/swig/swig/issues/2090 */
+# include <corecrt.h>
+#endif
+
+# undef _DEBUG
+# include <Python.h>
+# define _DEBUG 1
+#else
+# include <Python.h>
+#endif
+
+#if defined(SWIGPYTHON_BUILTIN) && defined(SWIG_HEAPTYPES)
+/* SWIG_HEAPTYPES is not ready for use with SWIGPYTHON_BUILTIN, but if turned on manually requires the following */
+#if PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x030c0000
+#error #include <structmember.h>
+#define Py_READONLY READONLY
+#define Py_T_PYSSIZET T_PYSSIZET
+#endif
+#endif
+
+#if __GNUC__ >= 7
+#pragma GCC diagnostic pop
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+%}
+
+%insert(runtime) "swigrun.swg"; /* SWIG API */
+%insert(runtime) "swigerrors.swg"; /* SWIG errors */
+%insert(runtime) "pyhead.swg"; /* Python includes and fixes */
+%insert(runtime) "pyerrors.swg"; /* Python errors */
+%insert(runtime) "pythreads.swg"; /* Python thread code */
+%insert(runtime) "pyapi.swg"; /* Python API */
+%insert(runtime) "pyrun.swg"; /* Python run-time code */
+
+#if defined(SWIGPYTHON_BUILTIN)
+%insert(runtime) "builtin.swg"; /* Specialization for classes with single inheritance */
+#endif
diff --git a/contrib/tools/swig/Lib/python/pystdcommon.swg b/contrib/tools/swig/Lib/python/pystdcommon.swg
new file mode 100644
index 00000000000..afa71350a91
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pystdcommon.swg
@@ -0,0 +1,265 @@
+%fragment("StdTraits","header",fragment="StdTraitsCommon")
+{
+namespace swig {
+ /*
+ Traits that provides the from method
+ */
+ template <class Type> struct traits_from_ptr {
+ static PyObject *from(Type *val, int owner = 0) {
+ return SWIG_InternalNewPointerObj(val, type_info<Type>(), owner);
+ }
+ };
+
+ template <class Type> struct traits_from {
+ static PyObject *from(const Type& val) {
+ return traits_from_ptr<Type>::from(new Type(val), 1);
+ }
+ };
+
+ template <class Type> struct traits_from<Type *> {
+ static PyObject *from(Type* val) {
+ return traits_from_ptr<Type>::from(val, 0);
+ }
+ };
+
+ template <class Type> struct traits_from<const Type *> {
+ static PyObject *from(const Type* val) {
+ return traits_from_ptr<Type>::from(const_cast<Type*>(val), 0);
+ }
+ };
+
+
+ template <class Type>
+ inline PyObject *from(const Type& val) {
+ return traits_from<Type>::from(val);
+ }
+
+ template <class Type>
+ inline PyObject *from_ptr(Type* val, int owner) {
+ return traits_from_ptr<Type>::from(val, owner);
+ }
+
+ /*
+ Traits that provides the asval/as/check method
+ */
+ template <class Type>
+ struct traits_asptr {
+ static int asptr(PyObject *obj, Type **val) {
+ int res = SWIG_ERROR;
+ swig_type_info *descriptor = type_info<Type>();
+ if (val) {
+ Type *p = 0;
+ int newmem = 0;
+ res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR;
+ if (SWIG_IsOK(res)) {
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ res |= SWIG_NEWOBJMASK;
+ }
+ *val = p;
+ }
+ } else {
+ res = descriptor ? SWIG_ConvertPtr(obj, 0, descriptor, 0) : SWIG_ERROR;
+ }
+ return res;
+ }
+ };
+
+ template <class Type>
+ inline int asptr(PyObject *obj, Type **vptr) {
+ return traits_asptr<Type>::asptr(obj, vptr);
+ }
+
+ template <class Type>
+ struct traits_asval {
+ static int asval(PyObject *obj, Type *val) {
+ if (val) {
+ Type *p = 0;
+ int res = traits_asptr<Type>::asptr(obj, &p);
+ if (!SWIG_IsOK(res)) return res;
+ if (p) {
+ typedef typename noconst_traits<Type>::noconst_type noconst_type;
+ *(const_cast<noconst_type*>(val)) = *p;
+ if (SWIG_IsNewObj(res)){
+ %delete(p);
+ res = SWIG_DelNewMask(res);
+ }
+ return res;
+ } else {
+ return SWIG_ERROR;
+ }
+ } else {
+ return traits_asptr<Type>::asptr(obj, (Type **)(0));
+ }
+ }
+ };
+
+ template <class Type> struct traits_asval<Type*> {
+ static int asval(PyObject *obj, Type **val) {
+ if (val) {
+ typedef typename noconst_traits<Type>::noconst_type noconst_type;
+ noconst_type *p = 0;
+ int res = traits_asptr<noconst_type>::asptr(obj, &p);
+ if (SWIG_IsOK(res)) {
+ *(const_cast<noconst_type**>(val)) = p;
+ }
+ return res;
+ } else {
+ return traits_asptr<Type>::asptr(obj, (Type **)(0));
+ }
+ }
+ };
+
+ template <class Type>
+ inline int asval(PyObject *obj, Type *val) {
+ return traits_asval<Type>::asval(obj, val);
+ }
+
+ template <class Type>
+ struct traits_as<Type, value_category> {
+ static Type as(PyObject *obj) {
+ Type v;
+ int res = asval(obj, &v);
+ if (!obj || !SWIG_IsOK(res)) {
+ if (!PyErr_Occurred()) {
+ ::%type_error(swig::type_name<Type>());
+ }
+ throw std::invalid_argument("bad type");
+ }
+ return v;
+ }
+ };
+
+ template <class Type>
+ struct traits_as<Type, pointer_category> {
+ static Type as(PyObject *obj) {
+ Type *v = 0;
+ int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR);
+ if (SWIG_IsOK(res) && v) {
+ if (SWIG_IsNewObj(res)) {
+ Type r(*v);
+ %delete(v);
+ return r;
+ } else {
+ return *v;
+ }
+ } else {
+ if (!PyErr_Occurred()) {
+ %type_error(swig::type_name<Type>());
+ }
+ throw std::invalid_argument("bad type");
+ }
+ }
+ };
+
+ template <class Type>
+ struct traits_as<Type*, pointer_category> {
+ static Type* as(PyObject *obj) {
+ Type *v = 0;
+ int res = (obj ? traits_asptr<Type>::asptr(obj, &v) : SWIG_ERROR);
+ if (SWIG_IsOK(res)) {
+ return v;
+ } else {
+ if (!PyErr_Occurred()) {
+ %type_error(swig::type_name<Type>());
+ }
+ throw std::invalid_argument("bad type");
+ }
+ }
+ };
+
+ template <class Type>
+ inline Type as(PyObject *obj) {
+ return traits_as<Type, typename traits<Type>::category>::as(obj);
+ }
+
+ template <class Type>
+ struct traits_check<Type, value_category> {
+ static bool check(PyObject *obj) {
+ int res = obj ? asval(obj, (Type *)(0)) : SWIG_ERROR;
+ return SWIG_IsOK(res) ? true : false;
+ }
+ };
+
+ template <class Type>
+ struct traits_check<Type, pointer_category> {
+ static bool check(PyObject *obj) {
+ int res = obj ? asptr(obj, (Type **)(0)) : SWIG_ERROR;
+ return SWIG_IsOK(res) ? true : false;
+ }
+ };
+
+ template <class Type>
+ inline bool check(PyObject *obj) {
+ return traits_check<Type, typename traits<Type>::category>::check(obj);
+ }
+}
+}
+
+//
+// Backward compatibility
+//
+
+#ifdef SWIG_PYTHON_BACKWARD_COMP
+%fragment("<string>");
+%{
+PyObject* SwigInt_FromBool(bool b) {
+ return PyInt_FromLong(b ? 1L : 0L);
+}
+double SwigNumber_Check(PyObject* o) {
+ return PyFloat_Check(o) || PyInt_Check(o) || PyLong_Check(o);
+}
+double SwigNumber_AsDouble(PyObject* o) {
+ return PyFloat_Check(o) ? PyFloat_AsDouble(o)
+ : (PyInt_Check(o) ? double(PyInt_AsLong(o))
+ : double(PyLong_AsLong(o)));
+}
+PyObject* SwigString_FromString(const std::string& s) {
+ return PyString_FromStringAndSize(s.data(),s.size());
+}
+std::string SwigString_AsString(PyObject* o) {
+ return std::string(PyString_AsString(o));
+}
+%}
+
+#endif
+
+
+%define %specialize_std_container(Type,Check,As,From)
+%{
+namespace swig {
+ template <> struct traits_asval<Type > {
+ typedef Type value_type;
+ static int asval(PyObject *obj, value_type *val) {
+ if (Check(obj)) {
+ if (val) *val = As(obj);
+ return SWIG_OK;
+ }
+ return SWIG_ERROR;
+ }
+ };
+ template <> struct traits_from<Type > {
+ typedef Type value_type;
+ static PyObject *from(const value_type& val) {
+ return From(val);
+ }
+ };
+
+ template <>
+ struct traits_check<Type, value_category> {
+ static int check(PyObject *obj) {
+ int res = Check(obj);
+ return obj && res ? res : 0;
+ }
+ };
+}
+%}
+%enddef
+
+
+#define specialize_std_vector(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
+#define specialize_std_list(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
+#define specialize_std_deque(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
+#define specialize_std_set(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
+#define specialize_std_multiset(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
+#define specialize_std_unordered_set(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
+#define specialize_std_unordered_multiset(Type,Check,As,From) %specialize_std_container(%arg(Type),Check,As,From)
diff --git a/contrib/tools/swig/Lib/python/pystrings.swg b/contrib/tools/swig/Lib/python/pystrings.swg
new file mode 100644
index 00000000000..9797d1f75e8
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pystrings.swg
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------
+ * utility methods for char strings
+ * ------------------------------------------------------------ */
+%fragment("SWIG_AsCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") {
+/* Return string from Python obj. NOTE: obj must remain in scope in order
+ to use the returned cptr (but only when alloc is set to SWIG_OLDOBJ) */
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(PyObject *obj, char **cptr, size_t *psize, int *alloc)
+{
+%#if PY_VERSION_HEX>=0x03000000
+%#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
+ if (PyBytes_Check(obj))
+%#else
+ if (PyUnicode_Check(obj))
+%#endif
+%#else
+ if (PyString_Check(obj))
+%#endif
+ {
+ char *cstr; Py_ssize_t len;
+ PyObject *bytes = NULL;
+ int ret = SWIG_OK;
+ if (alloc)
+ *alloc = SWIG_OLDOBJ;
+%#if PY_VERSION_HEX>=0x03000000 && defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
+ if (PyBytes_AsStringAndSize(obj, &cstr, &len) == -1)
+ return SWIG_TypeError;
+%#else
+ cstr = (char *)SWIG_PyUnicode_AsUTF8AndSize(obj, &len, &bytes);
+ if (!cstr)
+ return SWIG_TypeError;
+ /* The returned string is only duplicated if the char * returned is not owned and memory managed by obj */
+ if (bytes && cptr) {
+ if (alloc) {
+ cstr = %new_copy_array(cstr, len + 1, char);
+ *alloc = SWIG_NEWOBJ;
+ } else {
+ /* alloc must be set in order to clean up allocated memory */
+ return SWIG_RuntimeError;
+ }
+ }
+%#endif
+ if (cptr) *cptr = cstr;
+ if (psize) *psize = len + 1;
+ SWIG_Py_XDECREF(bytes);
+ return ret;
+ } else {
+%#if defined(SWIG_PYTHON_2_UNICODE)
+%#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
+%#error "Cannot use both SWIG_PYTHON_2_UNICODE and SWIG_PYTHON_STRICT_BYTE_CHAR at once"
+%#endif
+%#if PY_VERSION_HEX<0x03000000
+ if (PyUnicode_Check(obj)) {
+ char *cstr; Py_ssize_t len;
+ if (!alloc && cptr) {
+ return SWIG_RuntimeError;
+ }
+ obj = PyUnicode_AsUTF8String(obj);
+ if (!obj)
+ return SWIG_TypeError;
+ if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) {
+ if (cptr) {
+ if (alloc) *alloc = SWIG_NEWOBJ;
+ *cptr = %new_copy_array(cstr, len + 1, char);
+ }
+ if (psize) *psize = len + 1;
+
+ SWIG_Py_XDECREF(obj);
+ return SWIG_OK;
+ } else {
+ SWIG_Py_XDECREF(obj);
+ }
+ }
+%#endif
+%#endif
+
+ swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+ if (pchar_descriptor) {
+ void* vptr = 0;
+ if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
+ if (cptr) *cptr = (char *) vptr;
+ if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
+ if (alloc) *alloc = SWIG_OLDOBJ;
+ return SWIG_OK;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+
+%fragment("SWIG_FromCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") {
+SWIGINTERNINLINE PyObject *
+SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+{
+ if (carray) {
+ if (size > INT_MAX) {
+ swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+ return pchar_descriptor ?
+ SWIG_InternalNewPointerObj(%const_cast(carray,char *), pchar_descriptor, 0) : SWIG_Py_Void();
+ } else {
+%#if PY_VERSION_HEX >= 0x03000000
+%#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
+ return PyBytes_FromStringAndSize(carray, %numeric_cast(size, Py_ssize_t));
+%#else
+ return PyUnicode_DecodeUTF8(carray, %numeric_cast(size, Py_ssize_t), "surrogateescape");
+%#endif
+%#else
+ return PyString_FromStringAndSize(carray, %numeric_cast(size, Py_ssize_t));
+%#endif
+ }
+ } else {
+ return SWIG_Py_Void();
+ }
+}
+}
+
diff --git a/contrib/tools/swig/Lib/python/python.swg b/contrib/tools/swig/Lib/python/python.swg
new file mode 100644
index 00000000000..769d9e104a0
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/python.swg
@@ -0,0 +1,59 @@
+/* ------------------------------------------------------------
+ * python.swg
+ *
+ * Python configuration module.
+ * ------------------------------------------------------------ */
+
+/* ------------------------------------------------------------
+ * Inner macros
+ * ------------------------------------------------------------ */
+%include <pymacros.swg>
+
+
+/* ------------------------------------------------------------
+ * The runtime part
+ * ------------------------------------------------------------ */
+%include <pyruntime.swg>
+
+/* ------------------------------------------------------------
+ * Special user directives
+ * ------------------------------------------------------------ */
+%include <pyuserdir.swg>
+
+/* ------------------------------------------------------------
+ * Typemap specializations
+ * ------------------------------------------------------------ */
+%include <pytypemaps.swg>
+
+/* ------------------------------------------------------------
+ * Overloaded operator support
+ * ------------------------------------------------------------ */
+%include <pyopers.swg>
+
+/* ------------------------------------------------------------
+ * Warnings for Python keywords
+ * ------------------------------------------------------------ */
+%include <pythonkw.swg>
+
+/* ------------------------------------------------------------
+ * The Python autodoc support
+ * ------------------------------------------------------------ */
+%include <pydocs.swg>
+
+/* ------------------------------------------------------------
+ * The Python classes, for C++
+ * ------------------------------------------------------------ */
+%include <pyclasses.swg>
+
+/* ------------------------------------------------------------
+ * The Python initialization function
+ * ------------------------------------------------------------ */
+%include <pyinit.swg>
+
+
+/* ------------------------------------------------------------
+ * For backward compatibility
+ * ------------------------------------------------------------ */
+%include <pybackward.swg>
+
+
diff --git a/contrib/tools/swig/Lib/python/pythonkw.swg b/contrib/tools/swig/Lib/python/pythonkw.swg
new file mode 100644
index 00000000000..a21034524fd
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pythonkw.swg
@@ -0,0 +1,140 @@
+/*
+ Warnings for Python keywords, built-in names and bad names.
+*/
+
+#define PYTHONKW(x) %keywordwarn("'" `x` "' is a python keyword", rename="_%s") `x`
+#define PYTHONBN(x) %builtinwarn("'" `x` "' conflicts with a built-in name in python") `x`
+
+
+/*
+ Warnings for Python keywords
+ https://docs.python.org/2/reference/lexical_analysis.html#keywords
+*/
+
+PYTHONKW(and);
+PYTHONKW(as);
+PYTHONKW(assert);
+PYTHONKW(async);
+PYTHONKW(await);
+PYTHONKW(break);
+PYTHONKW(class);
+PYTHONKW(continue);
+PYTHONKW(def);
+PYTHONKW(del);
+PYTHONKW(elif);
+PYTHONKW(else);
+PYTHONKW(except);
+PYTHONKW(exec);
+PYTHONKW(finally);
+PYTHONKW(for);
+PYTHONKW(from);
+PYTHONKW(global);
+PYTHONKW(if);
+PYTHONKW(import);
+PYTHONKW(in);
+PYTHONKW(is);
+PYTHONKW(lambda);
+PYTHONKW(not);
+PYTHONKW(or);
+PYTHONKW(pass);
+PYTHONKW(print);
+PYTHONKW(raise);
+PYTHONKW(return);
+PYTHONKW(try);
+PYTHONKW(while);
+PYTHONKW(with);
+PYTHONKW(yield);
+
+/*
+ built-in functions
+ https://docs.python.org/2/library/functions.html
+ */
+
+PYTHONBN(abs);
+PYTHONBN(apply);
+PYTHONBN(bool);
+PYTHONBN(buffer);
+PYTHONBN(callable);
+PYTHONBN(chr);
+PYTHONBN(classmethod);
+PYTHONBN(cmp);
+PYTHONBN(coerce);
+PYTHONBN(compile);
+PYTHONBN(complex);
+PYTHONBN(delattr);
+PYTHONBN(dict);
+PYTHONBN(dir);
+PYTHONBN(divmod);
+PYTHONBN(enumerate);
+PYTHONBN(eval);
+PYTHONBN(execfile);
+PYTHONBN(file);
+PYTHONBN(filter);
+PYTHONBN(float);
+PYTHONBN(frozenset);
+PYTHONBN(getattr);
+PYTHONBN(globals);
+PYTHONBN(hasattr);
+PYTHONBN(hash);
+PYTHONBN(hex);
+PYTHONBN(id);
+PYTHONBN(input);
+PYTHONBN(int);
+PYTHONBN(intern);
+PYTHONBN(isinstance);
+PYTHONBN(issubclass);
+PYTHONBN(iter);
+PYTHONBN(len);
+PYTHONBN(list);
+PYTHONBN(locals);
+PYTHONBN(long);
+PYTHONBN(map);
+PYTHONBN(max);
+PYTHONBN(min);
+PYTHONBN(object);
+PYTHONBN(oct);
+PYTHONBN(open);
+PYTHONBN(ord);
+PYTHONBN(pow);
+PYTHONBN(property);
+PYTHONBN(range);
+PYTHONBN(raw_input);
+PYTHONBN(reduce);
+PYTHONBN(reload);
+PYTHONBN(repr);
+PYTHONBN(reversed);
+PYTHONBN(round);
+PYTHONBN(set);
+PYTHONBN(setattr);
+PYTHONBN(slice);
+PYTHONBN(sorted);
+PYTHONBN(staticmethod);
+PYTHONBN(str);
+PYTHONBN(sum);
+PYTHONBN(super);
+PYTHONBN(tuple);
+PYTHONBN(type);
+PYTHONBN(unichr);
+PYTHONBN(unicode);
+PYTHONBN(vars);
+PYTHONBN(xrange);
+PYTHONBN(zip);
+
+
+/*
+ built-in names
+ boolean type and None
+*/
+PYTHONBN(True);
+PYTHONBN(False);
+
+PYTHONKW(None);
+
+
+/*
+ 'self' is also a bad Name
+*/
+PYTHONKW(self);
+
+#undef PYTHONBN
+#undef PYTHONKW
diff --git a/contrib/tools/swig/Lib/python/pythreads.swg b/contrib/tools/swig/Lib/python/pythreads.swg
new file mode 100644
index 00000000000..96a64710c38
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pythreads.swg
@@ -0,0 +1,68 @@
+#if defined(SWIG_PYTHON_NO_THREADS)
+# if defined(SWIG_PYTHON_THREADS)
+# undef SWIG_PYTHON_THREADS
+# endif
+#endif
+#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */
+# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL)
+# define SWIG_PYTHON_USE_GIL
+# endif
+# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */
+# if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
+# if PY_VERSION_HEX < 0x03070000
+# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads()
+# else
+# define SWIG_PYTHON_INITIALIZE_THREADS
+# endif
+# endif
+# ifdef __cplusplus /* C++ code */
+ class SWIG_Python_Thread_Block {
+ bool status;
+ PyGILState_STATE state;
+ public:
+ void end() { if (status) { PyGILState_Release(state); status = false;} }
+ SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {}
+ ~SWIG_Python_Thread_Block() { end(); }
+ };
+ class SWIG_Python_Thread_Allow {
+ bool status;
+ PyThreadState *save;
+ public:
+ void end() { if (status) { status = false; PyEval_RestoreThread(save); }}
+ SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {}
+ ~SWIG_Python_Thread_Allow() { end(); }
+ };
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block
+# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end()
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow
+# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end()
+# else /* C code */
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure()
+# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block)
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread()
+# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow)
+# endif
+# else /* Old thread way, not implemented, user must provide it */
+# if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
+# define SWIG_PYTHON_INITIALIZE_THREADS
+# endif
+# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+# endif
+# if !defined(SWIG_PYTHON_THREAD_END_BLOCK)
+# define SWIG_PYTHON_THREAD_END_BLOCK
+# endif
+# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW)
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+# endif
+# if !defined(SWIG_PYTHON_THREAD_END_ALLOW)
+# define SWIG_PYTHON_THREAD_END_ALLOW
+# endif
+# endif
+#else /* No thread support */
+# define SWIG_PYTHON_INITIALIZE_THREADS
+# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+# define SWIG_PYTHON_THREAD_END_BLOCK
+# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+# define SWIG_PYTHON_THREAD_END_ALLOW
+#endif
diff --git a/contrib/tools/swig/Lib/python/pytypemaps.swg b/contrib/tools/swig/Lib/python/pytypemaps.swg
new file mode 100644
index 00000000000..f4a6e457705
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pytypemaps.swg
@@ -0,0 +1,103 @@
+/* ------------------------------------------------------------
+ * Typemap specializations for Python
+ * ------------------------------------------------------------ */
+
+/* ------------------------------------------------------------
+ * Fragment section
+ * ------------------------------------------------------------ */
+#ifdef SWIG_PYTHON_LEGACY_BOOL
+// Default prior to SWIG 3.0.0
+#undef SWIG_TYPECHECK_BOOL
+%define SWIG_TYPECHECK_BOOL 10000 %enddef
+#endif
+
+/* Include fundamental fragment definitions */
+%include <typemaps/fragments.swg>
+
+/* Look for user fragments file. */
+%include <pyfragments.swg>
+
+/* Python fragments for fundamental types */
+%include <pyprimtypes.swg>
+
+/* Python fragments for char* strings */
+%include <pystrings.swg>
+
+
+/* ------------------------------------------------------------
+ * Unified typemap section
+ * ------------------------------------------------------------ */
+
+/* directors are supported in Python */
+#ifndef SWIG_DIRECTOR_TYPEMAPS
+#define SWIG_DIRECTOR_TYPEMAPS
+#endif
+
+
+/* Python types */
+#define SWIG_Object PyObject *
+#define VOID_Object SWIG_Py_Void()
+
+/* Python allows implicit conversion */
+#define %implicitconv_flag $implicitconv
+
+
+/* Overload of the output/constant/exception/dirout handling */
+
+/* append output */
+#define SWIG_AppendOutput(result, obj) SWIG_Python_AppendOutput(result, obj, $isvoid)
+
+/* set constant */
+#if defined(SWIGPYTHON_BUILTIN)
+#define SWIG_SetConstant(name, obj) SWIG_Python_SetConstant(d, d == md ? public_interface : NULL, name,obj)
+#else
+#define SWIG_SetConstant(name, obj) SWIG_Python_SetConstant(d, name,obj)
+#endif
+
+/* raise */
+#define SWIG_Raise(obj, type, desc) SWIG_Python_Raise(obj, type, desc)
+
+/* clear errors */
+#define %error_clear PyErr_Clear()
+
+/* Include the unified typemap library */
+%include <typemaps/swigtypemaps.swg>
+
+
+/* ------------------------------------------------------------
+ * Python extra typemaps / typemap overrides
+ * ------------------------------------------------------------ */
+
+/* Get the address of the 'python self' object */
+
+%typemap(in,numinputs=0,noblock=1) PyObject **PYTHON_SELF {
+ $1 = &$self;
+}
+
+
+/* Consttab, needed for callbacks, it should be removed later */
+
+%typemap(consttab) SWIGTYPE ((*)(ANY))
+{ SWIG_PY_POINTER, "$symname", 0, 0, (void *)($value), &$descriptor }
+%typemap(consttab) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY));
+
+%typemap(constcode) SWIGTYPE ((*)(ANY)) ""
+%typemap(constcode) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY));
+
+
+/* Smart Pointers */
+%typemap(out,noblock=1) const SWIGTYPE & SMARTPOINTER {
+ $result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor, SWIG_POINTER_OWN | %newpointer_flags);
+}
+
+%typemap(ret,noblock=1) const SWIGTYPE & SMARTPOINTER, SWIGTYPE SMARTPOINTER {
+ if ($result) {
+ PyObject *robj = PyObject_CallMethod($result, (char *)"__deref__", NULL);
+ if (robj && !PyErr_Occurred()) {
+ SwigPyObject_append((PyObject *) SWIG_Python_GetSwigThis($result),
+ (PyObject *) SWIG_Python_GetSwigThis(robj));
+ SWIG_Py_DECREF(robj);
+ }
+ }
+}
+
diff --git a/contrib/tools/swig/Lib/python/pyuserdir.swg b/contrib/tools/swig/Lib/python/pyuserdir.swg
new file mode 100644
index 00000000000..3110760793e
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pyuserdir.swg
@@ -0,0 +1,242 @@
+/* -------------------------------------------------------------------------
+ * Special user directives
+ * ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+
+/* shadow code */
+#define %shadow %insert("shadow")
+#define %pythoncode %insert("python")
+#define %pythonbegin %insert("pythonbegin")
+
+
+/* ------------------------------------------------------------------------- */
+/*
+Use the "nondynamic" feature to make a wrapped class behave as a "nondynamic"
+one, ie, a python class that doesn't dynamically add new attributes.
+
+For example, for the class
+
+%pythonnondynamic A;
+struct A
+{
+ int a;
+ int b;
+};
+
+you will get:
+
+ aa = A()
+ aa.a = 1 # Ok
+ aa.b = 1 # Ok
+ aa.c = 3 # error
+
+Since nondynamic is a feature, if you use it like
+
+ %pythonnondynamic;
+
+it will make all the wrapped classes nondynamic ones.
+
+The implementation is based on this recipe:
+
+ http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252158
+
+*/
+
+#define %pythonnondynamic %feature("python:nondynamic", "1")
+#define %nopythonnondynamic %feature("python:nondynamic", "0")
+#define %clearpythonnondynamic %feature("python:nondynamic", "")
+#define %pythondynamic %nopythonnondynamic
+
+
+/* ------------------------------------------------------------------------- */
+/*
+
+Use %pythonmaybecall to flag a method like __add__ or __radd__. These
+don't produce an error when called, they just return NotImplemented.
+
+These methods "may be called" if needed.
+
+*/
+
+#define %pythonmaybecall %feature("python:maybecall", "1")
+#define %nopythonmaybecall %feature("python:maybecall", "0")
+#define %clearpythonmaybecall %feature("python:maybecall", "")
+
+/* ------------------------------------------------------------------------- */
+/*
+ The %pythoncallback feature produce a more natural callback wrapper
+ than the %callback mechanism, ie, it uses the original name for
+ the callback and callable objects.
+
+ Just use it as
+
+ %pythoncallback(1) foo;
+ int foo(int a);
+
+ %pythoncallback(1) A::foo;
+ struct A {
+ static int foo(int a);
+ };
+
+ int bar(int, int (*pf)(int));
+
+ then, you can use it as:
+
+ a = foo(1)
+ b = bar(2, foo)
+
+ c = A.foo(3)
+ d = bar(4, A.foo)
+
+
+ If you use it with a member method
+ %pythoncallback(1) A::foom;
+ struct A {
+ int foom(int a);
+ };
+
+ then you can use it as
+
+ r = a.foom(3) # eval the method
+ mptr = A.foom_cb_ptr # returns the callback pointer
+
+ where the '_cb_ptr' suffix is added for the callback pointer.
+
+*/
+
+#define %pythoncallback %feature("python:callback")
+#define %nopythoncallback %feature("python:callback","0")
+#define %clearpythoncallback %feature("python:callback","")
+
+/* ------------------------------------------------------------------------- */
+/*
+ Support for the old %callback directive name
+*/
+#ifdef %callback
+#undef %callback
+#endif
+
+#ifdef %nocallback
+#undef %nocallback
+#endif
+
+#ifdef %clearcallback
+#undef %clearcallback
+#endif
+
+#define %callback(x) %feature("python:callback",`x`)
+#define %nocallback %nopythoncallback
+#define %clearcallback %clearpythoncallback
+
+/* ------------------------------------------------------------------------- */
+/*
+ Thread support - Advance control
+
+*/
+
+#define %nothread %feature("nothread")
+#define %thread %feature("nothread","0")
+#define %clearnothread %feature("nothread","")
+
+#define %nothreadblock %feature("nothreadblock")
+#define %threadblock %feature("nothreadblock","0")
+#define %clearnothreadblock %feature("nothreadblock","")
+
+#define %nothreadallow %feature("nothreadallow")
+#define %threadallow %feature("nothreadallow","0")
+#define %clearnothreadallow %feature("nothreadallow","")
+
+
+/* ------------------------------------------------------------------------- */
+/*
+ Implicit Conversion using the C++ constructor mechanism
+*/
+
+#define %implicitconv %feature("implicitconv")
+#define %noimplicitconv %feature("implicitconv", "0")
+#define %clearimplicitconv %feature("implicitconv", "")
+
+
+/* ------------------------------------------------------------------------- */
+/*
+ Enable keywords parameters
+*/
+
+#define %kwargs %feature("kwargs")
+#define %nokwargs %feature("kwargs", "0")
+#define %clearkwargs %feature("kwargs", "")
+
+/* ------------------------------------------------------------------------- */
+/*
+ Add python code to the proxy/shadow code
+
+ %pythonprepend - Add code before the C++ function is called
+ %pythonappend - Add code after the C++ function is called
+*/
+
+#define %pythonprepend %feature("pythonprepend")
+#define %clearpythonprepend %feature("pythonprepend","")
+
+#define %pythonappend %feature("pythonappend")
+#define %clearpythonappend %feature("pythonappend","")
+
+
+/* ------------------------------------------------------------------------- */
+/*
+ %extend_smart_pointer extend the smart pointer support.
+
+ For example, if you have a smart pointer as:
+
+ template <class Type> class RCPtr {
+ public:
+ ...
+ RCPtr(Type *p);
+ Type * operator->() const;
+ ...
+ };
+
+ you use the %extend_smart_pointer directive as:
+
+ %extend_smart_pointer(RCPtr<A>);
+ %template(RCPtr_A) RCPtr<A>;
+
+ then, if you have something like:
+
+ RCPtr<A> make_ptr();
+ int foo(A *);
+
+ you can do the following:
+
+ a = make_ptr();
+ b = foo(a);
+
+ ie, swig will accept a RCPtr<A> object where a 'A *' is
+ expected.
+
+ Also, when using vectors
+
+ %extend_smart_pointer(RCPtr<A>);
+ %template(RCPtr_A) RCPtr<A>;
+ %template(vector_A) std::vector<RCPtr<A> >;
+
+ you can type
+
+ a = A();
+ v = vector_A(2)
+ v[0] = a
+
+ ie, an 'A *' object is accepted, via implicit conversion,
+ where a RCPtr<A> object is expected. Additionally
+
+ x = v[0]
+
+ returns (and sets 'x' as) a copy of v[0], making reference
+ counting possible and consistent.
+*/
+
+%define %extend_smart_pointer(Type...)
+%implicitconv Type;
+%apply const SWIGTYPE& SMARTPOINTER { const Type& };
+%apply SWIGTYPE SMARTPOINTER { Type };
+%enddef
diff --git a/contrib/tools/swig/Lib/python/pywstrings.swg b/contrib/tools/swig/Lib/python/pywstrings.swg
new file mode 100644
index 00000000000..903885abb58
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/pywstrings.swg
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------
+ * utility methods for wchar_t strings
+ * ------------------------------------------------------------ */
+
+%{
+#if PY_VERSION_HEX >= 0x03020000
+# define SWIGPY_UNICODE_ARG(obj) ((PyObject*) (obj))
+#else
+# define SWIGPY_UNICODE_ARG(obj) ((PyUnicodeObject*) (obj))
+#endif
+%}
+
+%fragment("SWIG_AsWCharPtrAndSize","header",fragment="<wchar.h>",fragment="SWIG_pwchar_descriptor") {
+SWIGINTERN int
+SWIG_AsWCharPtrAndSize(PyObject *obj, wchar_t **cptr, size_t *psize, int *alloc)
+{
+ PyObject *tmp = 0;
+ int isunicode = PyUnicode_Check(obj);
+%#if PY_VERSION_HEX < 0x03000000 && !defined(SWIG_PYTHON_STRICT_UNICODE_WCHAR)
+ if (!isunicode && PyString_Check(obj)) {
+ tmp = PyUnicode_FromObject(obj);
+ if (tmp) {
+ isunicode = 1;
+ obj = tmp;
+ } else {
+ PyErr_Clear();
+ return SWIG_TypeError;
+ }
+ }
+%#endif
+ if (isunicode) {
+%#if PY_VERSION_HEX >= 0x03030000
+%# if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
+ Py_ssize_t len = PyUnicode_GetLength(obj);
+%# else
+ Py_ssize_t len = PyUnicode_AsWideChar(SWIGPY_UNICODE_ARG(obj), NULL, 0) - 1;
+%# endif
+%#else
+ Py_ssize_t len = PyUnicode_GetSize(obj);
+%#endif
+ if (cptr) {
+ Py_ssize_t length;
+ *cptr = %new_array(len + 1, wchar_t);
+ length = PyUnicode_AsWideChar(SWIGPY_UNICODE_ARG(obj), *cptr, len);
+ if (length == -1) {
+ PyErr_Clear();
+ SWIG_Py_XDECREF(tmp);
+ return SWIG_TypeError;
+ }
+ (*cptr)[length] = 0;
+ }
+ if (psize) *psize = (size_t) len + 1;
+ if (alloc) *alloc = cptr ? SWIG_NEWOBJ : 0;
+ SWIG_Py_XDECREF(tmp);
+ return SWIG_OK;
+ } else {
+ swig_type_info* pwchar_descriptor = SWIG_pwchar_descriptor();
+ if (pwchar_descriptor) {
+ void * vptr = 0;
+ if (SWIG_ConvertPtr(obj, &vptr, pwchar_descriptor, 0) == SWIG_OK) {
+ if (cptr) *cptr = (wchar_t *)vptr;
+ if (psize) *psize = vptr ? (wcslen((wchar_t *)vptr) + 1) : 0;
+ return SWIG_OK;
+ }
+ }
+ }
+ return SWIG_TypeError;
+}
+}
+
+%fragment("SWIG_FromWCharPtrAndSize","header",fragment="<wchar.h>",fragment="SWIG_pwchar_descriptor") {
+SWIGINTERNINLINE PyObject *
+SWIG_FromWCharPtrAndSize(const wchar_t * carray, size_t size)
+{
+ if (carray) {
+ if (size > INT_MAX) {
+ swig_type_info* pwchar_descriptor = SWIG_pwchar_descriptor();
+ return pwchar_descriptor ?
+ SWIG_InternalNewPointerObj(%const_cast(carray,wchar_t *), pwchar_descriptor, 0) : SWIG_Py_Void();
+ } else {
+ return PyUnicode_FromWideChar(carray, %numeric_cast(size, Py_ssize_t));
+ }
+ } else {
+ return SWIG_Py_Void();
+ }
+}
+}
+
+
diff --git a/contrib/tools/swig/Lib/python/std_alloc.i b/contrib/tools/swig/Lib/python/std_alloc.i
new file mode 100644
index 00000000000..35dc051beab
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_alloc.i
@@ -0,0 +1 @@
+%include <std/std_alloc.i>
diff --git a/contrib/tools/swig/Lib/python/std_array.i b/contrib/tools/swig/Lib/python/std_array.i
new file mode 100644
index 00000000000..707b354750b
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_array.i
@@ -0,0 +1,119 @@
+/*
+ std::array
+*/
+
+%fragment("StdArrayTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T, size_t N>
+ struct traits_asptr<std::array<T, N> > {
+ static int asptr(PyObject *obj, std::array<T, N> **vec) {
+ return traits_asptr_stdseq<std::array<T, N> >::asptr(obj, vec);
+ }
+ };
+
+ template <class T, size_t N>
+ struct traits_from<std::array<T, N> > {
+ static PyObject *from(const std::array<T, N>& vec) {
+ return traits_from_stdseq<std::array<T, N> >::from(vec);
+ }
+ };
+
+ template <class T, size_t N>
+ struct IteratorProtocol<std::array<T, N>, T> {
+
+ static void assign(PyObject *obj, std::array<T, N> *seq) {
+ SwigVar_PyObject iter = PyObject_GetIter(obj);
+ if (iter) {
+ SwigVar_PyObject item = PyIter_Next(iter);
+ size_t count = 0;
+ typename std::array<T, N>::iterator array_iter = seq->begin();
+ while (item && (count < N)) {
+ ++count;
+ *array_iter++ = swig::as<T>(item);
+ item = PyIter_Next(iter);
+ }
+ if (count != N || item)
+ throw std::invalid_argument("std::array size does not match source container size");
+ }
+ }
+
+ static bool check(PyObject *obj) {
+ bool ret = false;
+ SwigVar_PyObject iter = PyObject_GetIter(obj);
+ if (iter) {
+ SwigVar_PyObject item = PyIter_Next(iter);
+ size_t count = 0;
+ ret = true;
+ while (item && (count < N)) {
+ ++count;
+ ret = swig::check<T>(item);
+ item = ret ? PyIter_Next(iter) : 0;
+ }
+ if (count != N || item)
+ ret = false;
+ }
+ return ret;
+ }
+ };
+
+ template <class T, size_t N>
+ inline void
+ erase(std::array<T, N>* SWIGUNUSEDPARM(seq), const typename std::array<T, N>::iterator& SWIGUNUSEDPARM(position)) {
+ throw std::invalid_argument("std::array object does not support item deletion");
+ }
+
+ // Only limited slicing is supported as std::array is fixed in size
+ template <class T, size_t N, class Difference>
+ inline std::array<T, N>*
+ getslice(const std::array<T, N>* self, Difference i, Difference j, Py_ssize_t step) {
+ typedef std::array<T, N> Sequence;
+ typename Sequence::size_type size = self->size();
+ Difference ii = 0;
+ Difference jj = 0;
+ swig::slice_adjust(i, j, step, size, ii, jj);
+
+ if (step == 1 && ii == 0 && static_cast<typename Sequence::size_type>(jj) == size) {
+ Sequence *sequence = new Sequence();
+ std::copy(self->begin(), self->end(), sequence->begin());
+ return sequence;
+ } else if (step == -1 && static_cast<typename Sequence::size_type>(ii) == (size - 1) && jj == -1) {
+ Sequence *sequence = new Sequence();
+ std::copy(self->rbegin(), self->rend(), sequence->begin());
+ return sequence;
+ } else {
+ throw std::invalid_argument("std::array object only supports getting a slice that is the size of the array");
+ }
+ }
+
+ template <class T, size_t N, class Difference, class InputSeq>
+ inline void
+ setslice(std::array<T, N>* self, Difference i, Difference j, Py_ssize_t step, const InputSeq& is = InputSeq()) {
+ typedef std::array<T, N> Sequence;
+ typename Sequence::size_type size = self->size();
+ Difference ii = 0;
+ Difference jj = 0;
+ swig::slice_adjust(i, j, step, size, ii, jj, true);
+
+ if (step == 1 && ii == 0 && static_cast<typename Sequence::size_type>(jj) == size) {
+ std::copy(is.begin(), is.end(), self->begin());
+ } else if (step == -1 && static_cast<typename Sequence::size_type>(ii) == (size - 1) && jj == -1) {
+ std::copy(is.rbegin(), is.rend(), self->begin());
+ } else {
+ throw std::invalid_argument("std::array object only supports setting a slice that is the size of the array");
+ }
+ }
+
+ template <class T, size_t N, class Difference>
+ inline void
+ delslice(std::array<T, N>* SWIGUNUSEDPARM(self), Difference SWIGUNUSEDPARM(i), Difference SWIGUNUSEDPARM(j), Py_ssize_t SWIGUNUSEDPARM(step)) {
+ throw std::invalid_argument("std::array object does not support item deletion");
+ }
+ }
+%}
+
+#define %swig_array_methods(Type...) %swig_sequence_methods_non_resizable(Type)
+#define %swig_array_methods_val(Type...) %swig_sequence_methods_non_resizable_val(Type);
+
+%include <std/std_array.i>
+
diff --git a/contrib/tools/swig/Lib/python/std_auto_ptr.i b/contrib/tools/swig/Lib/python/std_auto_ptr.i
new file mode 100644
index 00000000000..3d7ae8ba16e
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_auto_ptr.i
@@ -0,0 +1,39 @@
+/* -----------------------------------------------------------------------------
+ * std_auto_ptr.i
+ *
+ * SWIG library file for handling std::auto_ptr.
+ * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
+ * class when returning a std::auto_ptr from a function.
+ * Memory ownership is passed from the proxy class to the std::auto_ptr in the
+ * C++ layer when passed as a parameter to a wrapped function.
+ * ----------------------------------------------------------------------------- */
+
+%define %auto_ptr(TYPE)
+%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "TYPE *", $symname, $argnum);
+ } else {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ }
+ $1.reset((TYPE *)argp);
+}
+
+%typemap (out) std::auto_ptr< TYPE > %{
+ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
+%}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0);
+ $1 = SWIG_CheckState(res);
+}
+
+%template() std::auto_ptr< TYPE >;
+%enddef
+
+namespace std {
+ template <class T> class auto_ptr {};
+}
diff --git a/contrib/tools/swig/Lib/python/std_basic_string.i b/contrib/tools/swig/Lib/python/std_basic_string.i
new file mode 100644
index 00000000000..e3f524dbdad
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_basic_string.i
@@ -0,0 +1,89 @@
+#if !defined(SWIG_STD_STRING)
+#define SWIG_STD_BASIC_STRING
+
+%include <pycontainer.swg>
+
+#define %swig_basic_string(Type...) %swig_sequence_methods_val(Type)
+
+
+%fragment(SWIG_AsPtr_frag(std::basic_string<char>),"header",
+ fragment="SWIG_AsCharPtrAndSize") {
+SWIGINTERN int
+SWIG_AsPtr(std::basic_string<char>)(PyObject* obj, std::string **val) {
+ static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string<char> *");
+ std::string *vptr;
+ if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) {
+ if (val) *val = vptr;
+ return SWIG_OLDOBJ;
+ } else {
+ PyErr_Clear();
+ char* buf = 0 ; size_t size = 0; int alloc = 0;
+ if (SWIG_IsOK(SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc))) {
+ if (buf) {
+ if (val) *val = new std::string(buf, size - 1);
+ if (alloc == SWIG_NEWOBJ) %delete_array(buf);
+ return SWIG_NEWOBJ;
+ } else {
+ if (val) *val = 0;
+ return SWIG_OLDOBJ;
+ }
+ }
+ return SWIG_ERROR;
+ }
+}
+}
+
+%fragment(SWIG_From_frag(std::basic_string<char>),"header",
+ fragment="SWIG_FromCharPtrAndSize") {
+SWIGINTERNINLINE PyObject*
+ SWIG_From(std::basic_string<char>)(const std::string& s) {
+ return SWIG_FromCharPtrAndSize(s.data(), s.size());
+ }
+}
+
+%include <std/std_basic_string.i>
+%typemaps_asptrfromn(%checkcode(STRING), std::basic_string<char>);
+
+#endif
+
+
+#if !defined(SWIG_STD_WSTRING)
+
+%fragment(SWIG_AsPtr_frag(std::basic_string<wchar_t>),"header",
+ fragment="SWIG_AsWCharPtrAndSize") {
+SWIGINTERN int
+SWIG_AsPtr(std::basic_string<wchar_t>)(PyObject* obj, std::wstring **val) {
+ static swig_type_info* string_info = SWIG_TypeQuery("std::basic_string<wchar_t> *");
+ std::wstring *vptr;
+ if (SWIG_IsOK(SWIG_ConvertPtr(obj, (void**)&vptr, string_info, 0))) {
+ if (val) *val = vptr;
+ return SWIG_OLDOBJ;
+ } else {
+ PyErr_Clear();
+ wchar_t *buf = 0 ; size_t size = 0; int alloc = 0;
+ if (SWIG_IsOK(SWIG_AsWCharPtrAndSize(obj, &buf, &size, &alloc))) {
+ if (buf) {
+ if (val) *val = new std::wstring(buf, size - 1);
+ if (alloc == SWIG_NEWOBJ) %delete_array(buf);
+ return SWIG_NEWOBJ;
+ } else {
+ if (val) *val = 0;
+ return SWIG_OLDOBJ;
+ }
+ }
+ return SWIG_ERROR;
+ }
+}
+}
+
+%fragment(SWIG_From_frag(std::basic_string<wchar_t>),"header",
+ fragment="SWIG_FromWCharPtrAndSize") {
+SWIGINTERNINLINE PyObject*
+ SWIG_From(std::basic_string<wchar_t>)(const std::wstring& s) {
+ return SWIG_FromWCharPtrAndSize(s.data(), s.size());
+ }
+}
+
+%typemaps_asptrfromn(%checkcode(UNISTRING), std::basic_string<wchar_t>);
+
+#endif
diff --git a/contrib/tools/swig/Lib/python/std_char_traits.i b/contrib/tools/swig/Lib/python/std_char_traits.i
new file mode 100644
index 00000000000..bf4e6c47dd4
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_char_traits.i
@@ -0,0 +1 @@
+%include <std/std_char_traits.i>
diff --git a/contrib/tools/swig/Lib/python/std_common.i b/contrib/tools/swig/Lib/python/std_common.i
new file mode 100644
index 00000000000..605766238bb
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_common.i
@@ -0,0 +1,74 @@
+%include <std/std_except.i>
+%include <pystdcommon.swg>
+
+
+/*
+ Generate the traits for a 'primitive' type, such as 'double',
+ for which the SWIG_AsVal and SWIG_From methods are already defined.
+*/
+
+%define %traits_ptypen(Type...)
+ %fragment(SWIG_Traits_frag(Type),"header",
+ fragment=SWIG_AsVal_frag(Type),
+ fragment=SWIG_From_frag(Type),
+ fragment="StdTraits") {
+namespace swig {
+ template <> struct traits< Type > {
+ typedef value_category category;
+ static const char* type_name() { return #Type; }
+ };
+ template <> struct traits_asval< Type > {
+ typedef Type value_type;
+ static int asval(PyObject *obj, value_type *val) {
+ return SWIG_AsVal(Type)(obj, val);
+ }
+ };
+ template <> struct traits_from< Type > {
+ typedef Type value_type;
+ static PyObject *from(const value_type& val) {
+ return SWIG_From(Type)(val);
+ }
+ };
+}
+}
+%enddef
+
+/* Traits for enums. This is bit of a sneaky trick needed because a generic template specialization of enums
+ is not possible (unless using template meta-programming which SWIG doesn't support because of the explicit
+ instantiations required using %template). The STL containers define the 'front' method and the typemap
+ below is used whenever the front method is wrapped returning an enum. This typemap simply picks up the
+ standard enum typemap, but additionally drags in a fragment containing the traits_asval and traits_from
+ required in the generated code for enums. */
+
+%define %traits_enum(Type...)
+ %fragment("SWIG_Traits_enum_"{Type},"header",
+ fragment=SWIG_AsVal_frag(int),
+ fragment=SWIG_From_frag(int),
+ fragment="StdTraits") {
+namespace swig {
+ template <> struct traits_asval< Type > {
+ typedef Type value_type;
+ static int asval(PyObject *obj, value_type *val) {
+ return SWIG_AsVal(int)(obj, (int *)val);
+ }
+ };
+ template <> struct traits_from< Type > {
+ typedef Type value_type;
+ static PyObject *from(const value_type& val) {
+ return SWIG_From(int)((int)val);
+ }
+ };
+}
+}
+%typemap(out, fragment="SWIG_Traits_enum_"{Type}) const enum SWIGTYPE& front %{$typemap(out, const enum SWIGTYPE&)%}
+%enddef
+
+
+%include <std/std_common.i>
+
+//
+// Generates the traits for all the known primitive
+// C++ types (int, double, ...)
+//
+%apply_cpptypes(%traits_ptypen);
+
diff --git a/contrib/tools/swig/Lib/python/std_complex.i b/contrib/tools/swig/Lib/python/std_complex.i
new file mode 100644
index 00000000000..c9c46c4c3bb
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_complex.i
@@ -0,0 +1,27 @@
+/*
+ * STD C++ complex typemaps
+ */
+
+%include <pycomplex.swg>
+
+%{
+#include <complex>
+%}
+
+namespace std {
+ %naturalvar complex;
+ template<typename T> class complex;
+ %template() complex<double>;
+ %template() complex<float>;
+}
+
+/* defining the complex as/from converters */
+
+%swig_cplxdbl_convn(std::complex<double>, std::complex<double>, std::real, std::imag)
+%swig_cplxflt_convn(std::complex<float>, std::complex<float>, std::real, std::imag)
+
+/* defining the typemaps */
+
+%typemaps_primitive(%checkcode(CPLXDBL), std::complex<double>);
+%typemaps_primitive(%checkcode(CPLXFLT), std::complex<float>);
+
diff --git a/contrib/tools/swig/Lib/python/std_container.i b/contrib/tools/swig/Lib/python/std_container.i
new file mode 100644
index 00000000000..d24c1570f1d
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_container.i
@@ -0,0 +1,2 @@
+%include <pycontainer.swg>
+%include <std/std_container.i>
diff --git a/contrib/tools/swig/Lib/python/std_deque.i b/contrib/tools/swig/Lib/python/std_deque.i
new file mode 100644
index 00000000000..d9a174706b3
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_deque.i
@@ -0,0 +1,27 @@
+/*
+ Deques
+*/
+
+%fragment("StdDequeTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T>
+ struct traits_asptr<std::deque<T> > {
+ static int asptr(PyObject *obj, std::deque<T> **vec) {
+ return traits_asptr_stdseq<std::deque<T> >::asptr(obj, vec);
+ }
+ };
+
+ template <class T>
+ struct traits_from<std::deque<T> > {
+ static PyObject *from(const std::deque<T>& vec) {
+ return traits_from_stdseq<std::deque<T> >::from(vec);
+ }
+ };
+ }
+%}
+
+#define %swig_deque_methods(Type...) %swig_sequence_methods(Type)
+#define %swig_deque_methods_val(Type...) %swig_sequence_methods_val(Type);
+
+%include <std/std_deque.i>
diff --git a/contrib/tools/swig/Lib/python/std_except.i b/contrib/tools/swig/Lib/python/std_except.i
new file mode 100644
index 00000000000..af98428f65d
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_except.i
@@ -0,0 +1 @@
+%include <typemaps/std_except.swg>
diff --git a/contrib/tools/swig/Lib/python/std_filesystem.i b/contrib/tools/swig/Lib/python/std_filesystem.i
new file mode 100644
index 00000000000..4fd1161424a
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_filesystem.i
@@ -0,0 +1,127 @@
+/* -----------------------------------------------------------------------------
+ * std_filesystem.i
+ *
+ * SWIG typemaps for std::filesystem::path
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <filesystem>
+%}
+
+namespace std {
+ namespace filesystem {
+ class path;
+ }
+}
+
+%fragment("SWIG_std_filesystem", "header") {
+SWIGINTERN PyObject *SWIG_std_filesystem_importPathClass() {
+ PyObject *module = PyImport_ImportModule("pathlib");
+ PyObject *cls = PyObject_GetAttrString(module, "Path");
+ SWIG_Py_DECREF(module);
+ return cls;
+}
+
+SWIGINTERN bool SWIG_std_filesystem_isPathInstance(PyObject *obj) {
+ PyObject *cls = SWIG_std_filesystem_importPathClass();
+ bool is_instance = PyObject_IsInstance(obj, cls);
+ SWIG_Py_DECREF(cls);
+ return is_instance;
+}
+}
+
+%typemap(in, fragment="SWIG_std_filesystem", fragment="<type_traits>") std::filesystem::path {
+ if (PyUnicode_Check($input)) {
+ PyObject *bytes = NULL;
+ const char *s = SWIG_PyUnicode_AsUTF8AndSize($input, NULL, &bytes);
+ $1 = std::filesystem::path(s);
+ SWIG_Py_XDECREF(bytes);
+ } else if (SWIG_std_filesystem_isPathInstance($input)) {
+ PyObject *str_obj = PyObject_Str($input);
+ if constexpr (std::is_same_v<typename std::filesystem::path::value_type, wchar_t>) {
+ Py_ssize_t size = 0;
+ wchar_t *ws = PyUnicode_AsWideCharString(str_obj, &size);
+ if (!ws) SWIG_fail;
+ $1 = std::filesystem::path(std::wstring(ws, static_cast<size_t>(size)));
+ PyMem_Free(ws);
+ } else {
+ PyObject *bytes = NULL;
+ const char *s = SWIG_PyUnicode_AsUTF8AndSize(str_obj, NULL, &bytes);
+ $1 = std::filesystem::path(s);
+ SWIG_Py_XDECREF(bytes);
+ }
+ SWIG_Py_DECREF(str_obj);
+ } else {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $descriptor(std::filesystem::path *), $disown | 0);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ std::filesystem::path *temp = %reinterpret_cast(argp, $1_ltype*);
+ $1 = *temp;
+ }
+}
+
+%typemap(in, fragment="SWIG_std_filesystem", fragment="<type_traits>") const std::filesystem::path &(std::filesystem::path temp_path) {
+ if (PyUnicode_Check($input)) {
+ PyObject *bytes = NULL;
+ const char *s = SWIG_PyUnicode_AsUTF8AndSize($input, NULL, &bytes);
+ temp_path = std::filesystem::path(s);
+ $1 = &temp_path;
+ SWIG_Py_XDECREF(bytes);
+ } else if (SWIG_std_filesystem_isPathInstance($input)) {
+ PyObject *str_obj = PyObject_Str($input);
+ if constexpr (std::is_same_v<typename std::filesystem::path::value_type, wchar_t>) {
+ Py_ssize_t size = 0;
+ wchar_t *ws = PyUnicode_AsWideCharString(str_obj, &size);
+ if (!ws) SWIG_fail;
+ temp_path = std::filesystem::path(std::wstring(ws, static_cast<size_t>(size)));
+ $1 = &temp_path;
+ PyMem_Free(ws);
+ } else {
+ PyObject *bytes = NULL;
+ const char *s = SWIG_PyUnicode_AsUTF8AndSize(str_obj, NULL, &bytes);
+ temp_path = std::filesystem::path(s);
+ $1 = &temp_path;
+ SWIG_Py_XDECREF(bytes);
+ }
+ SWIG_Py_DECREF(str_obj);
+ } else {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $descriptor, $disown | 0);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ $1 = %reinterpret_cast(argp, $1_ltype);
+ }
+}
+
+%typemap(out, fragment="SWIG_std_filesystem", fragment="<type_traits>") std::filesystem::path {
+ PyObject *args;
+ if constexpr (std::is_same_v<typename std::filesystem::path::value_type, wchar_t>) {
+ std::wstring s = $1.generic_wstring();
+ args = Py_BuildValue("(u)", s.data());
+ } else {
+ std::string s = $1.generic_string();
+ args = Py_BuildValue("(s)", s.data());
+ }
+ PyObject *cls = SWIG_std_filesystem_importPathClass();
+ $result = PyObject_CallObject(cls, args);
+ SWIG_Py_DECREF(cls);
+ SWIG_Py_DECREF(args);
+}
+
+%typemap(out, fragment="SWIG_std_filesystem", fragment="<type_traits>") const std::filesystem::path & {
+ PyObject *args;
+ if constexpr (std::is_same_v<typename std::filesystem::path::value_type, wchar_t>) {
+ std::wstring s = $1->generic_wstring();
+ args = Py_BuildValue("(u)", s.data());
+ } else {
+ std::string s = $1->generic_string();
+ args = Py_BuildValue("(s)", s.data());
+ }
+ PyObject *cls = SWIG_std_filesystem_importPathClass();
+ $result = PyObject_CallObject(cls, args);
+ SWIG_Py_DECREF(cls);
+ SWIG_Py_DECREF(args);
+}
diff --git a/contrib/tools/swig/Lib/python/std_ios.i b/contrib/tools/swig/Lib/python/std_ios.i
new file mode 100644
index 00000000000..aa6f0994d76
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_ios.i
@@ -0,0 +1,3 @@
+%rename(ios_base_in) std::ios_base::in;
+
+%include <std/std_ios.i>
diff --git a/contrib/tools/swig/Lib/python/std_iostream.i b/contrib/tools/swig/Lib/python/std_iostream.i
new file mode 100644
index 00000000000..43d6b0c24be
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_iostream.i
@@ -0,0 +1,8 @@
+namespace std
+{
+%callback(1) endl;
+%callback(1) ends;
+%callback(1) flush;
+}
+
+%include <std/std_iostream.i>
diff --git a/contrib/tools/swig/Lib/python/std_list.i b/contrib/tools/swig/Lib/python/std_list.i
new file mode 100644
index 00000000000..24d274b423f
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_list.i
@@ -0,0 +1,28 @@
+/*
+ Lists
+*/
+
+%fragment("StdListTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T >
+ struct traits_asptr<std::list<T> > {
+ static int asptr(PyObject *obj, std::list<T> **lis) {
+ return traits_asptr_stdseq<std::list<T> >::asptr(obj, lis);
+ }
+ };
+
+ template <class T>
+ struct traits_from<std::list<T> > {
+ static PyObject *from(const std::list<T>& vec) {
+ return traits_from_stdseq<std::list<T> >::from(vec);
+ }
+ };
+ }
+%}
+
+#define %swig_list_methods(Type...) %swig_sequence_methods(Type)
+#define %swig_list_methods_val(Type...) %swig_sequence_methods_val(Type);
+
+%include <std/std_list.i>
+
diff --git a/contrib/tools/swig/Lib/python/std_map.i b/contrib/tools/swig/Lib/python/std_map.i
new file mode 100644
index 00000000000..954e7eb2d9a
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_map.i
@@ -0,0 +1,304 @@
+/*
+ Maps
+*/
+
+%fragment("StdMapCommonTraits","header",fragment="StdSequenceTraits",fragment="SwigPyIterator_T")
+{
+ namespace swig {
+ template <class ValueType>
+ struct from_key_oper
+ {
+ typedef const ValueType& argument_type;
+ typedef PyObject *result_type;
+ result_type operator()(argument_type v) const
+ {
+ return swig::from(v.first);
+ }
+ };
+
+ template <class ValueType>
+ struct from_value_oper
+ {
+ typedef const ValueType& argument_type;
+ typedef PyObject *result_type;
+ result_type operator()(argument_type v) const
+ {
+ return swig::from(v.second);
+ }
+ };
+
+ template<class OutIterator, class FromOper, class ValueType = typename OutIterator::value_type>
+ struct SwigPyMapIterator_T : SwigPyIteratorClosed_T<OutIterator, ValueType, FromOper>
+ {
+ SwigPyMapIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
+ : SwigPyIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq)
+ {
+ }
+ };
+
+
+ template<class OutIterator,
+ class FromOper = from_key_oper<typename OutIterator::value_type> >
+ struct SwigPyMapKeyIterator_T : SwigPyMapIterator_T<OutIterator, FromOper>
+ {
+ SwigPyMapKeyIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
+ : SwigPyMapIterator_T<OutIterator, FromOper>(curr, first, last, seq)
+ {
+ }
+ };
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_key_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
+ {
+ return new SwigPyMapKeyIterator_T<OutIter>(current, begin, end, seq);
+ }
+
+ template<class OutIterator,
+ class FromOper = from_value_oper<typename OutIterator::value_type> >
+ struct SwigPyMapValueIterator_T : SwigPyMapIterator_T<OutIterator, FromOper>
+ {
+ SwigPyMapValueIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
+ : SwigPyMapIterator_T<OutIterator, FromOper>(curr, first, last, seq)
+ {
+ }
+ };
+
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_value_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
+ {
+ return new SwigPyMapValueIterator_T<OutIter>(current, begin, end, seq);
+ }
+ }
+}
+
+%fragment("StdMapTraits","header",fragment="StdMapCommonTraits")
+{
+ namespace swig {
+ template <class K, class T, class Compare, class Alloc>
+ struct traits_asptr<std::map<K,T,Compare,Alloc > > {
+ typedef std::map<K,T,Compare,Alloc > map_type;
+ static int asptr(PyObject *obj, map_type **val) {
+ int res = SWIG_ERROR;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (PyDict_Check(obj)) {
+ SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
+%#if PY_VERSION_HEX >= 0x03000000
+ /* In Python 3.x the ".items()" method returns a dict_items object */
+ items = PySequence_Fast(items, ".items() didn't return a sequence!");
+%#endif
+ res = traits_asptr_stdseq<map_type, std::pair<K, T> >::asptr(items, val);
+ } else {
+ map_type *p = 0;
+ swig_type_info *descriptor = swig::type_info<map_type>();
+ res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res) && val) *val = p;
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return res;
+ }
+ };
+
+ template <class K, class T, class Compare, class Alloc >
+ struct traits_from<std::map<K,T,Compare,Alloc > > {
+ typedef std::map<K,T,Compare,Alloc > map_type;
+ typedef typename map_type::const_iterator const_iterator;
+ typedef typename map_type::size_type size_type;
+
+ static PyObject *asdict(const map_type& map) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ size_type size = map.size();
+ Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject *obj = PyDict_New();
+ for (const_iterator i= map.begin(); i!= map.end(); ++i) {
+ swig::SwigVar_PyObject key = swig::from(i->first);
+ swig::SwigVar_PyObject val = swig::from(i->second);
+ PyDict_SetItem(obj, key, val);
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return obj;
+ }
+
+ static PyObject *from(const map_type& map) {
+ swig_type_info *desc = swig::type_info<map_type>();
+ if (desc && desc->clientdata) {
+ return SWIG_InternalNewPointerObj(new map_type(map), desc, SWIG_POINTER_OWN);
+ } else {
+ return asdict(map);
+ }
+ }
+ };
+ }
+}
+
+%define %swig_map_common(Map...)
+ %swig_sequence_iterator(Map);
+ %swig_container_methods(Map)
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_length", functype="lenfunc") __len__;
+ %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
+ %feature("python:slot", "tp_iter", functype="getiterfunc") key_iterator;
+ %feature("python:slot", "sq_contains", functype="objobjproc") __contains__;
+
+ %extend {
+ %newobject iterkeys(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* iterkeys(PyObject **PYTHON_SELF) {
+ return swig::make_output_key_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+ %newobject itervalues(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* itervalues(PyObject **PYTHON_SELF) {
+ return swig::make_output_value_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+ %newobject iteritems(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* iteritems(PyObject **PYTHON_SELF) {
+ return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+ }
+
+#else
+ %extend {
+ %pythoncode %{def __iter__(self):
+ return self.key_iterator()%}
+ %pythoncode %{def iterkeys(self):
+ return self.key_iterator()%}
+ %pythoncode %{def itervalues(self):
+ return self.value_iterator()%}
+ %pythoncode %{def iteritems(self):
+ return self.iterator()%}
+ }
+#endif
+
+ %extend {
+ mapped_type const & __getitem__(const key_type& key) throw (std::out_of_range) {
+ Map::const_iterator i = self->find(key);
+ if (i != self->end())
+ return i->second;
+ else
+ throw std::out_of_range("key not found");
+ }
+
+ void __delitem__(const key_type& key) throw (std::out_of_range) {
+ Map::iterator i = self->find(key);
+ if (i != self->end())
+ self->erase(i);
+ else
+ throw std::out_of_range("key not found");
+ }
+
+ bool has_key(const key_type& key) const {
+ Map::const_iterator i = self->find(key);
+ return i != self->end();
+ }
+
+ PyObject* keys() {
+ Map::size_type size = self->size();
+ Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject* keyList = PyList_New(pysize);
+ Map::const_iterator i = self->begin();
+ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
+ PyList_SET_ITEM(keyList, j, swig::from(i->first));
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return keyList;
+ }
+
+ PyObject* values() {
+ Map::size_type size = self->size();
+ Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject* valList = PyList_New(pysize);
+ Map::const_iterator i = self->begin();
+ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
+ PyList_SET_ITEM(valList, j, swig::from(i->second));
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return valList;
+ }
+
+ PyObject* items() {
+ Map::size_type size = self->size();
+ Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject* itemList = PyList_New(pysize);
+ Map::const_iterator i = self->begin();
+ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
+ PyList_SET_ITEM(itemList, j, swig::from(*i));
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return itemList;
+ }
+
+ bool __contains__(const key_type& key) {
+ return self->find(key) != self->end();
+ }
+
+ %newobject key_iterator(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* key_iterator(PyObject **PYTHON_SELF) {
+ return swig::make_output_key_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+ %newobject value_iterator(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* value_iterator(PyObject **PYTHON_SELF) {
+ return swig::make_output_value_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+ }
+
+%enddef
+
+%define %swig_map_methods(Map...)
+ %swig_map_common(Map)
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__;
+#endif
+
+ %extend {
+ // This will be called through the mp_ass_subscript slot to delete an entry.
+ void __setitem__(const key_type& key) {
+ self->erase(key);
+ }
+
+ void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
+%#ifdef __cpp_lib_map_try_emplace
+ (*self).insert_or_assign(key, x);
+%#else
+ (*self)[key] = x;
+%#endif
+ }
+
+ PyObject* asdict() {
+ return swig::traits_from< Map >::asdict(*self);
+ }
+ }
+
+
+%enddef
+
+
+%include <std/std_map.i>
diff --git a/contrib/tools/swig/Lib/python/std_multimap.i b/contrib/tools/swig/Lib/python/std_multimap.i
new file mode 100644
index 00000000000..75b4d7fcfac
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_multimap.i
@@ -0,0 +1,83 @@
+/*
+ Multimaps
+*/
+%include <std_map.i>
+
+%fragment("StdMultimapTraits","header",fragment="StdMapCommonTraits")
+{
+ namespace swig {
+ template <class K, class T>
+ struct traits_asptr<std::multimap<K,T> > {
+ typedef std::multimap<K,T> multimap_type;
+ static int asptr(PyObject *obj, std::multimap<K,T> **val) {
+ int res = SWIG_ERROR;
+ if (PyDict_Check(obj)) {
+ SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
+%#if PY_VERSION_HEX >= 0x03000000
+ /* In Python 3.x the ".items()" method returns a dict_items object */
+ items = PySequence_Fast(items, ".items() didn't return a sequence!");
+%#endif
+ res = traits_asptr_stdseq<std::multimap<K,T>, std::pair<K, T> >::asptr(items, val);
+ } else {
+ multimap_type *p = 0;
+ swig_type_info *descriptor = swig::type_info<multimap_type>();
+ res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res) && val) *val = p;
+ }
+ return res;
+ }
+ };
+
+ template <class K, class T >
+ struct traits_from<std::multimap<K,T> > {
+ typedef std::multimap<K,T> multimap_type;
+ typedef typename multimap_type::const_iterator const_iterator;
+ typedef typename multimap_type::size_type size_type;
+
+ static PyObject *from(const multimap_type& multimap) {
+ swig_type_info *desc = swig::type_info<multimap_type>();
+ if (desc && desc->clientdata) {
+ return SWIG_InternalNewPointerObj(new multimap_type(multimap), desc, SWIG_POINTER_OWN);
+ } else {
+ size_type size = multimap.size();
+ Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ if (pysize < 0) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyErr_SetString(PyExc_OverflowError, "multimap size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject *obj = PyDict_New();
+ for (const_iterator i= multimap.begin(); i!= multimap.end(); ++i) {
+ swig::SwigVar_PyObject key = swig::from(i->first);
+ swig::SwigVar_PyObject val = swig::from(i->second);
+ PyDict_SetItem(obj, key, val);
+ }
+ return obj;
+ }
+ }
+ };
+ }
+}
+
+%define %swig_multimap_methods(Type...)
+ %swig_map_common(Type);
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__;
+#endif
+
+ %extend {
+ // This will be called through the mp_ass_subscript slot to delete an entry.
+ void __setitem__(const key_type& key) {
+ self->erase(key);
+ }
+
+ void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
+ self->insert(Type::value_type(key,x));
+ }
+ }
+%enddef
+
+%include <std/std_multimap.i>
+
diff --git a/contrib/tools/swig/Lib/python/std_multiset.i b/contrib/tools/swig/Lib/python/std_multiset.i
new file mode 100644
index 00000000000..b79f64e5a31
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_multiset.i
@@ -0,0 +1,30 @@
+/*
+ Multisets
+*/
+
+%include <std_set.i>
+
+%fragment("StdMultisetTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T>
+ struct traits_asptr<std::multiset<T> > {
+ static int asptr(PyObject *obj, std::multiset<T> **m) {
+ return traits_asptr_stdseq<std::multiset<T> >::asptr(obj, m);
+ }
+ };
+
+ template <class T>
+ struct traits_from<std::multiset<T> > {
+ static PyObject *from(const std::multiset<T>& vec) {
+ return traits_from_stdseq<std::multiset<T> >::from(vec);
+ }
+ };
+ }
+%}
+
+#define %swig_multiset_methods(Set...) %swig_set_methods(Set)
+
+
+
+%include <std/std_multiset.i>
diff --git a/contrib/tools/swig/Lib/python/std_pair.i b/contrib/tools/swig/Lib/python/std_pair.i
new file mode 100644
index 00000000000..0dcd0bb7ef2
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_pair.i
@@ -0,0 +1,206 @@
+/*
+ Pairs
+*/
+%include <pystdcommon.swg>
+
+//#define SWIG_STD_PAIR_ASVAL
+
+%fragment("StdPairTraits","header",fragment="StdTraits") {
+ namespace swig {
+#ifdef SWIG_STD_PAIR_ASVAL
+ template <class T, class U >
+ struct traits_asval<std::pair<T,U> > {
+ typedef std::pair<T,U> value_type;
+
+ static int get_pair(PyObject* first, PyObject* second,
+ std::pair<T,U> *val)
+ {
+ if (val) {
+ T *pfirst = &(val->first);
+ int res1 = swig::asval((PyObject*)first, pfirst);
+ if (!SWIG_IsOK(res1)) return res1;
+ U *psecond = &(val->second);
+ int res2 = swig::asval((PyObject*)second, psecond);
+ if (!SWIG_IsOK(res2)) return res2;
+ return res1 > res2 ? res1 : res2;
+ } else {
+ T *pfirst = 0;
+ int res1 = swig::asval((PyObject*)first, 0);
+ if (!SWIG_IsOK(res1)) return res1;
+ U *psecond = 0;
+ int res2 = swig::asval((PyObject*)second, psecond);
+ if (!SWIG_IsOK(res2)) return res2;
+ return res1 > res2 ? res1 : res2;
+ }
+ }
+
+ static int asval(PyObject *obj, std::pair<T,U> *val) {
+ int res = SWIG_ERROR;
+ if (PyTuple_Check(obj)) {
+ if (PyTuple_GET_SIZE(obj) == 2) {
+ res = get_pair(PyTuple_GET_ITEM(obj,0),PyTuple_GET_ITEM(obj,1), val);
+ }
+ } else if (PySequence_Check(obj)) {
+ if (PySequence_Size(obj) == 2) {
+ swig::SwigVar_PyObject first = PySequence_GetItem(obj,0);
+ swig::SwigVar_PyObject second = PySequence_GetItem(obj,1);
+ res = get_pair(first, second, val);
+ }
+ } else {
+ value_type *p = 0;
+ swig_type_info *descriptor = swig::type_info<value_type>();
+ res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res) && val) *val = *p;
+ }
+ return res;
+ }
+ };
+
+#else
+ template <class T, class U >
+ struct traits_asptr<std::pair<T,U> > {
+ typedef std::pair<T,U> value_type;
+
+ static int get_pair(PyObject* first, PyObject* second,
+ std::pair<T,U> **val)
+ {
+ if (val) {
+ value_type *vp = %new_instance(std::pair<T,U>);
+ T *pfirst = &(vp->first);
+ int res1 = swig::asval((PyObject*)first, pfirst);
+ if (!SWIG_IsOK(res1)) {
+ %delete(vp);
+ return res1;
+ }
+ U *psecond = &(vp->second);
+ int res2 = swig::asval((PyObject*)second, psecond);
+ if (!SWIG_IsOK(res2)) {
+ %delete(vp);
+ return res2;
+ }
+ *val = vp;
+ return SWIG_AddNewMask(res1 > res2 ? res1 : res2);
+ } else {
+ T *pfirst = 0;
+ int res1 = swig::asval((PyObject*)first, pfirst);
+ if (!SWIG_IsOK(res1)) return res1;
+ U *psecond = 0;
+ int res2 = swig::asval((PyObject*)second, psecond);
+ if (!SWIG_IsOK(res2)) return res2;
+ return res1 > res2 ? res1 : res2;
+ }
+ }
+
+ static int asptr(PyObject *obj, std::pair<T,U> **val) {
+ int res = SWIG_ERROR;
+ if (PyTuple_Check(obj)) {
+ if (PyTuple_GET_SIZE(obj) == 2) {
+ res = get_pair(PyTuple_GET_ITEM(obj,0),PyTuple_GET_ITEM(obj,1), val);
+ }
+ } else if (PySequence_Check(obj)) {
+ if (PySequence_Size(obj) == 2) {
+ swig::SwigVar_PyObject first = PySequence_GetItem(obj,0);
+ swig::SwigVar_PyObject second = PySequence_GetItem(obj,1);
+ res = get_pair(first, second, val);
+ }
+ } else {
+ value_type *p = 0;
+ swig_type_info *descriptor = swig::type_info<value_type>();
+ res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res) && val) *val = p;
+ }
+ return res;
+ }
+ };
+
+#endif
+ template <class T, class U >
+ struct traits_from<std::pair<T,U> > {
+ static PyObject *from(const std::pair<T,U>& val) {
+ PyObject* obj = PyTuple_New(2);
+ PyTuple_SetItem(obj,0,swig::from(val.first));
+ PyTuple_SetItem(obj,1,swig::from(val.second));
+ return obj;
+ }
+ };
+ }
+
+#if defined(SWIGPYTHON_BUILTIN)
+SWIGINTERN Py_ssize_t
+SwigPython_std_pair_len (PyObject *a)
+{
+ return 2;
+}
+
+SWIGINTERN PyObject*
+SwigPython_std_pair_repr (PyObject *o)
+{
+ PyObject *tuple = PyTuple_New(2);
+ assert(tuple);
+ PyTuple_SET_ITEM(tuple, 0, PyObject_GetAttrString(o, (char*) "first"));
+ PyTuple_SET_ITEM(tuple, 1, PyObject_GetAttrString(o, (char*) "second"));
+ PyObject *result = PyObject_Repr(tuple);
+ SWIG_Py_DECREF(tuple);
+ return result;
+}
+
+SWIGINTERN PyObject*
+SwigPython_std_pair_getitem (PyObject *a, Py_ssize_t b)
+{
+ PyObject *result = PyObject_GetAttrString(a, b % 2 ? (char*) "second" : (char*) "first");
+ return result;
+}
+
+SWIGINTERN int
+SwigPython_std_pair_setitem (PyObject *a, Py_ssize_t b, PyObject *c)
+{
+ int result = PyObject_SetAttrString(a, b % 2 ? (char*) "second" : (char*) "first", c);
+ return result;
+}
+#endif
+
+}
+
+%feature("python:sq_length") std::pair "SwigPython_std_pair_len";
+%feature("python:sq_length") std::pair<T*,U> "SwigPython_std_pair_len";
+%feature("python:sq_length") std::pair<T,U*> "SwigPython_std_pair_len";
+%feature("python:sq_length") std::pair<T*,U*> "SwigPython_std_pair_len";
+
+%feature("python:tp_repr") std::pair "SwigPython_std_pair_repr";
+%feature("python:tp_repr") std::pair<T*,U> "SwigPython_std_pair_repr";
+%feature("python:tp_repr") std::pair<T,U*> "SwigPython_std_pair_repr";
+%feature("python:tp_repr") std::pair<T*,U*> "SwigPython_std_pair_repr";
+
+%feature("python:sq_item") std::pair "SwigPython_std_pair_getitem";
+%feature("python:sq_item") std::pair<T*,U> "SwigPython_std_pair_getitem";
+%feature("python:sq_item") std::pair<T,U*> "SwigPython_std_pair_getitem";
+%feature("python:sq_item") std::pair<T*,U*> "SwigPython_std_pair_getitem";
+
+%feature("python:sq_ass_item") std::pair "SwigPython_std_pair_setitem";
+%feature("python:sq_ass_item") std::pair<T*,U> "SwigPython_std_pair_setitem";
+%feature("python:sq_ass_item") std::pair<T,U*> "SwigPython_std_pair_setitem";
+%feature("python:sq_ass_item") std::pair<T*,U*> "SwigPython_std_pair_setitem";
+
+%define %swig_pair_methods(pair...)
+#if !defined(SWIGPYTHON_BUILTIN)
+%extend {
+%pythoncode %{def __len__(self):
+ return 2
+def __repr__(self):
+ return str((self.first, self.second))
+def __getitem__(self, index):
+ if not (index % 2):
+ return self.first
+ else:
+ return self.second
+def __setitem__(self, index, val):
+ if not (index % 2):
+ self.first = val
+ else:
+ self.second = val%}
+}
+#endif
+%enddef
+
+%include <std/std_pair.i>
+
diff --git a/contrib/tools/swig/Lib/python/std_set.i b/contrib/tools/swig/Lib/python/std_set.i
new file mode 100644
index 00000000000..3f80daff686
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_set.i
@@ -0,0 +1,56 @@
+/*
+ Sets
+*/
+
+%fragment("StdSetTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T>
+ struct traits_asptr<std::set<T> > {
+ static int asptr(PyObject *obj, std::set<T> **s) {
+ return traits_asptr_stdseq<std::set<T> >::asptr(obj, s);
+ }
+ };
+
+ template <class T>
+ struct traits_from<std::set<T> > {
+ static PyObject *from(const std::set<T>& vec) {
+ return traits_from_stdseq<std::set<T> >::from(vec);
+ }
+ };
+ }
+%}
+
+%define %swig_set_methods(set...)
+ %swig_sequence_iterator(set);
+ %swig_container_methods(set);
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
+ %feature("python:slot", "sq_contains", functype="objobjproc") __contains__;
+#endif
+
+ %extend {
+ void append(value_type x) {
+ self->insert(x);
+ }
+
+ bool __contains__(value_type x) {
+ return self->find(x) != self->end();
+ }
+
+ value_type __getitem__(difference_type i) const throw (std::out_of_range) {
+ return *(swig::cgetpos(self, i));
+ }
+
+ void add(value_type x) {
+ self->insert(x);
+ }
+
+ void discard(value_type x) {
+ self->erase(x);
+ }
+ }
+%enddef
+
+%include <std/std_set.i>
diff --git a/contrib/tools/swig/Lib/python/std_shared_ptr.i b/contrib/tools/swig/Lib/python/std_shared_ptr.i
new file mode 100644
index 00000000000..df873679c62
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_shared_ptr.i
@@ -0,0 +1,2 @@
+#define SWIG_SHARED_PTR_NAMESPACE std
+%include <boost_shared_ptr.i>
diff --git a/contrib/tools/swig/Lib/python/std_sstream.i b/contrib/tools/swig/Lib/python/std_sstream.i
new file mode 100644
index 00000000000..6647df8cd4f
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_sstream.i
@@ -0,0 +1 @@
+%include <std/std_sstream.i>
diff --git a/contrib/tools/swig/Lib/python/std_streambuf.i b/contrib/tools/swig/Lib/python/std_streambuf.i
new file mode 100644
index 00000000000..44b9bb4d788
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_streambuf.i
@@ -0,0 +1 @@
+%include <std/std_streambuf.i>
diff --git a/contrib/tools/swig/Lib/python/std_string.i b/contrib/tools/swig/Lib/python/std_string.i
new file mode 100644
index 00000000000..dc1378ae6de
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_string.i
@@ -0,0 +1 @@
+%include <typemaps/std_string.swg>
diff --git a/contrib/tools/swig/Lib/python/std_string_view.i b/contrib/tools/swig/Lib/python/std_string_view.i
new file mode 100644
index 00000000000..702dd9b49ef
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_string_view.i
@@ -0,0 +1,135 @@
+/* -----------------------------------------------------------------------------
+ * std_string_view.i
+ *
+ * SWIG typemaps for std::string_view types
+ * ----------------------------------------------------------------------------- */
+
+%include <exception.i>
+
+%{
+#include <string_view>
+
+#if PY_VERSION_HEX < 0x03000000
+# error std_string_view.i not supported for Python 2
+#endif
+%}
+
+namespace std {
+
+ %naturalvar string_view;
+
+ class string_view;
+
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_STRINGVIEW) string_view, const string_view & %{
+#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ $1 = PyBytes_Check($input);
+#else
+ $1 = PyUnicode_Check($input) || PyBytes_Check($input);
+#endif
+ %}
+
+ %typemap(in) string_view (PyObject *bytes = NULL) {
+ Py_ssize_t len;
+%#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ const char *p = PyBytes_AsString($input);
+ if (!p) SWIG_fail;
+ len = PyBytes_Size($input);
+%#else
+ const char *p;
+ if (PyUnicode_Check($input)) {
+ p = SWIG_PyUnicode_AsUTF8AndSize($input, &len, &bytes);
+ if (!p) SWIG_fail;
+ } else {
+ p = PyBytes_AsString($input);
+ if (!p) SWIG_fail;
+ len = PyBytes_Size($input);
+ }
+%#endif
+ $1 = std::string_view(p, len);
+ }
+
+ %typemap(freearg) string_view %{
+ SWIG_Py_XDECREF(bytes$argnum);
+ %}
+
+ %typemap(in) const string_view & ($*1_ltype temp, PyObject *bytes = NULL) {
+ Py_ssize_t len;
+%#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ const char *p = PyBytes_AsString($input);
+ if (!p) SWIG_fail;
+ len = PyBytes_Size($input);
+%#else
+ const char *p;
+ if (PyUnicode_Check($input)) {
+ p = SWIG_PyUnicode_AsUTF8AndSize($input, &len, &bytes);
+ if (!p) SWIG_fail;
+ } else {
+ p = PyBytes_AsString($input);
+ if (!p) SWIG_fail;
+ len = PyBytes_Size($input);
+ }
+%#endif
+ temp = std::string_view(p, len);
+ $1 = &temp;
+ }
+
+ %typemap(freearg) const string_view & %{
+ SWIG_Py_XDECREF(bytes$argnum);
+ %}
+
+ %typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) string_view {
+ Py_ssize_t len;
+%#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ const char *p = PyBytes_AsString($input);
+ if (p) len = PyBytes_Size($input);
+%#else
+ const char *p;
+ PyObject *bytes = NULL;
+ if (PyUnicode_Check($input)) {
+ p = SWIG_PyUnicode_AsUTF8AndSize($input, &len, &bytes);
+ // Avoid undefined behaviour (p will be pointing to a temporary
+ // if bytes is not NULL which happens when Py_LIMITED_API is defined
+ // and < 0x030A0000) and just leak by not calling Py_XDECREF.
+ // Py_XDECREF(bytes);
+ } else {
+ p = PyBytes_AsString($input);
+ if (p) len = PyBytes_Size($input);
+ }
+%#endif
+ if (p) $result = std::string_view(p, len);
+ }
+
+
+ %typemap(out) string_view %{
+#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ $result = PyBytes_FromStringAndSize($1.data(), $1.size());
+#else
+ $result = PyUnicode_FromStringAndSize($1.data(), $1.size());
+#endif
+ %}
+
+ %typemap(varout) string_view %{
+#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ $result = PyBytes_FromStringAndSize($1.data(), $1.size());
+#else
+ $result = PyUnicode_FromStringAndSize($1.data(), $1.size());
+#endif
+ %}
+
+ %typemap(directorin) string_view, const string_view & %{
+#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ $input = PyBytes_FromStringAndSize($1.data(), $1.size());
+#else
+ $input = PyUnicode_FromStringAndSize($1.data(), $1.size());
+#endif
+ %}
+
+ %typemap(out) const string_view & %{
+#ifdef SWIG_PYTHON_STRICT_BYTE_CHAR
+ $result = PyBytes_FromStringAndSize($1->data(), $1->size());
+#else
+ $result = PyUnicode_FromStringAndSize($1->data(), $1->size());
+#endif
+ %}
+
+}
diff --git a/contrib/tools/swig/Lib/python/std_unique_ptr.i b/contrib/tools/swig/Lib/python/std_unique_ptr.i
new file mode 100644
index 00000000000..e3669bb4a5a
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_unique_ptr.i
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ * std_unique_ptr.i
+ *
+ * SWIG library file for handling std::unique_ptr.
+ *
+ * Returning a std::unique_ptr from a wrapped function:
+ * Memory ownership is passed (moved) from the std::unique_ptr in the C++ layer
+ * to the proxy class when returning a std::unique_ptr by value from a function.
+ * Memory ownership is not moved when returning by any sort of reference.
+ *
+ * Passing a std::unique_ptr as a parameter to a wrapped function:
+ * Memory ownership is passed from the proxy class to the std::unique_ptr in the
+ * C++ layer when passed as a parameter by value, rvalue reference or non-const
+ * lvalue reference. Memory ownership is not transferred when passing by const
+ * lvalue reference.
+ * ----------------------------------------------------------------------------- */
+
+%include <unique_ptr.swg>
+
+%define %unique_ptr(TYPE)
+%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "TYPE *", $symname, $argnum);
+ } else {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ }
+ $1.reset((TYPE *)argp);
+}
+
+%typemap(in, noblock=1) std::unique_ptr< TYPE > & (void *argp = 0, int res = 0, std::unique_ptr< TYPE > uptr), std::unique_ptr< TYPE > && (void *argp = 0, int res = 0, std::unique_ptr< TYPE > uptr) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "TYPE *", $symname, $argnum);
+ } else {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ }
+ uptr.reset((TYPE *)argp);
+ $1 = &uptr;
+}
+
+%typemap(in, noblock=1, fragment="SwigNoDeleteUniquePtr") const std::unique_ptr< TYPE > & (void *argp = 0, int res = 0, swig::NoDeleteUniquePtr< TYPE > ndup) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), 0);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "TYPE *", $symname, $argnum);
+ }
+ ndup.uptr.reset((TYPE *)argp);
+ $1 = &ndup.uptr;
+}
+
+%typemap (out) std::unique_ptr< TYPE > %{
+ %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
+%}
+%typemap (out) std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && %{
+ %set_output(SWIG_NewPointerObj($1->get(), $descriptor(TYPE *), $owner | %newpointer_flags));
+%}
+
+%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE >, std::unique_ptr< TYPE > &, std::unique_ptr< TYPE > && {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0);
+ $1 = SWIG_CheckState(res);
+}
+
+%template() std::unique_ptr< TYPE >;
+%enddef
diff --git a/contrib/tools/swig/Lib/python/std_unordered_map.i b/contrib/tools/swig/Lib/python/std_unordered_map.i
new file mode 100644
index 00000000000..4321735561e
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_unordered_map.i
@@ -0,0 +1,290 @@
+/*
+ Unordered Maps
+*/
+%include <std_map.i>
+
+%fragment("StdUnorderedMapForwardIteratorTraits","header")
+{
+ namespace swig {
+ template<class OutIterator, class FromOper, class ValueType = typename OutIterator::value_type>
+ struct SwigPyMapForwardIterator_T : SwigPyForwardIteratorClosed_T<OutIterator, ValueType, FromOper>
+ {
+ SwigPyMapForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
+ : SwigPyForwardIteratorClosed_T<OutIterator,ValueType,FromOper>(curr, first, last, seq)
+ {
+ }
+ };
+
+
+ template<class OutIterator,
+ class FromOper = from_key_oper<typename OutIterator::value_type> >
+ struct SwigPyMapKeyForwardIterator_T : SwigPyMapForwardIterator_T<OutIterator, FromOper>
+ {
+ SwigPyMapKeyForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
+ : SwigPyMapForwardIterator_T<OutIterator, FromOper>(curr, first, last, seq)
+ {
+ }
+ };
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_key_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
+ {
+ return new SwigPyMapKeyForwardIterator_T<OutIter>(current, begin, end, seq);
+ }
+
+ template<class OutIterator,
+ class FromOper = from_value_oper<typename OutIterator::value_type> >
+ struct SwigPyMapValueForwardIterator_T : SwigPyMapForwardIterator_T<OutIterator, FromOper>
+ {
+ SwigPyMapValueForwardIterator_T(OutIterator curr, OutIterator first, OutIterator last, PyObject *seq)
+ : SwigPyMapForwardIterator_T<OutIterator, FromOper>(curr, first, last, seq)
+ {
+ }
+ };
+
+
+ template<typename OutIter>
+ inline SwigPyIterator*
+ make_output_value_forward_iterator(const OutIter& current, const OutIter& begin, const OutIter& end, PyObject *seq = 0)
+ {
+ return new SwigPyMapValueForwardIterator_T<OutIter>(current, begin, end, seq);
+ }
+ }
+}
+
+%fragment("StdUnorderedMapTraits","header",fragment="StdMapCommonTraits",fragment="StdUnorderedMapForwardIteratorTraits")
+{
+ namespace swig {
+ template <class K, class T, class Hash, class Compare, class Alloc>
+ struct traits_reserve<std::unordered_map<K,T,Hash,Compare,Alloc> > {
+ static void reserve(std::unordered_map<K,T,Hash,Compare,Alloc> &seq, typename std::unordered_map<K,T,Hash,Compare,Alloc>::size_type n) {
+ seq.reserve(n);
+ }
+ };
+
+ template <class K, class T, class Hash, class Compare, class Alloc>
+ struct traits_asptr<std::unordered_map<K,T,Hash,Compare,Alloc> > {
+ typedef std::unordered_map<K,T,Hash,Compare,Alloc> unordered_map_type;
+ static int asptr(PyObject *obj, unordered_map_type **val) {
+ int res = SWIG_ERROR;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (PyDict_Check(obj)) {
+ SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
+%#if PY_VERSION_HEX >= 0x03000000
+ /* In Python 3.x the ".items()" method returns a dict_items object */
+ items = PySequence_Fast(items, ".items() didn't return a sequence!");
+%#endif
+ res = traits_asptr_stdseq<std::unordered_map<K,T,Hash,Compare,Alloc>, std::pair<K, T> >::asptr(items, val);
+ } else {
+ unordered_map_type *p = 0;
+ swig_type_info *descriptor = swig::type_info<unordered_map_type>();
+ res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res) && val) *val = p;
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return res;
+ }
+ };
+
+ template <class K, class T, class Hash, class Compare, class Alloc>
+ struct traits_from<std::unordered_map<K,T,Hash,Compare,Alloc> > {
+ typedef std::unordered_map<K,T,Hash,Compare,Alloc> unordered_map_type;
+ typedef typename unordered_map_type::const_iterator const_iterator;
+ typedef typename unordered_map_type::size_type size_type;
+
+ static PyObject *asdict(const unordered_map_type& map) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ size_type size = map.size();
+ Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject *obj = PyDict_New();
+ for (const_iterator i= map.begin(); i!= map.end(); ++i) {
+ swig::SwigVar_PyObject key = swig::from(i->first);
+ swig::SwigVar_PyObject val = swig::from(i->second);
+ PyDict_SetItem(obj, key, val);
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return obj;
+ }
+
+ static PyObject *from(const unordered_map_type& map) {
+ swig_type_info *desc = swig::type_info<unordered_map_type>();
+ if (desc && desc->clientdata) {
+ return SWIG_InternalNewPointerObj(new unordered_map_type(map), desc, SWIG_POINTER_OWN);
+ } else {
+ return asdict(map);
+ }
+ }
+ };
+ }
+}
+
+%define %swig_unordered_map_common(Map...)
+ %swig_sequence_forward_iterator(Map);
+ %swig_container_methods(Map)
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_length", functype="lenfunc") __len__;
+ %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
+ %feature("python:slot", "tp_iter", functype="getiterfunc") key_iterator;
+ %feature("python:slot", "sq_contains", functype="objobjproc") __contains__;
+
+ %extend {
+ %newobject iterkeys(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* iterkeys(PyObject **PYTHON_SELF) {
+ return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+ %newobject itervalues(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* itervalues(PyObject **PYTHON_SELF) {
+ return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+ %newobject iteritems(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* iteritems(PyObject **PYTHON_SELF) {
+ return swig::make_output_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+ }
+
+#else
+ %extend {
+ %pythoncode %{def __iter__(self):
+ return self.key_iterator()%}
+ %pythoncode %{def iterkeys(self):
+ return self.key_iterator()%}
+ %pythoncode %{def itervalues(self):
+ return self.value_iterator()%}
+ %pythoncode %{def iteritems(self):
+ return self.iterator()%}
+ }
+#endif
+
+ %extend {
+ mapped_type const & __getitem__(const key_type& key) throw (std::out_of_range) {
+ Map::const_iterator i = self->find(key);
+ if (i != self->end())
+ return i->second;
+ else
+ throw std::out_of_range("key not found");
+ }
+
+ void __delitem__(const key_type& key) throw (std::out_of_range) {
+ Map::iterator i = self->find(key);
+ if (i != self->end())
+ self->erase(i);
+ else
+ throw std::out_of_range("key not found");
+ }
+
+ bool has_key(const key_type& key) const {
+ Map::const_iterator i = self->find(key);
+ return i != self->end();
+ }
+
+ PyObject* keys() {
+ Map::size_type size = self->size();
+ Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject* keyList = PyList_New(pysize);
+ Map::const_iterator i = self->begin();
+ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
+ PyList_SET_ITEM(keyList, j, swig::from(i->first));
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return keyList;
+ }
+
+ PyObject* values() {
+ Map::size_type size = self->size();
+ Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject* valList = PyList_New(pysize);
+ Map::const_iterator i = self->begin();
+ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
+ PyList_SET_ITEM(valList, j, swig::from(i->second));
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return valList;
+ }
+
+ PyObject* items() {
+ Map::size_type size = self->size();
+ Py_ssize_t pysize = (size <= (Map::size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (pysize < 0) {
+ PyErr_SetString(PyExc_OverflowError, "unordered_map size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject* itemList = PyList_New(pysize);
+ Map::const_iterator i = self->begin();
+ for (Py_ssize_t j = 0; j < pysize; ++i, ++j) {
+ PyList_SET_ITEM(itemList, j, swig::from(*i));
+ }
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return itemList;
+ }
+
+ bool __contains__(const key_type& key) {
+ return self->find(key) != self->end();
+ }
+
+ %newobject key_iterator(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* key_iterator(PyObject **PYTHON_SELF) {
+ return swig::make_output_key_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+
+ %newobject value_iterator(PyObject **PYTHON_SELF);
+ swig::SwigPyIterator* value_iterator(PyObject **PYTHON_SELF) {
+ return swig::make_output_value_forward_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);
+ }
+ }
+
+%enddef
+
+%define %swig_unordered_map_methods(Map...)
+ %swig_unordered_map_common(Map)
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__;
+#endif
+
+ %extend {
+ // This will be called through the mp_ass_subscript slot to delete an entry.
+ void __setitem__(const key_type& key) {
+ self->erase(key);
+ }
+
+ void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
+%#ifdef __cpp_lib_unordered_map_try_emplace
+ (*self).insert_or_assign(key, x);
+%#else
+ (*self)[key] = x;
+%#endif
+ }
+
+ PyObject* asdict() {
+ return swig::traits_from< Map >::asdict(*self);
+ }
+ }
+
+
+%enddef
+
+
+%include <std/std_unordered_map.i>
diff --git a/contrib/tools/swig/Lib/python/std_unordered_multimap.i b/contrib/tools/swig/Lib/python/std_unordered_multimap.i
new file mode 100644
index 00000000000..816ec0933a8
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_unordered_multimap.i
@@ -0,0 +1,90 @@
+/*
+ Unordered Multimaps
+*/
+%include <std_unordered_map.i>
+
+%fragment("StdUnorderedMultimapTraits","header",fragment="StdMapCommonTraits",fragment="StdUnorderedMapForwardIteratorTraits")
+{
+ namespace swig {
+ template <class K, class T, class Hash, class Compare, class Alloc>
+ struct traits_reserve<std::unordered_multimap<K,T,Hash,Compare,Alloc> > {
+ static void reserve(std::unordered_multimap<K,T,Hash,Compare,Alloc> &seq, typename std::unordered_multimap<K,T,Hash,Compare,Alloc>::size_type n) {
+ seq.reserve(n);
+ }
+ };
+
+ template <class K, class T, class Hash, class Compare, class Alloc>
+ struct traits_asptr<std::unordered_multimap<K,T,Hash,Compare,Alloc> > {
+ typedef std::unordered_multimap<K,T,Hash,Compare,Alloc> unordered_multimap_type;
+ static int asptr(PyObject *obj, std::unordered_multimap<K,T,Hash,Compare,Alloc> **val) {
+ int res = SWIG_ERROR;
+ if (PyDict_Check(obj)) {
+ SwigVar_PyObject items = PyObject_CallMethod(obj,(char *)"items",NULL);
+%#if PY_VERSION_HEX >= 0x03000000
+ /* In Python 3.x the ".items()" method returns a dict_items object */
+ items = PySequence_Fast(items, ".items() didn't return a sequence!");
+%#endif
+ res = traits_asptr_stdseq<std::unordered_multimap<K,T,Hash,Compare,Alloc>, std::pair<K, T> >::asptr(items, val);
+ } else {
+ unordered_multimap_type *p = 0;
+ swig_type_info *descriptor = swig::type_info<unordered_multimap_type>();
+ res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res) && val) *val = p;
+ }
+ return res;
+ }
+ };
+
+ template <class K, class T, class Hash, class Compare, class Alloc>
+ struct traits_from<std::unordered_multimap<K,T,Hash,Compare,Alloc> > {
+ typedef std::unordered_multimap<K,T,Hash,Compare,Alloc> unordered_multimap_type;
+ typedef typename unordered_multimap_type::const_iterator const_iterator;
+ typedef typename unordered_multimap_type::size_type size_type;
+
+ static PyObject *from(const unordered_multimap_type& unordered_multimap) {
+ swig_type_info *desc = swig::type_info<unordered_multimap_type>();
+ if (desc && desc->clientdata) {
+ return SWIG_InternalNewPointerObj(new unordered_multimap_type(unordered_multimap), desc, SWIG_POINTER_OWN);
+ } else {
+ size_type size = unordered_multimap.size();
+ Py_ssize_t pysize = (size <= (size_type) INT_MAX) ? (Py_ssize_t) size : -1;
+ if (pysize < 0) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ PyErr_SetString(PyExc_OverflowError, "unordered_multimap size not valid in python");
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+ }
+ PyObject *obj = PyDict_New();
+ for (const_iterator i= unordered_multimap.begin(); i!= unordered_multimap.end(); ++i) {
+ swig::SwigVar_PyObject key = swig::from(i->first);
+ swig::SwigVar_PyObject val = swig::from(i->second);
+ PyDict_SetItem(obj, key, val);
+ }
+ return obj;
+ }
+ }
+ };
+ }
+}
+
+%define %swig_unordered_multimap_methods(Type...)
+ %swig_unordered_map_common(Type);
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") __setitem__;
+#endif
+
+ %extend {
+ // This will be called through the mp_ass_subscript slot to delete an entry.
+ void __setitem__(const key_type& key) {
+ self->erase(key);
+ }
+
+ void __setitem__(const key_type& key, const mapped_type& x) throw (std::out_of_range) {
+ self->insert(Type::value_type(key,x));
+ }
+ }
+%enddef
+
+%include <std/std_unordered_multimap.i>
+
diff --git a/contrib/tools/swig/Lib/python/std_unordered_multiset.i b/contrib/tools/swig/Lib/python/std_unordered_multiset.i
new file mode 100644
index 00000000000..0542247b23a
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_unordered_multiset.i
@@ -0,0 +1,37 @@
+/*
+ Unordered Multisets
+*/
+
+%include <std_unordered_set.i>
+
+%fragment("StdUnorderedMultisetTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class Key, class Hash, class Compare, class Alloc>
+ struct traits_reserve<std::unordered_multiset<Key,Hash,Compare,Alloc> > {
+ static void reserve(std::unordered_multiset<Key,Hash,Compare,Alloc> &seq, typename std::unordered_multiset<Key,Hash,Compare,Alloc>::size_type n) {
+ seq.reserve(n);
+ }
+ };
+
+ template <class Key, class Hash, class Compare, class Alloc>
+ struct traits_asptr<std::unordered_multiset<Key,Hash,Compare,Alloc> > {
+ static int asptr(PyObject *obj, std::unordered_multiset<Key,Hash,Compare,Alloc> **m) {
+ return traits_asptr_stdseq<std::unordered_multiset<Key,Hash,Compare,Alloc> >::asptr(obj, m);
+ }
+ };
+
+ template <class Key, class Hash, class Compare, class Alloc>
+ struct traits_from<std::unordered_multiset<Key,Hash,Compare,Alloc> > {
+ static PyObject *from(const std::unordered_multiset<Key,Hash,Compare,Alloc>& vec) {
+ return traits_from_stdseq<std::unordered_multiset<Key,Hash,Compare,Alloc> >::from(vec);
+ }
+ };
+ }
+%}
+
+#define %swig_unordered_multiset_methods(Set...) %swig_unordered_set_methods(Set)
+
+
+
+%include <std/std_unordered_multiset.i>
diff --git a/contrib/tools/swig/Lib/python/std_unordered_set.i b/contrib/tools/swig/Lib/python/std_unordered_set.i
new file mode 100644
index 00000000000..fd866b14aa0
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_unordered_set.i
@@ -0,0 +1,56 @@
+/*
+ Unordered Sets
+*/
+
+%fragment("StdUnorderedSetTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class Key, class Hash, class Compare, class Alloc>
+ struct traits_reserve<std::unordered_set<Key,Hash,Compare,Alloc> > {
+ static void reserve(std::unordered_set<Key,Hash,Compare,Alloc> &seq, typename std::unordered_set<Key,Hash,Compare,Alloc>::size_type n) {
+ seq.reserve(n);
+ }
+ };
+
+ template <class Key, class Hash, class Compare, class Alloc>
+ struct traits_asptr<std::unordered_set<Key,Hash,Compare,Alloc> > {
+ static int asptr(PyObject *obj, std::unordered_set<Key,Hash,Compare,Alloc> **s) {
+ return traits_asptr_stdseq<std::unordered_set<Key,Hash,Compare,Alloc> >::asptr(obj, s);
+ }
+ };
+
+ template <class Key, class Hash, class Compare, class Alloc>
+ struct traits_from<std::unordered_set<Key,Hash,Compare,Alloc> > {
+ static PyObject *from(const std::unordered_set<Key,Hash,Compare,Alloc>& vec) {
+ return traits_from_stdseq<std::unordered_set<Key,Hash,Compare,Alloc> >::from(vec);
+ }
+ };
+ }
+%}
+
+%define %swig_unordered_set_methods(unordered_set...)
+ %swig_sequence_forward_iterator(unordered_set);
+ %swig_container_methods(unordered_set);
+
+#if defined(SWIGPYTHON_BUILTIN)
+ %feature("python:slot", "sq_contains", functype="objobjproc") __contains__;
+ %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__;
+#endif
+
+
+ %extend {
+ void append(value_type x) {
+ self->insert(x);
+ }
+
+ bool __contains__(value_type x) {
+ return self->find(x) != self->end();
+ }
+
+ value_type __getitem__(difference_type i) const throw (std::out_of_range) {
+ return *(swig::cgetpos(self, i));
+ }
+ }
+%enddef
+
+%include <std/std_unordered_set.i>
diff --git a/contrib/tools/swig/Lib/python/std_vector.i b/contrib/tools/swig/Lib/python/std_vector.i
new file mode 100644
index 00000000000..2ac41a54d7d
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_vector.i
@@ -0,0 +1,34 @@
+/*
+ Vectors
+*/
+
+%fragment("StdVectorTraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T>
+ struct traits_reserve<std::vector<T> > {
+ static void reserve(std::vector<T> &seq, typename std::vector<T>::size_type n) {
+ seq.reserve(n);
+ }
+ };
+
+ template <class T>
+ struct traits_asptr<std::vector<T> > {
+ static int asptr(PyObject *obj, std::vector<T> **vec) {
+ return traits_asptr_stdseq<std::vector<T> >::asptr(obj, vec);
+ }
+ };
+
+ template <class T>
+ struct traits_from<std::vector<T> > {
+ static PyObject *from(const std::vector<T>& vec) {
+ return traits_from_stdseq<std::vector<T> >::from(vec);
+ }
+ };
+ }
+%}
+
+#define %swig_vector_methods(Type...) %swig_sequence_methods(Type)
+#define %swig_vector_methods_val(Type...) %swig_sequence_methods_val(Type);
+
+%include <std/std_vector.i>
diff --git a/contrib/tools/swig/Lib/python/std_vectora.i b/contrib/tools/swig/Lib/python/std_vectora.i
new file mode 100644
index 00000000000..3f084bd7de1
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_vectora.i
@@ -0,0 +1,31 @@
+/*
+ Vectors + allocators
+*/
+
+%fragment("StdVectorATraits","header",fragment="StdSequenceTraits")
+%{
+ namespace swig {
+ template <class T, class A>
+ struct traits_asptr<std::vector<T,A> > {
+ typedef std::vector<T,A> vector_type;
+ typedef T value_type;
+ static int asptr(PyObject *obj, vector_type **vec) {
+ return traits_asptr_stdseq<vector_type>::asptr(obj, vec);
+ }
+ };
+
+ template <class T, class A>
+ struct traits_from<std::vector<T,A> > {
+ typedef std::vector<T,A> vector_type;
+ static PyObject *from(const vector_type& vec) {
+ return traits_from_stdseq<vector_type>::from(vec);
+ }
+ };
+ }
+%}
+
+
+#define %swig_vector_methods(Type...) %swig_sequence_methods(Type)
+#define %swig_vector_methods_val(Type...) %swig_sequence_methods_val(Type);
+
+%include <std/std_vectora.i>
diff --git a/contrib/tools/swig/Lib/python/std_wios.i b/contrib/tools/swig/Lib/python/std_wios.i
new file mode 100644
index 00000000000..930a57dd0de
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_wios.i
@@ -0,0 +1 @@
+%include <std/std_wios.i>
diff --git a/contrib/tools/swig/Lib/python/std_wiostream.i b/contrib/tools/swig/Lib/python/std_wiostream.i
new file mode 100644
index 00000000000..d3a5ee785a2
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_wiostream.i
@@ -0,0 +1,10 @@
+namespace std
+{
+%callback(1) wendl;
+%callback(1) wends;
+%callback(1) wflush;
+}
+
+%include <std_basic_string.i>
+%include <std_wstring.i>
+%include <std/std_wiostream.i>
diff --git a/contrib/tools/swig/Lib/python/std_wsstream.i b/contrib/tools/swig/Lib/python/std_wsstream.i
new file mode 100644
index 00000000000..8843f56d895
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_wsstream.i
@@ -0,0 +1 @@
+%include <std/std_wsstream.i>
diff --git a/contrib/tools/swig/Lib/python/std_wstreambuf.i b/contrib/tools/swig/Lib/python/std_wstreambuf.i
new file mode 100644
index 00000000000..c0f09201cef
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_wstreambuf.i
@@ -0,0 +1 @@
+%include <std/std_wstreambuf.i>
diff --git a/contrib/tools/swig/Lib/python/std_wstring.i b/contrib/tools/swig/Lib/python/std_wstring.i
new file mode 100644
index 00000000000..ef8628137bd
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/std_wstring.i
@@ -0,0 +1,3 @@
+%include <pywstrings.swg>
+%include <typemaps/std_wstring.swg>
+
diff --git a/contrib/tools/swig/Lib/python/stl.i b/contrib/tools/swig/Lib/python/stl.i
new file mode 100644
index 00000000000..04f86014f2c
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/stl.i
@@ -0,0 +1,10 @@
+/* -----------------------------------------------------------------------------
+ * stl.i
+ * ----------------------------------------------------------------------------- */
+
+%include <std_common.i>
+%include <std_string.i>
+%include <std_vector.i>
+%include <std_map.i>
+%include <std_pair.i>
+
diff --git a/contrib/tools/swig/Lib/python/swigmove.i b/contrib/tools/swig/Lib/python/swigmove.i
new file mode 100644
index 00000000000..62ecca76823
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/swigmove.i
@@ -0,0 +1 @@
+%include <typemaps/swigmove.swg>
diff --git a/contrib/tools/swig/Lib/python/typemaps.i b/contrib/tools/swig/Lib/python/typemaps.i
new file mode 100644
index 00000000000..75592036b22
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/typemaps.i
@@ -0,0 +1,144 @@
+/* -----------------------------------------------------------------------------
+ * typemaps.i
+ *
+ * Pointer handling
+ * These mappings provide support for input/output arguments and common
+ * uses for C/C++ pointers.
+ * ----------------------------------------------------------------------------- */
+
+// INPUT typemaps.
+// These remap a C pointer to be an "INPUT" value which is passed by value
+// instead of reference.
+
+/*
+The following methods can be applied to turn a pointer into a simple
+"input" value. That is, instead of passing a pointer to an object,
+you would use a real value instead.
+
+ int *INPUT
+ short *INPUT
+ long *INPUT
+ long long *INPUT
+ unsigned int *INPUT
+ unsigned short *INPUT
+ unsigned long *INPUT
+ unsigned long long *INPUT
+ unsigned char *INPUT
+ bool *INPUT
+ float *INPUT
+ double *INPUT
+
+To use these, suppose you had a C function like this :
+
+ double fadd(double *a, double *b) {
+ return *a+*b;
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double fadd(double *INPUT, double *INPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INPUT { double *a, double *b };
+ double fadd(double *a, double *b);
+
+*/
+
+// OUTPUT typemaps. These typemaps are used for parameters that
+// are output only. The output value is appended to the result as
+// a list element.
+
+/*
+The following methods can be applied to turn a pointer into an "output"
+value. When calling a function, no input value would be given for
+a parameter, but an output value would be returned. In the case of
+multiple output values, they are returned in the form of a Python tuple.
+
+ int *OUTPUT
+ short *OUTPUT
+ long *OUTPUT
+ long long *OUTPUT
+ unsigned int *OUTPUT
+ unsigned short *OUTPUT
+ unsigned long *OUTPUT
+ unsigned long long *OUTPUT
+ unsigned char *OUTPUT
+ bool *OUTPUT
+ float *OUTPUT
+ double *OUTPUT
+
+For example, suppose you were trying to wrap the modf() function in the
+C math library which splits x into integral and fractional parts (and
+returns the integer part in one of its parameters) :
+
+ double modf(double x, double *ip);
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double modf(double x, double *OUTPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *OUTPUT { double *ip };
+ double modf(double x, double *ip);
+
+The Python output of the function would be a tuple containing both
+output values.
+
+*/
+
+// INOUT
+// Mappings for an argument that is both an input and output
+// parameter
+
+/*
+The following methods can be applied to make a function parameter both
+an input and output value. This combines the behavior of both the
+"INPUT" and "OUTPUT" methods described earlier. Output values are
+returned in the form of a Python tuple.
+
+ int *INOUT
+ short *INOUT
+ long *INOUT
+ long long *INOUT
+ unsigned int *INOUT
+ unsigned short *INOUT
+ unsigned long *INOUT
+ unsigned long long *INOUT
+ unsigned char *INOUT
+ bool *INOUT
+ float *INOUT
+ double *INOUT
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ void neg(double *INOUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INOUT { double *x };
+ void neg(double *x);
+
+Unlike C, this mapping does not directly modify the input value (since
+this makes no sense in Python). Rather, the modified input value shows
+up as the return value of the function. Thus, to apply this function
+to a Python variable you might do this :
+
+ x = neg(x)
+
+*/
+
+%include <typemaps/typemaps.swg>
diff --git a/contrib/tools/swig/Lib/python/wchar.i b/contrib/tools/swig/Lib/python/wchar.i
new file mode 100644
index 00000000000..308139a3ab7
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/wchar.i
@@ -0,0 +1,21 @@
+#ifdef __cplusplus
+
+%{
+#include <cwchar>
+%}
+
+#else
+
+%{
+#include <wchar.h>
+%}
+
+#endif
+
+%types(wchar_t *);
+%include <pywstrings.swg>
+
+/*
+ Enable swig wchar support.
+*/
+#define SWIG_WCHAR
diff --git a/contrib/tools/swig/Lib/python/ya.make b/contrib/tools/swig/Lib/python/ya.make
new file mode 100644
index 00000000000..27d61986dc2
--- /dev/null
+++ b/contrib/tools/swig/Lib/python/ya.make
@@ -0,0 +1,22 @@
+# Generated by devtools/yamaker.
+
+LIBRARY()
+
+LICENSE(LicenseRef-scancode-swig)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+VERSION(4.3.1)
+
+ORIGINAL_SOURCE(https://github.com/swig/swig/archive/v4.3.1.tar.gz)
+
+ADDINCL(
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib/python
+ GLOBAL FOR
+ swig
+ contrib/tools/swig/Lib
+)
+
+END()
diff --git a/contrib/tools/swig/Lib/runtime.swg b/contrib/tools/swig/Lib/runtime.swg
new file mode 100644
index 00000000000..1528a522226
--- /dev/null
+++ b/contrib/tools/swig/Lib/runtime.swg
@@ -0,0 +1,38 @@
+/* -----------------------------------------------------------------------------*
+ Standard SWIG API for use inside user code.
+
+ Don't include this file directly, run the command
+ swig -python -external-runtime
+ Also, read the Modules chapter of the SWIG Manual.
+
+ * -----------------------------------------------------------------------------*/
+
+#ifdef SWIG_MODULE_CLIENTDATA_TYPE
+
+SWIGRUNTIMEINLINE swig_type_info *
+SWIG_TypeQuery(SWIG_MODULE_CLIENTDATA_TYPE clientdata, const char *name) {
+ swig_module_info *module = SWIG_GetModule(clientdata);
+ return SWIG_TypeQueryModule(module, module, name);
+}
+
+SWIGRUNTIMEINLINE swig_type_info *
+SWIG_MangledTypeQuery(SWIG_MODULE_CLIENTDATA_TYPE clientdata, const char *name) {
+ swig_module_info *module = SWIG_GetModule(clientdata);
+ return SWIG_MangledTypeQueryModule(module, module, name);
+}
+
+#else
+
+SWIGRUNTIMEINLINE swig_type_info *
+SWIG_TypeQuery(const char *name) {
+ swig_module_info *module = SWIG_GetModule(NULL);
+ return SWIG_TypeQueryModule(module, module, name);
+}
+
+SWIGRUNTIMEINLINE swig_type_info *
+SWIG_MangledTypeQuery(const char *name) {
+ swig_module_info *module = SWIG_GetModule(NULL);
+ return SWIG_MangledTypeQueryModule(module, module, name);
+}
+
+#endif
diff --git a/contrib/tools/swig/Lib/shared_ptr.i b/contrib/tools/swig/Lib/shared_ptr.i
new file mode 100644
index 00000000000..b450229cf5a
--- /dev/null
+++ b/contrib/tools/swig/Lib/shared_ptr.i
@@ -0,0 +1,57 @@
+// This is a helper file for shared_ptr and should not be included directly.
+
+// The main implementation detail in using this smart pointer of a type is to customise the code generated
+// to use a pointer to the smart pointer of the type, rather than the usual pointer to the underlying type.
+// So for some type T, shared_ptr<T> * is used rather than T *.
+
+// Another key part of the implementation is the smartptr feature:
+// %feature("smartptr") T { shared_ptr<T> }
+// This feature marks the class T as having a smartptr to it (the shared_ptr<T> type). This is then used to
+// support smart pointers and inheritance. Say class D derives from base B, then shared_ptr<D> is marked
+// with a fake inheritance from shared_ptr<B> in the type system if the "smartptr" feature is used on both
+// B and D. This is to emulate the conversion of shared_ptr<D> to shared_ptr<B> in the target language.
+
+// shared_ptr namespaces could be boost or std or std::tr1
+// For example for std::tr1, use:
+// #define SWIG_SHARED_PTR_NAMESPACE std
+// #define SWIG_SHARED_PTR_SUBNAMESPACE tr1
+
+#if !defined(SWIG_SHARED_PTR_NAMESPACE)
+# define SWIG_SHARED_PTR_NAMESPACE boost
+#endif
+
+#if defined(SWIG_SHARED_PTR_SUBNAMESPACE)
+# define SWIG_SHARED_PTR_QNAMESPACE SWIG_SHARED_PTR_NAMESPACE::SWIG_SHARED_PTR_SUBNAMESPACE
+#else
+# define SWIG_SHARED_PTR_QNAMESPACE SWIG_SHARED_PTR_NAMESPACE
+#endif
+
+namespace SWIG_SHARED_PTR_NAMESPACE {
+#if defined(SWIG_SHARED_PTR_SUBNAMESPACE)
+ namespace SWIG_SHARED_PTR_SUBNAMESPACE {
+#endif
+ template <class T> class shared_ptr {
+ };
+#if defined(SWIG_SHARED_PTR_SUBNAMESPACE)
+ }
+#endif
+}
+
+%fragment("SWIG_null_deleter", "header") {
+struct SWIG_null_deleter {
+ void operator() (void const *) const {
+ }
+};
+%#define SWIG_NO_NULL_DELETER_0 , SWIG_null_deleter()
+%#define SWIG_NO_NULL_DELETER_1
+%#define SWIG_NO_NULL_DELETER_SWIG_POINTER_NEW
+%#define SWIG_NO_NULL_DELETER_SWIG_POINTER_OWN
+}
+
+
+// Main user macro for defining shared_ptr typemaps for both const and non-const pointer types
+%define %shared_ptr(TYPE...)
+%feature("smartptr", noblock=1) TYPE { SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > }
+SWIG_SHARED_PTR_TYPEMAPS(, TYPE)
+SWIG_SHARED_PTR_TYPEMAPS(const, TYPE)
+%enddef
diff --git a/contrib/tools/swig/Lib/std/README b/contrib/tools/swig/Lib/std/README
new file mode 100644
index 00000000000..5cd759dda19
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/README
@@ -0,0 +1,22 @@
+/* -----------------------------------------------------------------------------
+ * C++ STD + STL
+ * ----------------------------------------------------------------------------- */
+
+std_common.i general common code
+std_container.i general container code
+std_basic_string.i basic string
+std_char_traits.i char traits
+std_complex.i complex
+std_deque.i deque
+std_except.i exceptions
+std_ios.i ios
+std_iostream.i istream/ostream
+std_list.i list
+std_map.i map
+std_multimap.i multimap
+std_multiset.i multiset
+std_pair.i pair
+std_set.i set
+std_streambuf.i streambuf
+std_vector.i vector
+std_vectora.i vector + allocator
diff --git a/contrib/tools/swig/Lib/std/_std_deque.i b/contrib/tools/swig/Lib/std/_std_deque.i
new file mode 100644
index 00000000000..af9db27f43e
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/_std_deque.i
@@ -0,0 +1,139 @@
+/* -----------------------------------------------------------------------------
+ * _std_deque.i
+ *
+ * This file contains a generic definition of std::deque along with
+ * some helper functions. Specific language modules should include
+ * this file to generate wrappers.
+ * ----------------------------------------------------------------------------- */
+
+%include <std_except.i>
+
+%{
+#include <deque>
+#include <stdexcept>
+%}
+
+
+/* This macro defines all of the standard methods for a deque. This
+ is defined as a macro to simplify the task of specialization. For
+ example,
+
+ template<> class deque<int> {
+ public:
+ %std_deque_methods(int);
+ };
+*/
+
+%define %std_deque_methods_noempty(T...)
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ deque();
+ deque(unsigned int size, const T& value=T());
+ deque(const deque< T > &);
+ ~deque();
+
+ void assign(unsigned int n, const T& value);
+ void swap(deque< T > &x);
+ unsigned int size() const;
+ unsigned int max_size() const;
+ void resize(unsigned int n, T c = T());
+ const_reference front();
+ const_reference back();
+ void push_front(const T& x);
+ void push_back(const T& x);
+ void pop_front();
+ void pop_back();
+ void clear();
+
+ /* Some useful extensions */
+ %extend {
+ const_reference getitem(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i<0) i += size;
+ if (i>=0 && i<size)
+ return (*self)[i];
+ else
+ throw std::out_of_range("deque index out of range");
+ }
+ void setitem(int i, const T& x) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i<0) i+= size;
+ if (i>=0 && i<size)
+ (*self)[i] = x;
+ else
+ throw std::out_of_range("deque index out of range");
+ }
+ void delitem(int i) throw (std::out_of_range) {
+ int size = int(self->size());
+ if (i<0) i+= size;
+ if (i>=0 && i<size) {
+ self->erase(self->begin()+i);
+ } else {
+ throw std::out_of_range("deque index out of range");
+ }
+ }
+ std::deque< T > getslice(int i, int j) {
+ int size = int(self->size());
+ if (i<0) i = size+i;
+ if (j<0) j = size+j;
+ if (i<0) i = 0;
+ if (j>size) j = size;
+ std::deque< T > tmp(j-i);
+ std::copy(self->begin()+i,self->begin()+j,tmp.begin());
+ return tmp;
+ }
+ void setslice(int i, int j, const std::deque< T >& v) {
+ int size = int(self->size());
+ if (i<0) i = size+i;
+ if (j<0) j = size+j;
+ if (i<0) i = 0;
+ if (j>size) j = size;
+ if (int(v.size()) == j-i) {
+ std::copy(v.begin(),v.end(),self->begin()+i);
+ } else {
+ self->erase(self->begin()+i,self->begin()+j);
+ if (i+1 <= size)
+ self->insert(self->begin()+i+1,v.begin(),v.end());
+ else
+ self->insert(self->end(),v.begin(),v.end());
+ }
+ }
+ void delslice(int i, int j) {
+ int size = int(self->size());
+ if (i<0) i = size+i;
+ if (j<0) j = size+j;
+ if (i<0) i = 0;
+ if (j>size) j = size;
+ self->erase(self->begin()+i,self->begin()+j);
+ }
+ };
+%enddef
+
+#ifdef SWIGPHP
+%define %std_deque_methods(T...)
+ %extend {
+ bool is_empty() const {
+ return self->empty();
+ }
+ };
+ %std_deque_methods_noempty(T)
+%enddef
+#else
+%define %std_deque_methods(T...)
+ bool empty() const;
+ %std_deque_methods_noempty(T)
+%enddef
+#endif
+
+namespace std {
+ template<class T> class deque {
+ public:
+ %std_deque_methods(T);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_alloc.i b/contrib/tools/swig/Lib/std/std_alloc.i
new file mode 100644
index 00000000000..e460dc3eaf8
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_alloc.i
@@ -0,0 +1,77 @@
+namespace std
+{
+ /**
+ * @brief The "standard" allocator, as per [20.4].
+ *
+ * The private _Alloc is "SGI" style. (See comments at the top
+ * of stl_alloc.h.)
+ *
+ * The underlying allocator behaves as follows.
+ * - __default_alloc_template is used via two typedefs
+ * - "__single_client_alloc" typedef does no locking for threads
+ * - "__alloc" typedef is threadsafe via the locks
+ * - __new_alloc is used for memory requests
+ *
+ * (See @link Allocators allocators info @endlink for more.)
+ */
+ template<typename _Tp>
+ class allocator
+ {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp* pointer;
+ typedef const _Tp* const_pointer;
+ typedef _Tp& reference;
+ typedef const _Tp& const_reference;
+ typedef _Tp value_type;
+
+ template<typename _Tp1>
+ struct rebind;
+
+ allocator() throw();
+
+ allocator(const allocator& other) throw();
+ template<typename _Tp1>
+ allocator(const allocator<_Tp1>& other) throw();
+ ~allocator() throw();
+
+
+ pointer
+ address(reference __x) const;
+
+
+ const_pointer
+ address(const_reference __x) const;
+
+
+ // NB: __n is permitted to be 0. The C++ standard says nothing
+ // about what the return value is when __n == 0.
+ _Tp*
+ allocate(size_type __n, const void* = 0);
+
+ // __p is not permitted to be a null pointer.
+ void
+ deallocate(pointer __p, size_type __n);
+
+ size_type
+ max_size() const throw();
+
+ void construct(pointer __p, const _Tp& __val);
+ void destroy(pointer __p);
+ };
+
+ template<>
+ class allocator<void>
+ {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef void* pointer;
+ typedef const void* const_pointer;
+ typedef void value_type;
+
+ template<typename _Tp1>
+ struct rebind;
+ };
+} // namespace std
diff --git a/contrib/tools/swig/Lib/std/std_array.i b/contrib/tools/swig/Lib/std/std_array.i
new file mode 100644
index 00000000000..3f70ef57c22
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_array.i
@@ -0,0 +1,85 @@
+//
+// std::array
+//
+
+%include <std_container.i>
+
+%define %std_array_methods(array...)
+ %std_sequence_methods_non_resizable(array)
+ void fill(const value_type& u);
+%enddef
+
+
+%define %std_array_methods_val(array...)
+ %std_sequence_methods_non_resizable_val(array)
+ void fill(const value_type& u);
+%enddef
+
+// ------------------------------------------------------------------------
+// std::array
+//
+// The aim of all that follows would be to integrate std::array with
+// as much as possible, namely, to allow the user to pass and
+// be returned tuples or lists.
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::array<T, N>), f(const std::array<T, N>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::array<T, N> can be passed.
+// -- f(std::array<T, N>&), f(std::array<T, N>*):
+// the parameter may be modified; therefore, only a wrapped std::array
+// can be passed.
+// -- std::array<T, N> f(), const std::array<T, N>& f():
+// the array is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::array<T, N>& f(), std::array<T, N>* f():
+// the array is returned by reference; therefore, a wrapped std::array
+// is returned
+// -- const std::array<T, N>* f(), f(const std::array<T, N>*):
+// for consistency, they expect and return a plain array pointer.
+// ------------------------------------------------------------------------
+
+
+// exported classes
+
+namespace std {
+
+ template<class _Tp, size_t _Nm >
+ class array {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ %traits_swigtype(_Tp);
+ %traits_enum(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::array< _Tp, _Nm >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdArrayTraits") {
+ namespace swig {
+ template <> struct traits<std::array< _Tp, _Nm > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::array<" #_Tp "," #_Nm " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_STDARRAY, std::array< _Tp, _Nm >);
+
+#ifdef %swig_array_methods
+ // Add swig/language extra methods
+ %swig_array_methods(std::array< _Tp, _Nm >);
+#endif
+
+ %std_array_methods(array);
+ };
+}
+
diff --git a/contrib/tools/swig/Lib/std/std_basic_string.i b/contrib/tools/swig/Lib/std/std_basic_string.i
new file mode 100644
index 00000000000..e95cb476538
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_basic_string.i
@@ -0,0 +1,276 @@
+%include <exception.i>
+%include <std_container.i>
+%include <std_alloc.i>
+%include <std_char_traits.i>
+
+%fragment("<string>");
+
+namespace std
+{
+ %naturalvar basic_string;
+}
+
+
+namespace std {
+
+ template <class _CharT, class _Traits = char_traits<_CharT>, typename _Alloc = allocator<_CharT> >
+ class basic_string
+ {
+#if !defined(SWIG_STD_MODERN_STL) || defined(SWIG_STD_NOMODERN_STL)
+ %ignore push_back;
+ %ignore clear;
+ %ignore compare;
+ %ignore append;
+#endif
+
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _CharT value_type;
+ typedef value_type reference;
+ typedef value_type const_reference;
+ typedef _Alloc allocator_type;
+
+ static const size_type npos;
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ class iterator;
+ class reverse_iterator;
+ class const_iterator;
+ class const_reverse_iterator;
+#endif
+
+
+ %traits_swigtype(_CharT);
+ %fragment(SWIG_Traits_frag(_CharT));
+
+
+ basic_string(const _CharT* __s, size_type __n);
+
+ // Capacity:
+
+ size_type length() const;
+
+ size_type max_size() const;
+
+ size_type capacity() const;
+
+ void reserve(size_type __res_arg);
+ %extend {
+ void shrink_to_fit() {
+ %#if __cplusplus >= 202002L
+ self->shrink_to_fit();
+ %#else
+ self->reserve();
+ %#endif
+ }
+ }
+
+
+ // Modifiers:
+
+ basic_string&
+ append(const basic_string& __str);
+
+ basic_string&
+ append(const basic_string& __str, size_type __pos, size_type __n);
+
+ basic_string&
+ append(const _CharT* __s, size_type __n);
+
+ basic_string&
+ append(size_type __n, _CharT __c);
+
+ basic_string&
+ assign(const basic_string& __str);
+
+ basic_string&
+ assign(const basic_string& __str, size_type __pos, size_type __n);
+
+ basic_string&
+ assign(const _CharT* __s, size_type __n);
+
+ basic_string&
+ insert(size_type __pos1, const basic_string& __str);
+
+ basic_string&
+ insert(size_type __pos1, const basic_string& __str,
+ size_type __pos2, size_type __n);
+
+ basic_string&
+ insert(size_type __pos, const _CharT* __s, size_type __n);
+
+ basic_string&
+ insert(size_type __pos, size_type __n, _CharT __c);
+
+ basic_string&
+ erase(size_type __pos = 0, size_type __n = npos);
+
+ basic_string&
+ replace(size_type __pos, size_type __n, const basic_string& __str);
+
+ basic_string&
+ replace(size_type __pos1, size_type __n1, const basic_string& __str,
+ size_type __pos2, size_type __n2);
+
+ basic_string&
+ replace(size_type __pos, size_type __n1, const _CharT* __s,
+ size_type __n2);
+
+ basic_string&
+ replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c);
+
+
+ size_type
+ copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
+
+ // String operations:
+ const _CharT* c_str() const;
+
+ size_type
+ find(const _CharT* __s, size_type __pos, size_type __n) const;
+
+ size_type
+ find(const basic_string& __str, size_type __pos = 0) const;
+
+ size_type
+ find(_CharT __c, size_type __pos = 0) const;
+
+ size_type
+ rfind(const basic_string& __str, size_type __pos = npos) const;
+
+ size_type
+ rfind(const _CharT* __s, size_type __pos, size_type __n) const;
+
+ size_type
+ rfind(_CharT __c, size_type __pos = npos) const;
+
+ size_type
+ find_first_of(const basic_string& __str, size_type __pos = 0) const;
+
+ size_type
+ find_first_of(const _CharT* __s, size_type __pos, size_type __n) const;
+
+ size_type
+ find_first_of(_CharT __c, size_type __pos = 0) const;
+
+ size_type
+ find_last_of(const basic_string& __str, size_type __pos = npos) const;
+
+ size_type
+ find_last_of(const _CharT* __s, size_type __pos, size_type __n) const;
+
+ size_type
+ find_last_of(_CharT __c, size_type __pos = npos) const;
+
+ size_type
+ find_first_not_of(const basic_string& __str, size_type __pos = 0) const;
+
+ size_type
+ find_first_not_of(const _CharT* __s, size_type __pos,
+ size_type __n) const;
+
+ size_type
+ find_first_not_of(_CharT __c, size_type __pos = 0) const;
+
+ size_type
+ find_last_not_of(const basic_string& __str, size_type __pos = npos) const;
+
+ size_type
+ find_last_not_of(const _CharT* __s, size_type __pos,
+ size_type __n) const;
+
+ size_type
+ find_last_not_of(_CharT __c, size_type __pos = npos) const;
+
+ basic_string
+ substr(size_type __pos = 0, size_type __n = npos) const;
+
+ int
+ compare(const basic_string& __str) const;
+
+ int
+ compare(size_type __pos, size_type __n, const basic_string& __str) const;
+
+ int
+ compare(size_type __pos1, size_type __n1, const basic_string& __str,
+ size_type __pos2, size_type __n2) const;
+
+
+ %ignore pop_back();
+ %ignore front() const;
+ %ignore back() const;
+ %ignore basic_string(size_type n);
+ %std_sequence_methods_val(basic_string);
+
+
+ %ignore pop();
+
+
+#ifdef %swig_basic_string
+ // Add swig/language extra methods
+ %swig_basic_string(std::basic_string< _CharT, _Traits, _Alloc >);
+#endif
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+
+
+ class iterator;
+ class reverse_iterator;
+ class const_iterator;
+ class const_reverse_iterator;
+
+
+ void
+ insert(iterator __p, size_type __n, _CharT __c);
+
+ basic_string&
+ replace(iterator __i1, iterator __i2, const basic_string& __str);
+
+ basic_string&
+ replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n);
+
+ basic_string&
+ replace(iterator __i1, iterator __i2, size_type __n, _CharT __c);
+
+
+ basic_string&
+ replace(iterator __i1, iterator __i2, const _CharT* __k1, const _CharT* __k2);
+
+ basic_string&
+ replace(iterator __i1, iterator __i2, const_iterator __k1, const_iterator __k2);
+#endif
+
+ basic_string& operator +=(const basic_string& v);
+
+ %newobject __add__;
+ %newobject __radd__;
+ %extend {
+
+ std::basic_string< _CharT,_Traits,_Alloc >* __add__(const basic_string& v) {
+ std::basic_string< _CharT,_Traits,_Alloc >* res = new std::basic_string< _CharT,_Traits,_Alloc >(*self);
+ *res += v;
+ return res;
+ }
+
+ std::basic_string< _CharT,_Traits,_Alloc >* __radd__(const basic_string& v) {
+ std::basic_string< _CharT,_Traits,_Alloc >* res = new std::basic_string< _CharT,_Traits,_Alloc >(v);
+ *res += *self;
+ return res;
+ }
+
+ std::basic_string< _CharT,_Traits,_Alloc > __str__() {
+ return *self;
+ }
+
+ std::basic_ostream<_CharT, std::char_traits<_CharT> >&
+ __rlshift__(std::basic_ostream<_CharT, std::char_traits<_CharT> >& out) {
+ out << *self;
+ return out;
+ }
+ }
+
+ };
+}
+
+
diff --git a/contrib/tools/swig/Lib/std/std_char_traits.i b/contrib/tools/swig/Lib/std/std_char_traits.i
new file mode 100644
index 00000000000..b9b4def32fd
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_char_traits.i
@@ -0,0 +1,140 @@
+%include <std_common.i>
+#if defined(SWIG_WCHAR)
+%include <wchar.i>
+#endif
+
+namespace std
+{
+
+ /// 21.1.2 Basis for explicit _Traits specialization
+ /// NB: That for any given actual character type this definition is
+ /// probably wrong.
+ template<class _CharT>
+ struct char_traits
+ {
+ };
+
+
+ /// 21.1.4 char_traits specializations
+ template<>
+ struct char_traits<char> {
+ typedef char char_type;
+ typedef int int_type;
+ typedef streampos pos_type;
+ typedef streamoff off_type;
+ typedef mbstate_t state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2);
+
+ static bool
+ eq(const char_type& __c1, const char_type& __c2);
+
+ static bool
+ lt(const char_type& __c1, const char_type& __c2);
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, size_t __n);
+
+ static size_t
+ length(const char_type* __s);
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a);
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, size_t __n);
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n);
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a);
+
+ static char_type
+ to_char_type(const int_type& __c);
+
+ // To keep both the byte 0xff and the eof symbol 0xffffffff
+ // from ending up as 0xffffffff.
+ static int_type
+ to_int_type(const char_type& __c);
+
+ static bool
+ eq_int_type(const int_type& __c1, const int_type& __c2);
+
+ static int_type
+ eof() ;
+
+ static int_type
+ not_eof(const int_type& __c);
+ };
+
+
+#if defined(SWIG_WCHAR)
+ template<>
+ struct char_traits<wchar_t>
+ {
+ typedef wchar_t char_type;
+ typedef wint_t int_type;
+ typedef streamoff off_type;
+ typedef wstreampos pos_type;
+ typedef mbstate_t state_type;
+
+ static void
+ assign(char_type& __c1, const char_type& __c2);
+
+ static bool
+ eq(const char_type& __c1, const char_type& __c2);
+
+ static bool
+ lt(const char_type& __c1, const char_type& __c2);
+
+ static int
+ compare(const char_type* __s1, const char_type* __s2, size_t __n);
+
+ static size_t
+ length(const char_type* __s);
+
+ static const char_type*
+ find(const char_type* __s, size_t __n, const char_type& __a);
+
+ static char_type*
+ move(char_type* __s1, const char_type* __s2, int_type __n);
+
+ static char_type*
+ copy(char_type* __s1, const char_type* __s2, size_t __n);
+
+ static char_type*
+ assign(char_type* __s, size_t __n, char_type __a);
+
+ static char_type
+ to_char_type(const int_type& __c) ;
+
+ static int_type
+ to_int_type(const char_type& __c) ;
+
+ static bool
+ eq_int_type(const int_type& __c1, const int_type& __c2);
+
+ static int_type
+ eof() ;
+
+ static int_type
+ not_eof(const int_type& __c);
+ };
+#endif
+}
+
+namespace std {
+#ifndef SWIG_STL_WRAP_TRAITS
+%template() char_traits<char>;
+#if defined(SWIG_WCHAR)
+%template() char_traits<wchar_t>;
+#endif
+#else
+%template(char_traits_c) char_traits<char>;
+#if defined(SWIG_WCHAR)
+%template(char_traits_w) char_traits<wchar_t>;
+#endif
+#endif
+}
diff --git a/contrib/tools/swig/Lib/std/std_common.i b/contrib/tools/swig/Lib/std/std_common.i
new file mode 100644
index 00000000000..708f3ceedf9
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_common.i
@@ -0,0 +1,250 @@
+%include <std/std_except.i>
+
+//
+// Use the following macro with modern STL implementations
+//
+//#define SWIG_STD_MODERN_STL
+//
+// Use this to deactivate the previous definition, when using gcc-2.95
+// or similar old compilers.
+//
+//#define SWIG_STD_NOMODERN_STL
+
+// Here, we identify compilers we know have problems with STL.
+%{
+#if defined(__GNUC__)
+# if __GNUC__ == 2 && __GNUC_MINOR <= 96
+# define SWIG_STD_NOMODERN_STL
+# endif
+#endif
+%}
+
+//
+// Common code for supporting the C++ std namespace
+//
+
+%fragment("<string>");
+%fragment("<stdexcept>");
+%fragment("<stddef.h>");
+
+
+%fragment("StdIteratorTraits","header",fragment="<stddef.h>") %{
+#if defined(__SUNPRO_CC) && defined(_RWSTD_VER)
+# if !defined(SWIG_NO_STD_NOITERATOR_TRAITS_STL)
+# define SWIG_STD_NOITERATOR_TRAITS_STL
+# endif
+#endif
+
+#if !defined(SWIG_STD_NOITERATOR_TRAITS_STL)
+#include <iterator>
+#else
+namespace std {
+ template <class Iterator>
+ struct iterator_traits {
+ typedef ptrdiff_t difference_type;
+ typedef typename Iterator::value_type value_type;
+ };
+
+ template <class Iterator, class Category,class T, class Reference, class Pointer, class Distance>
+ struct iterator_traits<__reverse_bi_iterator<Iterator,Category,T,Reference,Pointer,Distance> > {
+ typedef Distance difference_type;
+ typedef T value_type;
+ };
+
+ template <class T>
+ struct iterator_traits<T*> {
+ typedef T value_type;
+ typedef ptrdiff_t difference_type;
+ };
+
+ template<typename _InputIterator>
+ inline typename iterator_traits<_InputIterator>::difference_type
+ distance(_InputIterator __first, _InputIterator __last)
+ {
+ typename iterator_traits<_InputIterator>::difference_type __n = 0;
+ while (__first != __last) {
+ ++__first; ++__n;
+ }
+ return __n;
+ }
+}
+#endif
+%}
+
+%fragment("StdTraitsCommon","header",fragment="<string>") %{
+namespace swig {
+ template <class Type>
+ struct noconst_traits {
+ typedef Type noconst_type;
+ };
+
+ template <class Type>
+ struct noconst_traits<const Type> {
+ typedef Type noconst_type;
+ };
+
+ /*
+ type categories
+ */
+ struct pointer_category { };
+ struct value_category { };
+
+ /*
+ General traits that provides type_name and type_info
+ */
+ template <class Type> struct traits { };
+
+ template <class Type>
+ inline const char* type_name() {
+ return traits<typename noconst_traits<Type >::noconst_type >::type_name();
+ }
+
+ template <class Type> struct traits_info {
+ static swig_type_info *type_query(std::string name) {
+ name += " *";
+ return SWIG_TypeQuery(name.c_str());
+ }
+ static swig_type_info *type_info() {
+ static swig_type_info *info = type_query(type_name<Type>());
+ return info;
+ }
+ };
+
+ /*
+ Partial specialization for pointers (traits_info)
+ */
+ template <class Type> struct traits_info<Type *> {
+ static swig_type_info *type_query(std::string name) {
+ name += " *";
+ return SWIG_TypeQuery(name.c_str());
+ }
+ static swig_type_info *type_info() {
+ static swig_type_info *info = type_query(type_name<Type>());
+ return info;
+ }
+ };
+
+ template <class Type>
+ inline swig_type_info *type_info() {
+ return traits_info<Type>::type_info();
+ }
+
+ /*
+ Partial specialization for pointers (traits)
+ */
+ template <class Type> struct traits <Type *> {
+ typedef pointer_category category;
+ static std::string make_ptr_name(const char* name) {
+ std::string ptrname = name;
+ ptrname += " *";
+ return ptrname;
+ }
+ static const char* type_name() {
+ static std::string name = make_ptr_name(swig::type_name<Type>());
+ return name.c_str();
+ }
+ };
+
+ template <class Type, class Category>
+ struct traits_as { };
+
+ template <class Type, class Category>
+ struct traits_check { };
+
+}
+%}
+
+/*
+ Generate the traits for a swigtype
+*/
+
+%define %traits_swigtype(Type...)
+%fragment(SWIG_Traits_frag(Type),"header",fragment="StdTraits") {
+ namespace swig {
+ template <> struct traits< Type > {
+ typedef pointer_category category;
+ static const char* type_name() { return #Type; }
+ };
+ }
+}
+%enddef
+
+
+
+/*
+ Generate the typemaps for a class that has 'value' traits
+*/
+
+%define %typemap_traits(Code,Type...)
+ %typemaps_asvalfrom(%arg(Code),
+ %arg(swig::asval< Type >),
+ %arg(swig::from),
+ %arg(SWIG_Traits_frag(Type)),
+ %arg(SWIG_Traits_frag(Type)),
+ Type);
+%enddef
+
+/*
+ Generate the typemaps for a class that behaves more like a 'pointer' or
+ plain wrapped Swigtype.
+*/
+
+%define %typemap_traits_ptr(Code,Type...)
+ %typemaps_asptrfrom(%arg(Code),
+ %arg(swig::asptr),
+ %arg(swig::from),
+ %arg(SWIG_Traits_frag(Type)),
+ %arg(SWIG_Traits_frag(Type)),
+ Type);
+%enddef
+
+
+/*
+ Equality methods
+*/
+%define %std_equal_methods(Type...)
+%extend Type {
+ bool operator == (const Type& v) {
+ return *self == v;
+ }
+
+ bool operator != (const Type& v) {
+ return *self != v;
+ }
+}
+
+%enddef
+
+/*
+ Order methods
+*/
+
+%define %std_order_methods(Type...)
+%extend Type {
+ bool operator > (const Type& v) {
+ return *self > v;
+ }
+
+ bool operator < (const Type& v) {
+ return *self < v;
+ }
+
+ bool operator >= (const Type& v) {
+ return *self >= v;
+ }
+
+ bool operator <= (const Type& v) {
+ return *self <= v;
+ }
+}
+%enddef
+
+/*
+ Comparison methods
+*/
+
+%define %std_comp_methods(Type...)
+%std_equal_methods(Type )
+%std_order_methods(Type )
+%enddef
+
diff --git a/contrib/tools/swig/Lib/std/std_container.i b/contrib/tools/swig/Lib/std/std_container.i
new file mode 100644
index 00000000000..570dfde484e
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_container.i
@@ -0,0 +1,169 @@
+%include <std_common.i>
+%include <exception.i>
+%include <std_alloc.i>
+
+%{
+#include <algorithm>
+%}
+
+// Common non-resizable container methods
+
+%define %std_container_methods_non_resizable(container...)
+
+ container();
+ container(const container& other);
+
+ bool empty() const;
+ size_type size() const;
+ void swap(container& v);
+
+%enddef
+
+%define %std_container_methods_forward_iterators(container...)
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+ class iterator;
+ class const_iterator;
+ iterator begin();
+ iterator end();
+ #endif
+
+%enddef
+
+%define %std_container_methods_reverse_iterators(container...)
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+ class reverse_iterator;
+ class const_reverse_iterator;
+ reverse_iterator rbegin();
+ reverse_iterator rend();
+ #endif
+
+%enddef
+
+// Common container methods
+
+%define %std_container_methods(container...)
+
+ %std_container_methods_non_resizable(%arg(container))
+ %std_container_methods_forward_iterators(%arg(container))
+ %std_container_methods_reverse_iterators(%arg(container))
+
+ void clear();
+ allocator_type get_allocator() const;
+
+%enddef
+
+%define %std_container_methods_without_reverse_iterators(container...)
+
+ %std_container_methods_non_resizable(%arg(container))
+ %std_container_methods_forward_iterators(%arg(container))
+
+ void clear();
+ allocator_type get_allocator() const;
+
+%enddef
+
+// Common sequence
+
+%define %std_sequence_methods_common(sequence)
+
+ %std_container_methods(%arg(sequence));
+
+ sequence(size_type size);
+ void pop_back();
+
+ void resize(size_type new_size);
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ iterator erase(iterator pos) { return $self->erase(pos); }
+ iterator erase(iterator first, iterator last) { return $self->erase(first, last); }
+}
+ #endif
+
+%enddef
+
+%define %std_sequence_methods_non_resizable(sequence)
+
+ %std_container_methods_non_resizable(%arg(sequence))
+ %std_container_methods_forward_iterators(%arg(container))
+ %std_container_methods_reverse_iterators(%arg(container))
+
+ const value_type& front() const;
+ const value_type& back() const;
+
+%enddef
+
+%define %std_sequence_methods(sequence)
+
+ %std_sequence_methods_common(%arg(sequence));
+
+ sequence(size_type size, const value_type& value);
+ void push_back(const value_type& x);
+
+ const value_type& front() const;
+ const value_type& back() const;
+
+ void assign(size_type n, const value_type& x);
+ void resize(size_type new_size, const value_type& x);
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ iterator insert(iterator pos, const value_type& x) { return $self->insert(pos, x); }
+ void insert(iterator pos, size_type n, const value_type& x) { $self->insert(pos, n, x); }
+}
+ #endif
+
+%enddef
+
+%define %std_sequence_methods_non_resizable_val(sequence...)
+
+ %std_container_methods_non_resizable(%arg(sequence))
+ %std_container_methods_forward_iterators(%arg(container))
+ %std_container_methods_reverse_iterators(%arg(container))
+
+ value_type front() const;
+ value_type back() const;
+
+#endif
+
+%enddef
+
+%define %std_sequence_methods_val(sequence...)
+
+ %std_sequence_methods_common(%arg(sequence));
+
+ sequence(size_type size, value_type value);
+ void push_back(value_type x);
+
+ value_type front() const;
+ value_type back() const;
+
+ void assign(size_type n, value_type x);
+ void resize(size_type new_size, value_type x);
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ iterator insert(iterator pos, value_type x) { return $self->insert(pos, x); }
+ void insert(iterator pos, size_type n, value_type x) { $self->insert(pos, n, x); }
+}
+ #endif
+
+%enddef
+
+
+//
+// Ignore member methods for Type with no default constructor
+//
+%define %std_nodefconst_type(Type...)
+%feature("ignore") std::vector< Type >::vector(size_type size);
+%feature("ignore") std::vector< Type >::resize(size_type size);
+%feature("ignore") std::deque< Type >::deque(size_type size);
+%feature("ignore") std::deque< Type >::resize(size_type size);
+%feature("ignore") std::list< Type >::list(size_type size);
+%feature("ignore") std::list< Type >::resize(size_type size);
+%enddef
diff --git a/contrib/tools/swig/Lib/std/std_deque.i b/contrib/tools/swig/Lib/std/std_deque.i
new file mode 100644
index 00000000000..aa5536bf612
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_deque.i
@@ -0,0 +1,127 @@
+//
+// std::deque
+
+%include <std_container.i>
+
+// Deque
+
+%define %std_deque_methods(deque...)
+ %std_sequence_methods(deque)
+
+ void pop_front();
+ void push_front(const value_type& x);
+%enddef
+
+%define %std_deque_methods_val(deque...)
+ %std_sequence_methods_val(deque)
+
+ void pop_front();
+ void push_front(value_type x);
+%enddef
+
+// ------------------------------------------------------------------------
+// std::deque
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::deque<T>), f(const std::deque<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::deque<T> can be passed.
+// -- f(std::deque<T>&), f(std::deque<T>*):
+// the parameter may be modified; therefore, only a wrapped std::deque
+// can be passed.
+// -- std::deque<T> f(), const std::deque<T>& f():
+// the deque is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::deque<T>& f(), std::deque<T>* f():
+// the deque is returned by reference; therefore, a wrapped std::deque
+// is returned
+// -- const std::deque<T>* f(), f(const std::deque<T>*):
+// for consistency, they expect and return a plain deque pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <deque>
+%}
+
+// exported classes
+
+namespace std {
+
+ template<class _Tp, class _Alloc = allocator< _Tp > >
+ class deque {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::deque< _Tp, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdDequeTraits") {
+ namespace swig {
+ template <> struct traits<std::deque< _Tp, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::deque<" #_Tp " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_DEQUE, std::deque< _Tp, _Alloc >);
+
+#ifdef %swig_deque_methods
+ // Add swig/language extra methods
+ %swig_deque_methods(std::deque< _Tp, _Alloc >);
+#endif
+
+ %std_deque_methods(deque);
+ };
+
+ template<class _Tp, class _Alloc >
+ class deque< _Tp*, _Alloc > {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp* value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type reference;
+ typedef value_type const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::deque< _Tp*, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdDequeTraits") {
+ namespace swig {
+ template <> struct traits<std::deque< _Tp*, _Alloc > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::deque<" #_Tp " * >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_DEQUE, std::deque< _Tp*, _Alloc >);
+
+#ifdef %swig_deque_methods_val
+ // Add swig/language extra methods
+ %swig_deque_methods_val(std::deque< _Tp*, _Alloc >);
+#endif
+
+ %std_deque_methods_val(deque);
+ };
+
+}
+
diff --git a/contrib/tools/swig/Lib/std/std_except.i b/contrib/tools/swig/Lib/std/std_except.i
new file mode 100644
index 00000000000..728b9c8b529
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_except.i
@@ -0,0 +1,73 @@
+#if defined(SWIGJAVA) || defined(SWIGCSHARP)
+#error "do not use this version of std_except.i"
+#endif
+
+%{
+#include <typeinfo>
+#include <stdexcept>
+%}
+
+#if defined(SWIG_STD_EXCEPTIONS_AS_CLASSES)
+
+namespace std {
+ struct exception
+ {
+ virtual ~exception() throw();
+ virtual const char* what() const throw();
+ };
+
+ struct bad_cast : exception
+ {
+ };
+
+ struct bad_exception : exception
+ {
+ };
+
+ struct logic_error : exception
+ {
+ logic_error(const string& msg);
+ };
+
+ struct domain_error : logic_error
+ {
+ domain_error(const string& msg);
+ };
+
+ struct invalid_argument : logic_error
+ {
+ invalid_argument(const string& msg);
+ };
+
+ struct length_error : logic_error
+ {
+ length_error(const string& msg);
+ };
+
+ struct out_of_range : logic_error
+ {
+ out_of_range(const string& msg);
+ };
+
+ struct runtime_error : exception
+ {
+ runtime_error(const string& msg);
+ };
+
+ struct range_error : runtime_error
+ {
+ range_error(const string& msg);
+ };
+
+ struct overflow_error : runtime_error
+ {
+ overflow_error(const string& msg);
+ };
+
+ struct underflow_error : runtime_error
+ {
+ underflow_error(const string& msg);
+ };
+}
+
+#endif
diff --git a/contrib/tools/swig/Lib/std/std_ios.i b/contrib/tools/swig/Lib/std/std_ios.i
new file mode 100644
index 00000000000..7c62ed6904a
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_ios.i
@@ -0,0 +1,262 @@
+%include <std_char_traits.i>
+%include <std_basic_string.i>
+%include <std_except.i>
+%{
+#ifndef SWIG_STD_NOMODERN_STL
+# include <ios>
+#else
+# include <streambuf.h>
+#endif
+%}
+
+namespace std {
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_streambuf;
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_istream;
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_ostream;
+
+ // 27.4.2 Class ios_base
+ typedef size_t streamsize;
+
+ class locale;
+
+
+ class ios_base
+ {
+ public:
+
+#ifdef SWIG_NESTED_CLASSES
+ // 27.4.2.1.1 Class ios_base::failure
+ class failure : public exception
+ {
+ public:
+ explicit failure(const string& __str) throw();
+ };
+#endif
+
+ // 27.4.2.1.2 Type ios_base::fmtflags
+ typedef int fmtflags;
+ // 27.4.2.1.2 Type fmtflags
+ static const fmtflags boolalpha ;
+ static const fmtflags dec ;
+ static const fmtflags fixed ;
+ static const fmtflags hex ;
+ static const fmtflags internal ;
+ static const fmtflags left ;
+ static const fmtflags oct ;
+ static const fmtflags right ;
+ static const fmtflags scientific ;
+ static const fmtflags showbase ;
+ static const fmtflags showpoint ;
+ static const fmtflags showpos ;
+ static const fmtflags skipws ;
+ static const fmtflags unitbuf ;
+ static const fmtflags uppercase ;
+ static const fmtflags adjustfield ;
+ static const fmtflags basefield ;
+ static const fmtflags floatfield ;
+
+ // 27.4.2.1.3 Type ios_base::iostate
+ typedef int iostate;
+ static const iostate badbit ;
+ static const iostate eofbit ;
+ static const iostate failbit ;
+ static const iostate goodbit ;
+
+ // 27.4.2.1.4 Type openmode
+ typedef int openmode;
+ static const openmode app ;
+ static const openmode ate ;
+ static const openmode binary ;
+ static const openmode in ;
+ static const openmode out ;
+ static const openmode trunc ;
+
+ // 27.4.2.1.5 Type seekdir
+ typedef int seekdir;
+ static const seekdir beg ;
+ static const seekdir cur ;
+ static const seekdir end ;
+
+
+ // Callbacks;
+ enum event
+ {
+ erase_event,
+ imbue_event,
+ copyfmt_event
+ };
+
+ typedef void (*event_callback) (event, ios_base&, int);
+
+ void
+ register_callback(event_callback __fn, int __index);
+
+ // Fmtflags state:
+ inline fmtflags
+ flags() const ;
+
+ inline fmtflags
+ flags(fmtflags __fmtfl);
+
+ inline fmtflags
+ setf(fmtflags __fmtfl);
+
+ inline fmtflags
+ setf(fmtflags __fmtfl, fmtflags __mask);
+
+ inline void
+ unsetf(fmtflags __mask) ;
+
+ inline streamsize
+ precision() const ;
+
+ inline streamsize
+ precision(streamsize __prec);
+
+ inline streamsize
+ width() const ;
+
+ inline streamsize
+ width(streamsize __wide);
+
+ static bool
+ sync_with_stdio(bool __sync = true);
+
+ // Locales:
+ locale
+ imbue(const locale& __loc);
+
+ inline locale
+ getloc() const { return _M_ios_locale; }
+
+ // Storage:
+ static int
+ xalloc() throw();
+
+ inline long&
+ iword(int __ix);
+
+ inline void*&
+ pword(int __ix);
+
+ // Destructor
+ ~ios_base();
+
+ protected:
+ ios_base();
+
+ //50. Copy constructor and assignment operator of ios_base
+ private:
+ ios_base(const ios_base& other);
+
+ ios_base&
+ operator=(const ios_base& other);
+ };
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_ios : public ios_base
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef typename _Traits::int_type int_type;
+ typedef typename _Traits::pos_type pos_type;
+ typedef typename _Traits::off_type off_type;
+ typedef _Traits traits_type;
+
+ public:
+
+ iostate
+ rdstate() const;
+
+ void
+ clear(iostate __state = goodbit);
+
+ void
+ setstate(iostate __state);
+
+ bool
+ good() const;
+
+ bool
+ eof() const;
+
+ bool
+ fail() const;
+
+ bool
+ bad() const;
+
+ iostate
+ exceptions() const;
+
+ void
+ exceptions(iostate __except);
+
+ // Constructor/destructor:
+ explicit
+ basic_ios(basic_streambuf<_CharT, _Traits>* __sb) : ios_base();
+
+ virtual
+ ~basic_ios() ;
+
+ // Members:
+ basic_ostream<_CharT, _Traits>*
+ tie() const;
+
+ basic_ostream<_CharT, _Traits>*
+ tie(basic_ostream<_CharT, _Traits>* __tiestr);
+
+ basic_streambuf<_CharT, _Traits>*
+ rdbuf() const;
+
+ basic_streambuf<_CharT, _Traits>*
+ rdbuf(basic_streambuf<_CharT, _Traits>* __sb);
+
+ basic_ios&
+ copyfmt(const basic_ios& __rhs);
+
+ char_type
+ fill() const;
+
+ char_type
+ fill(char_type __ch);
+
+ // Locales:
+ locale
+ imbue(const locale& __loc);
+
+ char
+ narrow(char_type __c, char __dfault) const;
+
+ char_type
+ widen(char __c) const;
+
+ protected:
+ // 27.4.5.1 basic_ios constructors
+ basic_ios();
+ private:
+ basic_ios(const basic_ios& other);
+
+ basic_ios&
+ operator=(const basic_ios& other);
+ };
+
+}
+
+namespace std {
+ typedef basic_ios<char> ios;
+ %template(ios) basic_ios<char>;
+#if defined(SWIG_WCHAR)
+ typedef basic_ios<wchar_t> wios;
+ %template(wios) basic_ios<wchar_t>;
+#endif
+}
+
+
diff --git a/contrib/tools/swig/Lib/std/std_iostream.i b/contrib/tools/swig/Lib/std/std_iostream.i
new file mode 100644
index 00000000000..4c1269898df
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_iostream.i
@@ -0,0 +1,343 @@
+/*
+ For wchar support, you need to include the wchar.i file
+ before this file, ie:
+
+ %include <wchar.i>
+ %include <std_iostream.i>
+
+ or equivalently, just include
+
+ %include <std_wiostream.i>
+*/
+
+%include <std_ios.i>
+%include <std_basic_string.i>
+%include <std_string.i>
+#if defined(SWIG_WCHAR)
+%include <std_wstring.i>
+#endif
+
+%{
+#include <iostream>
+%}
+
+
+namespace std
+{
+ // 27.6.2.1 Template class basic_ostream
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_ostream : virtual public basic_ios<_CharT, _Traits>
+ {
+ public:
+ // Types (inherited from basic_ios (27.4.4)):
+ typedef _CharT char_type;
+ typedef typename _Traits::int_type int_type;
+ typedef typename _Traits::pos_type pos_type;
+ typedef typename _Traits::off_type off_type;
+ typedef _Traits traits_type;
+
+ // 27.6.2.2 Constructor/destructor:
+ explicit
+ basic_ostream(basic_streambuf<_CharT, _Traits>* __sb);
+
+ virtual
+ ~basic_ostream();
+
+ // 27.6.2.5 Formatted output:
+ // 27.6.2.5.3 basic_ostream::operator<<
+ basic_ostream<_CharT, _Traits>&
+ operator<<(basic_ostream<_CharT, _Traits>& (*__pf)(basic_ostream<_CharT, _Traits>&));
+
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(basic_ios<_CharT, _Traits>& (*__pf)(basic_ios<_CharT, _Traits>&));
+
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(ios_base& (*__pf) (ios_base&));
+
+ // 27.6.2.5.2 Arithmetic Inserters
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(long __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(unsigned long __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(bool __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(short __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(unsigned short __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(int __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(unsigned int __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(long long __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(unsigned long long __n);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(double __f);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(float __f);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(long double __f);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(const void* __p);
+
+ basic_ostream<_CharT, _Traits>&
+ operator<<(basic_streambuf<_CharT, _Traits>* __sb);
+
+ %extend {
+ std::basic_ostream<_CharT, _Traits >&
+ operator<<(const std::basic_string<_CharT,_Traits, std::allocator<_CharT> >& s)
+ {
+ *self << s;
+ return *self;
+ }
+ }
+
+ // Unformatted output:
+ basic_ostream<_CharT, _Traits>&
+ put(char_type __c);
+
+ basic_ostream<_CharT, _Traits>&
+ write(const char_type* __s, streamsize __n);
+
+ basic_ostream<_CharT, _Traits>&
+ flush();
+
+ // Seeks:
+ pos_type
+ tellp();
+
+ basic_ostream<_CharT, _Traits>&
+ seekp(pos_type);
+
+ basic_ostream<_CharT, _Traits>&
+ seekp(off_type, ios_base::seekdir);
+
+ };
+
+ // 27.6.1.1 Template class basic_istream
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_istream : virtual public basic_ios<_CharT, _Traits>
+ {
+ public:
+ // Types (inherited from basic_ios (27.4.4)):
+ typedef _CharT char_type;
+ typedef typename _Traits::int_type int_type;
+ typedef typename _Traits::pos_type pos_type;
+ typedef typename _Traits::off_type off_type;
+ typedef _Traits traits_type;
+
+
+ public:
+ // 27.6.1.1.1 Constructor/destructor:
+ explicit
+ basic_istream(basic_streambuf<_CharT, _Traits>* __sb);
+
+ virtual
+ ~basic_istream();
+
+ // 27.6.1.2.3 basic_istream::operator>>
+ basic_istream<_CharT, _Traits>&
+ operator>>(basic_istream<_CharT, _Traits>& (*__pf)(basic_istream<_CharT, _Traits>&));
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(basic_ios<_CharT, _Traits>& (*__pf)(basic_ios<_CharT, _Traits>&));
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(ios_base& (*__pf)(ios_base&));
+
+ // 27.6.1.2.2 Arithmetic Extractors
+ basic_istream<_CharT, _Traits>&
+ operator>>(bool& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(short& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(unsigned short& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(int& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(unsigned int& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(long& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(unsigned long& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(long long& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(unsigned long long& __n);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(float& __f);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(double& __f);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(long double& __f);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(void*& __p);
+
+ basic_istream<_CharT, _Traits>&
+ operator>>(basic_streambuf<_CharT, _Traits>* __sb);
+
+ // 27.6.1.3 Unformatted input:
+ inline streamsize
+ gcount(void) const;
+
+ int_type
+ get(void);
+
+ basic_istream<_CharT, _Traits>&
+ get(char_type& __c);
+
+ basic_istream<_CharT, _Traits>&
+ get(char_type* __s, streamsize __n, char_type __delim);
+
+ inline basic_istream<_CharT, _Traits>&
+ get(char_type* __s, streamsize __n);
+
+ basic_istream<_CharT, _Traits>&
+ get(basic_streambuf<_CharT, _Traits>& __sb, char_type __delim);
+
+ inline basic_istream<_CharT, _Traits>&
+ get(basic_streambuf<_CharT, _Traits>& __sb);
+
+ basic_istream<_CharT, _Traits>&
+ getline(char_type* __s, streamsize __n, char_type __delim);
+
+ inline basic_istream<_CharT, _Traits>&
+ getline(char_type* __s, streamsize __n);
+
+ basic_istream<_CharT, _Traits>&
+ ignore(streamsize __n = 1, int_type __delim = _Traits::eof());
+
+ int_type
+ peek(void);
+
+ basic_istream<_CharT, _Traits>&
+ read(char_type* __s, streamsize __n);
+
+ streamsize
+ readsome(char_type* __s, streamsize __n);
+
+ basic_istream<_CharT, _Traits>&
+ putback(char_type __c);
+
+ basic_istream<_CharT, _Traits>&
+ unget(void);
+
+ int
+ sync(void);
+
+ pos_type
+ tellg(void);
+
+ basic_istream<_CharT, _Traits>&
+ seekg(pos_type);
+
+ basic_istream<_CharT, _Traits>&
+ seekg(off_type, ios_base::seekdir);
+ };
+
+ %template(ostream) basic_ostream<char>;
+ %template(istream) basic_istream<char>;
+
+#if defined(SWIG_WCHAR)
+ %template(wostream) basic_ostream<wchar_t>;
+ %template(wistream) basic_istream<wchar_t>;
+#endif
+
+ // 27.6.1.5 Template class basic_iostream
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_iostream
+ : public basic_istream<_CharT, _Traits>,
+ public basic_ostream<_CharT, _Traits>
+ {
+ public:
+ typedef _CharT char_type;
+ typedef typename _Traits::int_type int_type;
+ typedef typename _Traits::pos_type pos_type;
+ typedef typename _Traits::off_type off_type;
+ typedef _Traits traits_type;
+
+ explicit
+ basic_iostream(basic_streambuf<_CharT, _Traits>* __sb);
+
+ virtual
+ ~basic_iostream();
+ };
+
+ typedef basic_ostream<char> ostream ;
+ typedef basic_istream<char> istream;
+ typedef basic_iostream<char> iostream;
+
+ extern istream cin;
+ extern ostream cout;
+ extern ostream cerr;
+ extern ostream clog;
+
+#if defined(SWIG_WCHAR)
+ typedef basic_ostream<wchar_t> wostream;
+ typedef basic_istream<wchar_t> wistream;
+ typedef basic_iostream<wchar_t> wiostream;
+
+ extern wistream wcin;
+ extern wostream wcout;
+ extern wostream wcerr;
+ extern wostream wclog;
+#endif
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ std::basic_ostream<_CharT, _Traits>&
+ endl(std::basic_ostream<_CharT, _Traits>& value);
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ std::basic_ostream<_CharT, _Traits>&
+ ends(std::basic_ostream<_CharT, _Traits>& value);
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ std::basic_ostream<_CharT, _Traits>&
+ flush(std::basic_ostream<_CharT, _Traits>& value);
+}
+
+namespace std {
+ %template(iostream) basic_iostream<char>;
+
+ %template(endl) endl<char, std::char_traits<char> >;
+ %template(ends) ends<char, std::char_traits<char> >;
+ %template(flush) flush<char, std::char_traits<char> >;
+
+#if defined(SWIG_WCHAR)
+ %template(wiostream) basic_iostream<wchar_t>;
+
+ %template(wendl) endl<wchar_t, std::char_traits<wchar_t> >;
+ %template(wends) ends<wchar_t, std::char_traits<wchar_t> >;
+ %template(wflush) flush<wchar_t, std::char_traits<wchar_t> >;
+#endif
+}
+
diff --git a/contrib/tools/swig/Lib/std/std_list.i b/contrib/tools/swig/Lib/std/std_list.i
new file mode 100644
index 00000000000..2cc2d97cfe1
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_list.i
@@ -0,0 +1,148 @@
+//
+// std::list
+//
+
+%include <std_container.i>
+
+// List
+
+%define %std_list_methods(list...)
+ %std_sequence_methods(list)
+
+ void pop_front();
+ void push_front(const value_type& x);
+
+ void reverse();
+
+%enddef
+
+
+%define %std_list_methods_val(list...)
+ %std_sequence_methods_val(list)
+
+ void pop_front();
+ void push_front(value_type x);
+
+ void remove(value_type x);
+ void unique();
+ void reverse();
+ void sort();
+
+ void merge(list& x);
+%enddef
+
+// ------------------------------------------------------------------------
+// std::list
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::list<T>), f(const std::list<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::list<T> can be passed.
+// -- f(std::list<T>&), f(std::list<T>*):
+// the parameter may be modified; therefore, only a wrapped std::list
+// can be passed.
+// -- std::list<T> f(), const std::list<T>& f():
+// the list is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::list<T>& f(), std::list<T>* f():
+// the list is returned by reference; therefore, a wrapped std::list
+// is returned
+// -- const std::list<T>* f(), f(const std::list<T>*):
+// for consistency, they expect and return a plain list pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <list>
+%}
+
+// exported classes
+
+namespace std {
+
+ template<class _Tp, class _Alloc = allocator< _Tp > >
+ class list {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::list< _Tp, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdListTraits") {
+ namespace swig {
+ template <> struct traits<std::list< _Tp, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::list<" #_Tp ", " #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_LIST, std::list< _Tp, _Alloc >);
+
+#ifdef %swig_list_methods
+ // Add swig/language extra methods
+ %swig_list_methods(std::list< _Tp, _Alloc >);
+#endif
+
+ %std_list_methods(list);
+ };
+
+ template<class _Tp, class _Alloc >
+ class list< _Tp*, _Alloc> {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp* value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::list< _Tp*, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdListTraits") {
+ namespace swig {
+ template <> struct traits<std::list< _Tp*, _Alloc > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::list<" #_Tp " *," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_LIST, std::list< _Tp*, _Alloc >);
+
+#ifdef %swig_list_methods_val
+ // Add swig/language extra methods
+ %swig_list_methods_val(std::list< _Tp*, _Alloc >);
+#endif
+
+ %std_list_methods_val(list);
+ };
+
+}
+
+%define %std_extequal_list(...)
+%extend std::list< __VA_ARGS__ > {
+ void remove(const value_type& x) { self->remove(x); }
+ void merge(std::list< __VA_ARGS__ >& x){ self->merge(x); }
+ void unique() { self->unique(); }
+ void sort() { self->sort(); }
+}
+%enddef
+
diff --git a/contrib/tools/swig/Lib/std/std_map.i b/contrib/tools/swig/Lib/std/std_map.i
new file mode 100644
index 00000000000..62f5cb37c02
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_map.i
@@ -0,0 +1,125 @@
+//
+// std::map
+//
+
+%include <std_pair.i>
+%include <std_container.i>
+
+%define %std_map_methods_common(map...)
+ %std_container_methods(map);
+
+ size_type erase(const key_type& x);
+ size_type count(const key_type& x) const;
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ void erase(iterator position) { $self->erase(position); }
+ void erase(iterator first, iterator last) { $self->erase(first, last); }
+}
+
+ iterator find(const key_type& x);
+ iterator lower_bound(const key_type& x);
+ iterator upper_bound(const key_type& x);
+#endif
+%enddef
+
+%define %std_map_methods(map...)
+ %std_map_methods_common(map);
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+// iterator insert(const value_type& x);
+ #endif
+%enddef
+
+
+// ------------------------------------------------------------------------
+// std::map
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::map<T>), f(const std::map<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::map<T> can be passed.
+// -- f(std::map<T>&), f(std::map<T>*):
+// the parameter may be modified; therefore, only a wrapped std::map
+// can be passed.
+// -- std::map<T> f(), const std::map<T>& f():
+// the map is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::map<T>& f(), std::map<T>* f():
+// the map is returned by reference; therefore, a wrapped std::map
+// is returned
+// -- const std::map<T>* f(), f(const std::map<T>*):
+// for consistency, they expect and return a plain map pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <map>
+%}
+%fragment("<algorithm>");
+%fragment("<stdexcept>");
+
+// exported class
+
+namespace std {
+
+ template<class _Key, class _Tp, class _Compare = std::less<_Key >,
+ class _Alloc = allocator<std::pair< const _Key, _Tp > > >
+ class map {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef std::pair< const _Key, _Tp > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::pair< _Key, _Tp >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< _Key, _Tp > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #_Key "," #_Tp " >";
+ }
+ };
+ }
+ }
+
+ %fragment(SWIG_Traits_frag(std::map< _Key, _Tp, _Compare, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(std::pair< _Key, _Tp >),
+ fragment="StdMapTraits") {
+ namespace swig {
+ template <> struct traits<std::map< _Key, _Tp, _Compare, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::map<" #_Key "," #_Tp "," #_Compare "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_MAP, std::map< _Key, _Tp, _Compare, _Alloc >);
+
+ map(const _Compare& other);
+
+#ifdef %swig_map_methods
+ // Add swig/language extra methods
+ %swig_map_methods(std::map< _Key, _Tp, _Compare, _Alloc >);
+#endif
+
+ %std_map_methods(map);
+ };
+
+}
diff --git a/contrib/tools/swig/Lib/std/std_multimap.i b/contrib/tools/swig/Lib/std/std_multimap.i
new file mode 100644
index 00000000000..03e76534121
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_multimap.i
@@ -0,0 +1,100 @@
+//
+// std::multimap
+//
+
+%include <std_map.i>
+
+
+%define %std_multimap_methods(mmap...)
+ %std_map_methods_common(mmap);
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
+#endif
+%enddef
+
+// ------------------------------------------------------------------------
+// std::multimap
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::multimap<T>), f(const std::multimap<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::multimap<T> can be passed.
+// -- f(std::multimap<T>&), f(std::multimap<T>*):
+// the parameter may be modified; therefore, only a wrapped std::multimap
+// can be passed.
+// -- std::multimap<T> f(), const std::multimap<T>& f():
+// the map is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::multimap<T>& f(), std::multimap<T>* f():
+// the map is returned by reference; therefore, a wrapped std::multimap
+// is returned
+// -- const std::multimap<T>* f(), f(const std::multimap<T>*):
+// for consistency, they expect and return a plain map pointer.
+// ------------------------------------------------------------------------
+
+
+// exported class
+
+
+namespace std {
+ template<class _Key, class _Tp, class _Compare = std::less< _Key >,
+ class _Alloc = allocator<std::pair< const _Key, _Tp > > >
+ class multimap {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef std::pair< const _Key, _Tp > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::pair< _Key, _Tp >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< _Key, _Tp > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #_Key "," #_Tp " >";
+ }
+ };
+ }
+ }
+
+ %fragment(SWIG_Traits_frag(std::multimap< _Key, _Tp, _Compare, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(std::pair< _Key, _Tp >),
+ fragment="StdMultimapTraits") {
+ namespace swig {
+ template <> struct traits<std::multimap< _Key, _Tp, _Compare, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::multimap<" #_Key "," #_Tp "," #_Compare "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_MULTIMAP, std::multimap< _Key, _Tp, _Compare, _Alloc >);
+
+ multimap(const _Compare& other);
+
+#ifdef %swig_multimap_methods
+ // Add swig/language extra methods
+ %swig_multimap_methods(std::multimap< _Key, _Tp, _Compare, _Alloc >);
+#endif
+
+ %std_multimap_methods(multimap);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_multiset.i b/contrib/tools/swig/Lib/std/std_multiset.i
new file mode 100644
index 00000000000..a1d0db81389
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_multiset.i
@@ -0,0 +1,83 @@
+//
+// std::multiset
+//
+
+%include <std_set.i>
+
+// Multiset
+
+%define %std_multiset_methods(multiset...)
+ %std_set_methods_common(multiset);
+%enddef
+
+
+// ------------------------------------------------------------------------
+// std::multiset
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::multiset<T>), f(const std::multiset<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::multiset<T> can be passed.
+// -- f(std::multiset<T>&), f(std::multiset<T>*):
+// the parameter may be modified; therefore, only a wrapped std::multiset
+// can be passed.
+// -- std::multiset<T> f(), const std::multiset<T>& f():
+// the set is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::multiset<T>& f(), std::multiset<T>* f():
+// the set is returned by reference; therefore, a wrapped std::multiset
+// is returned
+// -- const std::multiset<T>* f(), f(const std::multiset<T>*):
+// for consistency, they expect and return a plain set pointer.
+// ------------------------------------------------------------------------
+
+
+// exported classes
+
+namespace std {
+
+ //multiset
+
+ template <class _Key, class _Compare = std::less< _Key >,
+ class _Alloc = allocator< _Key > >
+ class multiset {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key value_type;
+ typedef _Key key_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+
+ %fragment(SWIG_Traits_frag(std::multiset< _Key, _Compare, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment="StdMultisetTraits") {
+ namespace swig {
+ template <> struct traits<std::multiset< _Key, _Compare, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::multiset<" #_Key "," #_Compare "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_MULTISET, std::multiset< _Key, _Compare, _Alloc >);
+
+ multiset(const _Compare& other);
+
+#ifdef %swig_multiset_methods
+ // Add swig/language extra methods
+ %swig_multiset_methods(std::multiset< _Key, _Compare, _Alloc >);
+#endif
+
+ %std_multiset_methods(multiset);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_pair.i b/contrib/tools/swig/Lib/std/std_pair.i
new file mode 100644
index 00000000000..800155f21ad
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_pair.i
@@ -0,0 +1,163 @@
+%include <std_common.i>
+
+%{
+#include <utility>
+%}
+
+
+namespace std {
+ template <class T, class U > struct pair {
+ typedef T first_type;
+ typedef U second_type;
+
+ %traits_swigtype(T);
+ %traits_swigtype(U);
+
+ %fragment(SWIG_Traits_frag(std::pair< T, U >), "header",
+ fragment=SWIG_Traits_frag(T),
+ fragment=SWIG_Traits_frag(U),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< T, U > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #T "," #U " >";
+ }
+ };
+ }
+ }
+
+#ifndef SWIG_STD_PAIR_ASVAL
+ %typemap_traits_ptr(SWIG_TYPECHECK_PAIR, std::pair< T, U >);
+#else
+ %typemap_traits(SWIG_TYPECHECK_PAIR, std::pair< T, U >);
+#endif
+
+ pair();
+ pair(T first, U second);
+ pair(const pair& other);
+
+ template <class U1, class U2> pair(const pair< U1, U2 > &other);
+
+ T first;
+ U second;
+
+#ifdef %swig_pair_methods
+ // Add swig/language extra methods
+ %swig_pair_methods(std::pair< T, U >)
+#endif
+ };
+
+ // ***
+ // The following specializations should disappear or get
+ // simplified when a 'const SWIGTYPE*&' can be defined
+ // ***
+ template <class T, class U > struct pair< T, U* > {
+ typedef T first_type;
+ typedef U* second_type;
+
+ %traits_swigtype(T);
+ %traits_swigtype(U);
+
+ %fragment(SWIG_Traits_frag(std::pair< T, U* >), "header",
+ fragment=SWIG_Traits_frag(T),
+ fragment=SWIG_Traits_frag(U),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< T, U* > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #T "," #U " * >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_PAIR, std::pair< T, U* >);
+
+ pair();
+ pair(T first, U* second);
+ pair(const pair& other);
+
+ T first;
+ U* second;
+
+#ifdef %swig_pair_methods
+ // Add swig/language extra methods
+ %swig_pair_methods(std::pair< T, U* >)
+#endif
+ };
+
+ template <class T, class U > struct pair< T*, U > {
+ typedef T* first_type;
+ typedef U second_type;
+
+ %traits_swigtype(T);
+ %traits_swigtype(U);
+
+ %fragment(SWIG_Traits_frag(std::pair< T*, U >), "header",
+ fragment=SWIG_Traits_frag(T),
+ fragment=SWIG_Traits_frag(U),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< T*, U > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #T " *," #U " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_PAIR, std::pair< T*, U >);
+
+ pair();
+ pair(T* first, U second);
+ pair(const pair& other);
+
+ T* first;
+ U second;
+
+#ifdef %swig_pair_methods
+ // Add swig/language extra methods
+ %swig_pair_methods(std::pair< T*, U >)
+#endif
+ };
+
+ template <class T, class U > struct pair< T*, U* > {
+ typedef T* first_type;
+ typedef U* second_type;
+
+ %traits_swigtype(T);
+ %traits_swigtype(U);
+
+ %fragment(SWIG_Traits_frag(std::pair< T*, U* >), "header",
+ fragment=SWIG_Traits_frag(T),
+ fragment=SWIG_Traits_frag(U),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< T*, U* > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #T " *," #U " * >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits(SWIG_TYPECHECK_PAIR, std::pair< T*, U* >);
+
+ pair();
+ pair(T* first, U* second);
+ pair(const pair& other);
+
+ T* first;
+ U* second;
+
+#ifdef %swig_pair_methods
+ // Add swig/language extra methods
+ %swig_pair_methods(std::pair< T*, U* >)
+#endif
+ };
+
+}
diff --git a/contrib/tools/swig/Lib/std/std_queue.i b/contrib/tools/swig/Lib/std/std_queue.i
new file mode 100644
index 00000000000..51bb04473d2
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_queue.i
@@ -0,0 +1,129 @@
+/**
+ * @file std_queue.i
+ * @date Sun May 6 01:48:07 2007
+ *
+ * @brief A wrapping of std::queue for Ruby.
+ *
+ *
+ */
+
+%include <std_container.i>
+
+// Queue
+
+%define %std_queue_methods(queue...)
+ queue();
+ queue(const _Sequence& other);
+
+ bool empty() const;
+ size_type size() const;
+ const value_type& front() const;
+ const value_type& back() const;
+ void pop();
+ void push(const value_type& value);
+%enddef
+
+%define %std_queue_methods_val(queue...)
+ %std_queue_methods(queue)
+%enddef
+
+// ------------------------------------------------------------------------
+// std::queue
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::queue<T>), f(const std::queue<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::queue<T> can be passed.
+// -- f(std::queue<T>&), f(std::queue<T>*):
+// the parameter may be modified; therefore, only a wrapped std::queue
+// can be passed.
+// -- std::queue<T> f(), const std::queue<T>& f():
+// the queue is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::queue<T>& f(), std::queue<T>* f():
+// the queue is returned by reference; therefore, a wrapped std::queue
+// is returned
+// -- const std::queue<T>* f(), f(const std::queue<T>*):
+// for consistency, they expect and return a plain queue pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <queue>
+%}
+
+// exported classes
+
+namespace std {
+
+ template<class _Tp, class _Sequence = std::deque< _Tp > >
+ class queue {
+ public:
+ typedef size_t size_type;
+ typedef _Tp value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Sequence container_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::queue< _Tp, _Sequence >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdQueueTraits") {
+ namespace swig {
+ template <> struct traits<std::queue< _Tp, _Sequence > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::queue<" #_Tp "," #_Sequence " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_QUEUE, std::queue< _Tp, _Sequence >);
+
+#ifdef %swig_queue_methods
+ // Add swig/language extra methods
+ %swig_queue_methods(std::queue< _Tp, _Sequence >);
+#endif
+
+ %std_queue_methods(queue);
+ };
+
+ template<class _Tp, class _Sequence >
+ class queue< _Tp*, _Sequence > {
+ public:
+ typedef size_t size_type;
+ typedef _Tp value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Sequence container_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::queue< _Tp*, _Sequence >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdQueueTraits") {
+ namespace swig {
+ template <> struct traits<std::queue< _Tp*, _Sequence > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::queue<" #_Tp "," #_Sequence " * >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_QUEUE, std::queue< _Tp*, _Sequence >);
+
+#ifdef %swig_queue_methods_val
+ // Add swig/language extra methods
+ %swig_queue_methods_val(std::queue< _Tp*, _Sequence >);
+#endif
+
+ %std_queue_methods_val(queue);
+ };
+
+}
+
diff --git a/contrib/tools/swig/Lib/std/std_set.i b/contrib/tools/swig/Lib/std/std_set.i
new file mode 100644
index 00000000000..0e05aca40c0
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_set.i
@@ -0,0 +1,122 @@
+//
+// std::set
+//
+
+%include <std_container.i>
+%include <std_pair.i>
+
+// Set
+%define %std_set_methods_common(set...)
+ set();
+ set(const set& other);
+
+ bool empty() const;
+ size_type size() const;
+ void clear();
+
+ void swap(set& v);
+
+
+ size_type erase(const key_type& x);
+ size_type count(const key_type& x) const;
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ class iterator;
+ class reverse_iterator;
+
+ iterator begin();
+ iterator end();
+ reverse_iterator rbegin();
+ reverse_iterator rend();
+
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ void erase(iterator pos) { $self->erase(pos); }
+ void erase(iterator first, iterator last) { $self->erase(first, last); }
+}
+
+ iterator find(const key_type& x);
+ iterator lower_bound(const key_type& x);
+ iterator upper_bound(const key_type& x);
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+#endif
+%enddef
+
+%define %std_set_methods(set...)
+ %std_set_methods_common(set);
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ std::pair<iterator,bool> insert(const value_type& __x);
+#endif
+%enddef
+
+// ------------------------------------------------------------------------
+// std::set
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::set<T>), f(const std::set<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::set<T> can be passed.
+// -- f(std::set<T>&), f(std::set<T>*):
+// the parameter may be modified; therefore, only a wrapped std::set
+// can be passed.
+// -- std::set<T> f(), const std::set<T>& f():
+// the set is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::set<T>& f(), std::set<T>* f():
+// the set is returned by reference; therefore, a wrapped std::set
+// is returned
+// -- const std::set<T>* f(), f(const std::set<T>*):
+// for consistency, they expect and return a plain set pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <set>
+%}
+
+// exported classes
+
+namespace std {
+
+ template <class _Key, class _Compare = std::less< _Key >,
+ class _Alloc = allocator< _Key > >
+ class set {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key value_type;
+ typedef _Key key_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+
+ %fragment(SWIG_Traits_frag(std::set< _Key, _Compare, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment="StdSetTraits") {
+ namespace swig {
+ template <> struct traits<std::set< _Key, _Compare, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::set<" #_Key "," #_Compare "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_SET, std::set< _Key, _Compare, _Alloc >);
+
+ set(const _Compare& other);
+
+#ifdef %swig_set_methods
+ // Add swig/language extra methods
+ %swig_set_methods(std::set< _Key, _Compare, _Alloc >);
+#endif
+
+ %std_set_methods(set);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_sstream.i b/contrib/tools/swig/Lib/std/std_sstream.i
new file mode 100644
index 00000000000..12bccef2e44
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_sstream.i
@@ -0,0 +1,195 @@
+/*
+ For wchar support, you need to include the wchar.i file
+ before this file, ie:
+
+ %include <wchar.i>
+ %include <std_sstream.i>
+
+ or equivalently, just include
+
+ %include <std_wsstream.i>
+*/
+
+%include <std_alloc.i>
+%include <std_basic_string.i>
+%include <std_string.i>
+%include <std_ios.i>
+#if defined(SWIG_WCHAR)
+%include <std_wstring.i>
+#endif
+%include <std_streambuf.i>
+%include <std_iostream.i>
+
+%{
+#include <sstream>
+%}
+
+
+namespace std
+{
+ template<typename _CharT, typename _Traits = char_traits<_CharT>,
+ typename _Alloc = allocator<_CharT> >
+ class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+// 251. basic_stringbuf missing allocator_type
+ typedef _Alloc allocator_type;
+ typedef typename traits_type::int_type int_type;
+ typedef typename traits_type::pos_type pos_type;
+ typedef typename traits_type::off_type off_type;
+
+ public:
+ // Constructors:
+ explicit
+ basic_stringbuf(ios_base::openmode __mode = ios_base::in | ios_base::out);
+
+ explicit
+ basic_stringbuf(const basic_string<_CharT, _Traits, _Alloc>& __str,
+ ios_base::openmode __mode = ios_base::in | ios_base::out);
+
+ // Get and set:
+ basic_string<_CharT, _Traits, _Alloc>
+ str() const;
+
+ void
+ str(const basic_string<_CharT, _Traits, _Alloc>& __s);
+
+ };
+
+
+ // 27.7.2 Template class basic_istringstream
+ template<typename _CharT, typename _Traits = char_traits<_CharT>,
+ typename _Alloc = allocator<_CharT> >
+ class basic_istringstream : public basic_istream<_CharT, _Traits>
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+// 251. basic_stringbuf missing allocator_type
+ typedef _Alloc allocator_type;
+ typedef typename traits_type::int_type int_type;
+ typedef typename traits_type::pos_type pos_type;
+ typedef typename traits_type::off_type off_type;
+
+
+ public:
+ // Constructors:
+ explicit
+ basic_istringstream(ios_base::openmode __mode = ios_base::in);
+
+ explicit
+ basic_istringstream(const basic_string<_CharT, _Traits, _Alloc>& __str,
+ ios_base::openmode __mode = ios_base::in);
+
+ ~basic_istringstream();
+
+ // Members:
+ basic_stringbuf<_CharT, _Traits, _Alloc>*
+ rdbuf() const;
+
+ basic_string<_CharT, _Traits, _Alloc>
+ str() const;
+
+ void
+ str(const basic_string<_CharT, _Traits, _Alloc>& __s);
+ };
+
+
+ // 27.7.3 Template class basic_ostringstream
+ template<typename _CharT, typename _Traits = char_traits<_CharT>,
+ typename _Alloc = allocator<_CharT> >
+ class basic_ostringstream : public basic_ostream<_CharT, _Traits>
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+// 251. basic_stringbuf missing allocator_type
+ typedef _Alloc allocator_type;
+ typedef typename traits_type::int_type int_type;
+ typedef typename traits_type::pos_type pos_type;
+ typedef typename traits_type::off_type off_type;
+
+
+ public:
+ // Constructors/destructor:
+ explicit
+ basic_ostringstream(ios_base::openmode __mode = ios_base::out);
+
+ explicit
+ basic_ostringstream(const basic_string<_CharT, _Traits, _Alloc>& __str,
+ ios_base::openmode __mode = ios_base::out);
+
+ ~basic_ostringstream();
+
+ // Members:
+ basic_stringbuf<_CharT, _Traits, _Alloc>*
+ rdbuf() const;
+
+ basic_string<_CharT, _Traits, _Alloc>
+ str() const;
+
+#if 0
+ void
+ str(const basic_string<_CharT, _Traits, _Alloc>& __s);
+#endif
+ };
+
+
+ // 27.7.4 Template class basic_stringstream
+ template<typename _CharT, typename _Traits = char_traits<_CharT>,
+ typename _Alloc = allocator<_CharT> >
+ class basic_stringstream : public basic_iostream<_CharT, _Traits>
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+// 251. basic_stringbuf missing allocator_type
+ typedef _Alloc allocator_type;
+ typedef typename traits_type::int_type int_type;
+ typedef typename traits_type::pos_type pos_type;
+ typedef typename traits_type::off_type off_type;
+
+ public:
+ // Constructors/destructors
+ explicit
+ basic_stringstream(ios_base::openmode __m = ios_base::out | ios_base::in);
+
+ explicit
+ basic_stringstream(const basic_string<_CharT, _Traits, _Alloc>& __str,
+ ios_base::openmode __m = ios_base::out | ios_base::in);
+
+ ~basic_stringstream();
+
+ // Members:
+ basic_stringbuf<_CharT, _Traits, _Alloc>*
+ rdbuf() const;
+
+ basic_string<_CharT, _Traits, _Alloc>
+ str() const;
+
+ void
+ str(const basic_string<_CharT, _Traits, _Alloc>& __s);
+ };
+
+
+} // namespace std
+
+
+namespace std {
+ %template(istringstream) basic_istringstream<char>;
+ %template(ostringstream) basic_ostringstream<char>;
+ %template(stringstream) basic_stringstream<char>;
+
+
+#if defined(SWIG_WCHAR)
+ %template(wistringstream) basic_istringstream<wchar_t>;
+ %template(wostringstream) basic_ostringstream<wchar_t>;
+ %template(wstringstream) basic_stringstream<wchar_t>;
+#endif
+}
diff --git a/contrib/tools/swig/Lib/std/std_stack.i b/contrib/tools/swig/Lib/std/std_stack.i
new file mode 100644
index 00000000000..ff714d09991
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_stack.i
@@ -0,0 +1,128 @@
+/**
+ * @file std_stack.i
+ * @date Sun May 6 01:48:07 2007
+ *
+ * @brief A wrapping of std::stack for Ruby.
+ *
+ *
+ */
+
+%include <std_container.i>
+
+// Stack
+
+%define %std_stack_methods(stack...)
+ stack();
+ stack(const _Sequence& other);
+
+ bool empty() const;
+ size_type size() const;
+ const value_type& top() const;
+ void pop();
+ void push(const value_type& value);
+%enddef
+
+%define %std_stack_methods_val(stack...)
+ %std_stack_methods(stack)
+%enddef
+
+// ------------------------------------------------------------------------
+// std::stack
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::stack<T>), f(const std::stack<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::stack<T> can be passed.
+// -- f(std::stack<T>&), f(std::stack<T>*):
+// the parameter may be modified; therefore, only a wrapped std::stack
+// can be passed.
+// -- std::stack<T> f(), const std::stack<T>& f():
+// the stack is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::stack<T>& f(), std::stack<T>* f():
+// the stack is returned by reference; therefore, a wrapped std::stack
+// is returned
+// -- const std::stack<T>* f(), f(const std::stack<T>*):
+// for consistency, they expect and return a plain stack pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <stack>
+%}
+
+// exported classes
+
+namespace std {
+
+ template<class _Tp, class _Sequence = std::deque< _Tp > >
+ class stack {
+ public:
+ typedef size_t size_type;
+ typedef _Tp value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Sequence container_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::stack< _Tp, _Sequence >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdStackTraits") {
+ namespace swig {
+ template <> struct traits<std::stack< _Tp, _Sequence > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::stack<" #_Tp "," #_Sequence " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_STACK, std::stack< _Tp, _Sequence >);
+
+#ifdef %swig_stack_methods
+ // Add swig/language extra methods
+ %swig_stack_methods(std::stack< _Tp, _Sequence >);
+#endif
+
+ %std_stack_methods(stack);
+ };
+
+ template<class _Tp, class _Sequence >
+ class stack< _Tp*, _Sequence > {
+ public:
+ typedef size_t size_type;
+ typedef _Sequence::value_type value_type;
+ typedef value_type reference;
+ typedef value_type const_reference;
+ typedef _Sequence container_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::stack< _Tp*, _Sequence >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdStackTraits") {
+ namespace swig {
+ template <> struct traits<std::stack< _Tp*, _Sequence > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::stack<" #_Tp "," #_Sequence " * >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_STACK, std::stack< _Tp*, _Sequence >);
+
+#ifdef %swig_stack_methods_val
+ // Add swig/language extra methods
+ %swig_stack_methods_val(std::stack< _Tp*, _Sequence >);
+#endif
+
+ %std_stack_methods_val(stack);
+ };
+
+}
+
diff --git a/contrib/tools/swig/Lib/std/std_streambuf.i b/contrib/tools/swig/Lib/std/std_streambuf.i
new file mode 100644
index 00000000000..e17249135c3
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_streambuf.i
@@ -0,0 +1,94 @@
+%include <std_ios.i>
+%{
+#ifndef SWIG_STD_NOMODERN_STL
+#include <streambuf>
+#else
+#include <streambuf.h>
+#endif
+%}
+
+namespace std {
+
+ template<typename _CharT, typename _Traits = char_traits<_CharT> >
+ class basic_streambuf
+ {
+ public:
+ // Types:
+ typedef _CharT char_type;
+ typedef _Traits traits_type;
+ typedef typename traits_type::int_type int_type;
+ typedef typename traits_type::pos_type pos_type;
+ typedef typename traits_type::off_type off_type;
+
+ public:
+ virtual
+ ~basic_streambuf();
+
+ // Locales:
+ locale
+ pubimbue(const locale &__loc);
+
+ locale
+ getloc() const;
+
+ // Buffer and positioning:
+ basic_streambuf<_CharT, _Traits>*
+ pubsetbuf(char_type* __s, streamsize __n);
+
+ pos_type
+ pubseekoff(off_type __off, ios_base::seekdir __way,
+ ios_base::openmode __mode = std::ios_base::in | std::ios_base::out);
+
+ pos_type
+ pubseekpos(pos_type __sp,
+ ios_base::openmode __mode = std::ios_base::in | std::ios_base::out);
+
+ int
+ pubsync() ;
+
+ // Get and put areas:
+ // Get area:
+ streamsize
+ in_avail();
+
+ int_type
+ snextc();
+
+ int_type
+ sbumpc();
+
+ int_type
+ sgetc();
+
+ streamsize
+ sgetn(char_type* __s, streamsize __n);
+
+ // Putback:
+ int_type
+ sputbackc(char_type __c);
+
+ int_type
+ sungetc();
+
+ // Put area:
+ int_type
+ sputc(char_type __c);
+
+ streamsize
+ sputn(const char_type* __s, streamsize __n);
+
+ protected:
+ basic_streambuf();
+
+ private:
+ basic_streambuf(const basic_streambuf& other);
+
+ };
+}
+
+namespace std {
+ %template(streambuf) basic_streambuf<char>;
+#if defined(SWIG_WCHAR)
+ %template(wstreambuf) basic_streambuf<wchar_t>;
+#endif
+}
diff --git a/contrib/tools/swig/Lib/std/std_string.i b/contrib/tools/swig/Lib/std/std_string.i
new file mode 100644
index 00000000000..35fcdd16c6b
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_string.i
@@ -0,0 +1,13 @@
+%include <std/std_basic_string.i>
+
+/* plain strings */
+
+namespace std
+{
+ %std_comp_methods(basic_string<char>);
+ %naturalvar string;
+ typedef basic_string<char> string;
+}
+
+
+%template(string) std::basic_string<char>;
diff --git a/contrib/tools/swig/Lib/std/std_unordered_map.i b/contrib/tools/swig/Lib/std/std_unordered_map.i
new file mode 100644
index 00000000000..1fd1eb980cb
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_unordered_map.i
@@ -0,0 +1,122 @@
+//
+// std::unordered_map
+//
+%include <std_pair.i>
+%include <std_container.i>
+
+%define %std_unordered_map_methods_common(unordered_map...)
+ %std_container_methods_without_reverse_iterators(unordered_map);
+
+ size_type erase(const key_type& x);
+ size_type count(const key_type& x) const;
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ void erase(iterator position) { $self->erase(position); }
+ void erase(iterator first, iterator last) { $self->erase(first, last); }
+}
+
+ iterator find(const key_type& x);
+#endif
+%enddef
+
+%define %std_unordered_map_methods(unordered_map...)
+ %std_unordered_map_methods_common(unordered_map);
+
+ #ifdef SWIG_EXPORT_ITERATOR_METHODS
+// iterator insert(const value_type& x);
+ #endif
+%enddef
+
+
+// ------------------------------------------------------------------------
+// std::unordered_map
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::unordered_map<T>), f(const std::unordered_map<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::unordered_map<T> can be passed.
+// -- f(std::unordered_map<T>&), f(std::unordered_map<T>*):
+// the parameter may be modified; therefore, only a wrapped std::unordered_map
+// can be passed.
+// -- std::unordered_map<T> f(), const std::unordered_map<T>& f():
+// the unordered_map is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::unordered_map<T>& f(), std::unordered_map<T>* f():
+// the unordered_map is returned by reference; therefore, a wrapped std::unordered_map
+// is returned
+// -- const std::unordered_map<T>* f(), f(const std::unordered_map<T>*):
+// for consistency, they expect and return a plain unordered_map pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <unordered_map>
+%}
+%fragment("<algorithm>");
+%fragment("<stdexcept>");
+
+// exported class
+
+namespace std {
+
+ template<class _Key, class _Tp, class _Hash = std::hash< _Key >, class _Pred = std::equal_to< _Key >,
+ class _Alloc = allocator<std::pair< const _Key, _Tp > > >
+ class unordered_map {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef std::pair< const _Key, _Tp > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Hash hasher;
+ typedef _Compare key_equal;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::pair< _Key, _Tp >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdPairTraits") {
+ namespace swig {
+ template <> struct traits<std::pair< _Key, _Tp > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::pair<" #_Key "," #_Tp " >";
+ }
+ };
+ }
+ }
+
+ %fragment(SWIG_Traits_frag(std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(std::pair< _Key, _Tp >),
+ fragment="StdUnorderedMapTraits") {
+ namespace swig {
+ template <> struct traits<std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::unordered_map<" #_Key "," #_Tp "," #_Hash "," #_Pred "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_MAP, std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc >);
+
+#ifdef %swig_unordered_map_methods
+ // Add swig/language extra methods
+ %swig_unordered_map_methods(std::unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc >);
+#endif
+
+ %std_unordered_map_methods(unordered_map);
+ };
+
+}
diff --git a/contrib/tools/swig/Lib/std/std_unordered_multimap.i b/contrib/tools/swig/Lib/std/std_unordered_multimap.i
new file mode 100644
index 00000000000..4be6aa492d0
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_unordered_multimap.i
@@ -0,0 +1,85 @@
+//
+// std::unordered_multimap
+//
+
+%include <std_unordered_map.i>
+
+%define %std_unordered_multimap_methods(mmap...)
+ %std_unordered_map_methods_common(mmap);
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
+#endif
+%enddef
+
+// ------------------------------------------------------------------------
+// std::unordered_multimap
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::unordered_multimap<T>), f(const std::unordered_multimap<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::unordered_multimap<T> can be passed.
+// -- f(std::unordered_multimap<T>&), f(std::unordered_multimap<T>*):
+// the parameter may be modified; therefore, only a wrapped std::unordered_multimap
+// can be passed.
+// -- std::unordered_multimap<T> f(), const std::unordered_multimap<T>& f():
+// the map is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::unordered_multimap<T>& f(), std::unordered_multimap<T>* f():
+// the map is returned by reference; therefore, a wrapped std::unordered_multimap
+// is returned
+// -- const std::unordered_multimap<T>* f(), f(const std::unordered_multimap<T>*):
+// for consistency, they expect and return a plain map pointer.
+// ------------------------------------------------------------------------
+
+
+// exported class
+
+
+namespace std {
+ template<class _Key, class _Tp, class _Hash = std::hash< _Key >, class _Pred = std::equal_to< _Key >,
+ class _Alloc = allocator<std::pair< const _Key, _Tp > > >
+ class unordered_multimap {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef std::pair< const _Key, _Tp > value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Hash hasher;
+ typedef _Compare key_equal;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(std::pair< _Key, _Tp >),
+ fragment="StdUnorderedMultimapTraits") {
+ namespace swig {
+ template <> struct traits<std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::unordered_multimap<" #_Key "," #_Tp "," #_Hash "," #_Pred "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_MULTIMAP, std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc >);
+
+#ifdef %swig_unordered_multimap_methods
+ // Add swig/language extra methods
+ %swig_unordered_multimap_methods(std::unordered_multimap< _Key, _Tp, _Hash, _Pred, _Alloc >);
+#endif
+
+ %std_unordered_multimap_methods(unordered_multimap);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_unordered_multiset.i b/contrib/tools/swig/Lib/std/std_unordered_multiset.i
new file mode 100644
index 00000000000..2910fb6ff67
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_unordered_multiset.i
@@ -0,0 +1,85 @@
+//
+// std::unordered_multiset
+//
+
+%include <std_unordered_set.i>
+
+// Unordered Multiset
+
+%define %std_unordered_multiset_methods(unordered_multiset...)
+ %std_unordered_set_methods_common(unordered_multiset);
+%enddef
+
+
+// ------------------------------------------------------------------------
+// std::unordered_multiset
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::unordered_multiset<Key>), f(const std::unordered_multiset<Key>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::unordered_multiset<Key> can be passed.
+// -- f(std::unordered_multiset<Key>&), f(std::unordered_multiset<Key>*):
+// the parameter may be modified; therefore, only a wrapped std::unordered_multiset
+// can be passed.
+// -- std::unordered_multiset<Key> f(), const std::unordered_multiset<Key>& f():
+// the set is returned by copy; therefore, a sequence of Key:s
+// is returned which is most easily used in other functions
+// -- std::unordered_multiset<Key>& f(), std::unordered_multiset<Key>* f():
+// the set is returned by reference; therefore, a wrapped std::unordered_multiset
+// is returned
+// -- const std::unordered_multiset<Key>* f(), f(const std::unordered_multiset<Key>*):
+// for consistency, they expect and return a plain set pointer.
+// ------------------------------------------------------------------------
+
+
+// exported classes
+
+namespace std {
+
+ //unordered_multiset
+
+ template <class _Key,
+ class _Hash = std::hash< _Key >,
+ class _Compare = std::equal_to< _Key >,
+ class _Alloc = allocator< _Key > >
+ class unordered_multiset {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key value_type;
+ typedef _Key key_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Hash hasher;
+ typedef _Compare key_equal;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+
+ %fragment(SWIG_Traits_frag(std::unordered_multiset< _Key, _Hash, _Compare, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment="StdUnorderedMultisetTraits") {
+ namespace swig {
+ template <> struct traits<std::unordered_multiset< _Key, _Hash, _Compare, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::unordered_multiset<" #_Key "," #_Hash "," #_Compare "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_MULTISET, std::unordered_multiset< _Key, _Hash, _Compare, _Alloc >);
+
+#ifdef %swig_unordered_multiset_methods
+ // Add swig/language extra methods
+ %swig_unordered_multiset_methods(std::unordered_multiset< _Key, _Hash, _Compare, _Alloc >);
+#endif
+
+ %std_unordered_multiset_methods(unordered_multiset);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_unordered_set.i b/contrib/tools/swig/Lib/std/std_unordered_set.i
new file mode 100644
index 00000000000..91e807423b5
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_unordered_set.i
@@ -0,0 +1,119 @@
+//
+// std::unordered_set
+//
+
+%include <std_container.i>
+%include <std_pair.i>
+
+// Unordered Set
+%define %std_unordered_set_methods_common(unordered_set...)
+ unordered_set();
+ unordered_set(const unordered_set& other);
+
+ bool empty() const;
+ size_type size() const;
+ void clear();
+
+ void swap(unordered_set& v);
+
+
+ size_type erase(const key_type& x);
+ size_type count(const key_type& x) const;
+
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ class iterator;
+
+ iterator begin();
+ iterator end();
+
+%extend {
+ // %extend wrapper used for differing definitions of these methods introduced in C++11
+ void erase(iterator pos) { $self->erase(pos); }
+ void erase(iterator first, iterator last) { $self->erase(first, last); }
+}
+
+ iterator find(const key_type& x);
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+#endif
+%enddef
+
+%define %std_unordered_set_methods(unordered_set...)
+ %std_unordered_set_methods_common(unordered_set);
+#ifdef SWIG_EXPORT_ITERATOR_METHODS
+ std::pair<iterator,bool> insert(const value_type& __x);
+#endif
+%enddef
+
+// ------------------------------------------------------------------------
+// std::unordered_set
+//
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::unordered_set<Key>), f(const std::unordered_set<Key>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::unordered_set<Key> can be passed.
+// -- f(std::unordered_set<Key>&), f(std::unordered_set<Key>*):
+// the parameter may be modified; therefore, only a wrapped std::unordered_set
+// can be passed.
+// -- std::unordered_set<Key> f(), const std::unordered_set<Key>& f():
+// the unordered_set is returned by copy; therefore, a sequence of Key:s
+// is returned which is most easily used in other functions
+// -- std::unordered_set<Key>& f(), std::unordered_set<Key>* f():
+// the unordered_set is returned by reference; therefore, a wrapped std::unordered_set
+// is returned
+// -- const std::unordered_set<Key>* f(), f(const std::unordered_set<Key>*):
+// for consistency, they expect and return a plain unordered_set pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <unordered_set>
+%}
+
+// exported classes
+
+namespace std {
+
+ template <class _Key,
+ class _Hash = std::hash< _Key >,
+ class _Compare = std::equal_to< _Key >,
+ class _Alloc = allocator< _Key > >
+ class unordered_set {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Key value_type;
+ typedef _Key key_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Hash hasher;
+ typedef _Compare key_equal;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Key);
+
+ %fragment(SWIG_Traits_frag(std::unordered_set< _Key, _Hash, _Compare, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Key),
+ fragment="StdUnorderedSetTraits") {
+ namespace swig {
+ template <> struct traits<std::unordered_set< _Key, _Hash, _Compare, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::unordered_set<" #_Key "," #_Hash "," #_Compare "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_SET, std::unordered_set< _Key, _Hash, _Compare, _Alloc >);
+
+#ifdef %swig_unordered_set_methods
+ // Add swig/language extra methods
+ %swig_unordered_set_methods(std::unordered_set< _Key, _Hash, _Compare, _Alloc >);
+#endif
+
+ %std_unordered_set_methods(unordered_set);
+ };
+}
diff --git a/contrib/tools/swig/Lib/std/std_vector.i b/contrib/tools/swig/Lib/std/std_vector.i
new file mode 100644
index 00000000000..b35f03bea20
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_vector.i
@@ -0,0 +1,225 @@
+//
+// std::vector
+//
+
+%include <std_container.i>
+
+// Vector
+
+%define %std_vector_methods(vector...)
+ %std_sequence_methods(vector)
+
+ void reserve(size_type n);
+ size_type capacity() const;
+%enddef
+
+
+%define %std_vector_methods_val(vector...)
+ %std_sequence_methods_val(vector)
+
+ void reserve(size_type n);
+ size_type capacity() const;
+%enddef
+
+
+// ------------------------------------------------------------------------
+// std::vector
+//
+// The aim of all that follows would be to integrate std::vector with
+// as much as possible, namely, to allow the user to pass and
+// be returned tuples or lists.
+// const declarations are used to guess the intent of the function being
+// exported; therefore, the following rationale is applied:
+//
+// -- f(std::vector<T>), f(const std::vector<T>&):
+// the parameter being read-only, either a sequence or a
+// previously wrapped std::vector<T> can be passed.
+// -- f(std::vector<T>&), f(std::vector<T>*):
+// the parameter may be modified; therefore, only a wrapped std::vector
+// can be passed.
+// -- std::vector<T> f(), const std::vector<T>& f():
+// the vector is returned by copy; therefore, a sequence of T:s
+// is returned which is most easily used in other functions
+// -- std::vector<T>& f(), std::vector<T>* f():
+// the vector is returned by reference; therefore, a wrapped std::vector
+// is returned
+// -- const std::vector<T>* f(), f(const std::vector<T>*):
+// for consistency, they expect and return a plain vector pointer.
+// ------------------------------------------------------------------------
+
+%{
+#include <vector>
+%}
+
+// exported classes
+
+
+namespace std {
+
+ template<class _Tp, class _Alloc = allocator< _Tp > >
+ class vector {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+ %traits_enum(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::vector< _Tp, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdVectorTraits") {
+ namespace swig {
+ template <> struct traits<std::vector< _Tp, _Alloc > > {
+ typedef pointer_category category;
+ static const char* type_name() {
+ return "std::vector<" #_Tp "," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector< _Tp, _Alloc >);
+
+#ifdef %swig_vector_methods
+ // Add swig/language extra methods
+ %swig_vector_methods(std::vector< _Tp, _Alloc >);
+#endif
+
+ %std_vector_methods(vector);
+ };
+
+ // ***
+ // This specialization should disappear or get simplified when
+ // a 'const SWIGTYPE*&' can be defined
+ // ***
+ template<class _Tp, class _Alloc >
+ class vector< _Tp*, _Alloc > {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp* value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::vector< _Tp*, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdVectorTraits") {
+ namespace swig {
+ template <> struct traits<std::vector< _Tp*, _Alloc > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::vector<" #_Tp " *," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector< _Tp*, _Alloc >);
+
+#ifdef %swig_vector_methods_val
+ // Add swig/language extra methods
+ %swig_vector_methods_val(std::vector< _Tp*, _Alloc >);
+#endif
+
+ %std_vector_methods_val(vector);
+ };
+
+ // ***
+ // const pointer specialization
+ // ***
+ template<class _Tp, class _Alloc >
+ class vector< _Tp const *, _Alloc > {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp const * value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(_Tp);
+
+ %fragment(SWIG_Traits_frag(std::vector< _Tp const*, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(_Tp),
+ fragment="StdVectorTraits") {
+ namespace swig {
+ template <> struct traits<std::vector< _Tp const*, _Alloc > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::vector<" #_Tp " const*," #_Alloc " >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector< _Tp const*, _Alloc >);
+
+#ifdef %swig_vector_methods_val
+ // Add swig/language extra methods
+ %swig_vector_methods_val(std::vector< _Tp const*, _Alloc >);
+#endif
+
+ %std_vector_methods_val(vector);
+ };
+
+ // ***
+ // bool specialization
+ // ***
+
+ template<class _Alloc >
+ class vector<bool,_Alloc > {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef bool value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef bool const_reference;
+ typedef _Alloc allocator_type;
+
+ %traits_swigtype(bool);
+
+ %fragment(SWIG_Traits_frag(std::vector<bool, _Alloc >), "header",
+ fragment=SWIG_Traits_frag(bool),
+ fragment="StdVectorTraits") {
+ namespace swig {
+ template <> struct traits<std::vector<bool, _Alloc > > {
+ typedef value_category category;
+ static const char* type_name() {
+ return "std::vector<bool, _Alloc >";
+ }
+ };
+ }
+ }
+
+ %typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector<bool, _Alloc >);
+
+
+#ifdef %swig_vector_methods_val
+ // Add swig/language extra methods
+ %swig_vector_methods_val(std::vector<bool, _Alloc >);
+#endif
+
+ %std_vector_methods_val(vector);
+
+#if defined(SWIG_STD_MODERN_STL) && !defined(SWIG_STD_NOMODERN_STL)
+ void flip();
+#endif
+
+ };
+
+}
diff --git a/contrib/tools/swig/Lib/std/std_vectora.i b/contrib/tools/swig/Lib/std/std_vectora.i
new file mode 100644
index 00000000000..0e83dc9b1e9
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_vectora.i
@@ -0,0 +1,7 @@
+//
+// We keep this file only for backward compatibility, since std_vector.i
+// now uses the std::allocator parameter.
+//
+
+%include <std_vector.i>
+
diff --git a/contrib/tools/swig/Lib/std/std_wios.i b/contrib/tools/swig/Lib/std/std_wios.i
new file mode 100644
index 00000000000..e9c5dd4d6e9
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_wios.i
@@ -0,0 +1,7 @@
+/*
+ Provide 'std_ios.i' with wchar support.
+*/
+
+%include <wchar.i>
+%include <std_ios.i>
+
diff --git a/contrib/tools/swig/Lib/std/std_wiostream.i b/contrib/tools/swig/Lib/std/std_wiostream.i
new file mode 100644
index 00000000000..b9bef903750
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_wiostream.i
@@ -0,0 +1,7 @@
+/*
+ Provide 'std_iostream.i' with wchar support.
+*/
+
+%include <wchar.i>
+%include <std_iostream.i>
+
diff --git a/contrib/tools/swig/Lib/std/std_wsstream.i b/contrib/tools/swig/Lib/std/std_wsstream.i
new file mode 100644
index 00000000000..4c663fc45e1
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_wsstream.i
@@ -0,0 +1,7 @@
+/*
+ Provide 'std_sstream.i' with wchar support.
+*/
+
+%include <wchar.i>
+%include <std_sstream.i>
+
diff --git a/contrib/tools/swig/Lib/std/std_wstreambuf.i b/contrib/tools/swig/Lib/std/std_wstreambuf.i
new file mode 100644
index 00000000000..86ac6af6d93
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_wstreambuf.i
@@ -0,0 +1,7 @@
+/*
+ Provide 'std_streambuf.i' with wchar support.
+*/
+
+%include <wchar.i>
+%include <std_streambuf.i>
+
diff --git a/contrib/tools/swig/Lib/std/std_wstring.i b/contrib/tools/swig/Lib/std/std_wstring.i
new file mode 100644
index 00000000000..e54d21200e4
--- /dev/null
+++ b/contrib/tools/swig/Lib/std/std_wstring.i
@@ -0,0 +1,14 @@
+%include <wchar.i>
+%include <std/std_basic_string.i>
+
+/* wide strings */
+
+namespace std
+{
+ %std_comp_methods(basic_string<wchar_t>);
+ %naturalvar wstring;
+ typedef basic_string<wchar_t> wstring;
+}
+
+%template(wstring) std::basic_string<wchar_t>;
+
diff --git a/contrib/tools/swig/Lib/std_except.i b/contrib/tools/swig/Lib/std_except.i
new file mode 100644
index 00000000000..0f8b23e703d
--- /dev/null
+++ b/contrib/tools/swig/Lib/std_except.i
@@ -0,0 +1,57 @@
+/* -----------------------------------------------------------------------------
+ * std_except.i
+ *
+ * SWIG library file with typemaps to handle and throw STD exceptions in a
+ * language and STL independent way, i.e., the target language doesn't
+ * require to support STL but only the 'exception.i' mechanism.
+ *
+ * These typemaps are used when methods are declared with an STD
+ * exception specification, such as
+ *
+ * size_t at() const throw (std::out_of_range);
+ *
+ * The typemaps here are based on the language independent
+ * 'exception.i' library. If that is working in your target language,
+ * this file will work.
+ *
+ * If the target language doesn't implement a robust 'exception.i'
+ * mechanism, or you prefer other ways to map the STD exceptions, write
+ * a new std_except.i file in the target library directory.
+ * ----------------------------------------------------------------------------- */
+
+#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGGUILE) || defined(SWIGUTL) || defined(SWIGD) || defined(SWIGOCAML)
+#error "This version of std_except.i should not be used"
+#endif
+
+%{
+#include <typeinfo>
+#include <stdexcept>
+%}
+
+%include <exception.i>
+
+
+%define %std_exception_map(Exception, Code)
+ %typemap(throws,noblock=1) Exception {
+ SWIG_exception(Code, $1.what());
+ }
+ %ignore Exception;
+ struct Exception {
+ };
+%enddef
+
+namespace std {
+ %std_exception_map(bad_cast, SWIG_TypeError);
+ %std_exception_map(bad_exception, SWIG_SystemError);
+ %std_exception_map(domain_error, SWIG_ValueError);
+ %std_exception_map(exception, SWIG_SystemError);
+ %std_exception_map(invalid_argument, SWIG_ValueError);
+ %std_exception_map(length_error, SWIG_IndexError);
+ %std_exception_map(logic_error, SWIG_RuntimeError);
+ %std_exception_map(out_of_range, SWIG_IndexError);
+ %std_exception_map(overflow_error, SWIG_OverflowError);
+ %std_exception_map(range_error, SWIG_OverflowError);
+ %std_exception_map(runtime_error, SWIG_RuntimeError);
+ %std_exception_map(underflow_error, SWIG_OverflowError);
+}
+
diff --git a/contrib/tools/swig/Lib/stdint.i b/contrib/tools/swig/Lib/stdint.i
new file mode 100644
index 00000000000..14fe6195e23
--- /dev/null
+++ b/contrib/tools/swig/Lib/stdint.i
@@ -0,0 +1,106 @@
+/* -----------------------------------------------------------------------------
+ * stdint.i
+ *
+ * SWIG library file for ISO C99 types: 7.18 Integer types <stdint.h>
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <stdint.h> // Use the C99 official header
+%}
+
+%include <swigarch.i>
+
+/* Exact integral types. */
+
+/* Signed. */
+
+typedef signed char int8_t;
+typedef short int int16_t;
+typedef int int32_t;
+#if defined(SWIGWORDSIZE64)
+typedef long int int64_t;
+#else
+typedef long long int int64_t;
+#endif
+
+/* Unsigned. */
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+#if defined(SWIGWORDSIZE64)
+typedef unsigned long int uint64_t;
+#else
+typedef unsigned long long int uint64_t;
+#endif
+
+
+/* Small types. */
+
+/* Signed. */
+typedef signed char int_least8_t;
+typedef short int int_least16_t;
+typedef int int_least32_t;
+#if defined(SWIGWORDSIZE64)
+typedef long int int_least64_t;
+#else
+typedef long long int int_least64_t;
+#endif
+
+/* Unsigned. */
+typedef unsigned char uint_least8_t;
+typedef unsigned short int uint_least16_t;
+typedef unsigned int uint_least32_t;
+#if defined(SWIGWORDSIZE64)
+typedef unsigned long int uint_least64_t;
+#else
+typedef unsigned long long int uint_least64_t;
+#endif
+
+
+/* Fast types. */
+
+/* Signed. */
+typedef signed char int_fast8_t;
+#if defined(SWIGWORDSIZE64)
+typedef long int int_fast16_t;
+typedef long int int_fast32_t;
+typedef long int int_fast64_t;
+#else
+typedef int int_fast16_t;
+typedef int int_fast32_t;
+typedef long long int int_fast64_t;
+#endif
+
+/* Unsigned. */
+typedef unsigned char uint_fast8_t;
+#if defined(SWIGWORDSIZE64)
+typedef unsigned long int uint_fast16_t;
+typedef unsigned long int uint_fast32_t;
+typedef unsigned long int uint_fast64_t;
+#else
+typedef unsigned int uint_fast16_t;
+typedef unsigned int uint_fast32_t;
+typedef unsigned long long int uint_fast64_t;
+#endif
+
+
+/* Types for `void *' pointers. */
+#if defined(SWIGWORDSIZE64)
+typedef long int intptr_t;
+typedef unsigned long int uintptr_t;
+#else
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+#endif
+
+
+/* Largest integral types. */
+#if defined(SWIGWORDSIZE64)
+typedef long int intmax_t;
+typedef unsigned long int uintmax_t;
+#else
+typedef long long int intmax_t;
+typedef unsigned long long int uintmax_t;
+#endif
+
+
diff --git a/contrib/tools/swig/Lib/stl.i b/contrib/tools/swig/Lib/stl.i
new file mode 100644
index 00000000000..0b236afda4b
--- /dev/null
+++ b/contrib/tools/swig/Lib/stl.i
@@ -0,0 +1,7 @@
+/* -----------------------------------------------------------------------------
+ * stl.i
+ * ----------------------------------------------------------------------------- */
+
+#warning "stl.i not implemented for this target"
+#define SWIG_STL_UNIMPL
+
diff --git a/contrib/tools/swig/Lib/swig.swg b/contrib/tools/swig/Lib/swig.swg
new file mode 100644
index 00000000000..a7d41a7aeef
--- /dev/null
+++ b/contrib/tools/swig/Lib/swig.swg
@@ -0,0 +1,710 @@
+/* -----------------------------------------------------------------------------
+ * swig.swg
+ *
+ * Common macro definitions for various SWIG directives. This file is always
+ * included at the top of each input file.
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * User Directives
+ * ----------------------------------------------------------------------------- */
+
+/* Code insertion directives such as %wrapper %{ ... %} */
+
+#define %begin %insert("begin")
+#define %runtime %insert("runtime")
+#define %header %insert("header")
+#define %wrapper %insert("wrapper")
+#define %init %insert("init")
+
+/* %ignore directive */
+
+#define %ignore %rename($ignore)
+#define %ignorewarn(x) %rename("$ignore:" x)
+
+/* Access control directives */
+
+#define %immutable %feature("immutable")
+#define %noimmutable %feature("immutable","0")
+#define %clearimmutable %feature("immutable","")
+#define %mutable %clearimmutable
+
+/* Generation of default constructors/destructors (old form, don't use) */
+#define %nodefault %feature("nodefault","1")
+#define %default %feature("nodefault","0")
+#define %clearnodefault %feature("nodefault","")
+#define %makedefault %clearnodefault
+
+/* Disable the generation of implicit default constructor */
+#define %nodefaultctor %feature("nodefaultctor","1")
+#define %defaultctor %feature("nodefaultctor","0")
+#define %clearnodefaultctor %feature("nodefaultctor","")
+
+/* Disable the generation of implicit default destructor (dangerous) */
+#define %nodefaultdtor %feature("nodefaultdtor","1")
+#define %defaultdtor %feature("nodefaultdtor","0")
+#define %clearnodefaultdtor %feature("nodefaultdtor","")
+
+/* Enable the generation of copy constructor */
+#define %copyctor %feature("copyctor","1")
+#define %nocopyctor %feature("copyctor","0")
+#define %clearcopyctor %feature("copyctor","")
+
+/* Force the old nodefault behavior, ie disable both constructor and destructor */
+#define %oldnodefault %feature("oldnodefault","1")
+#define %nooldnodefault %feature("oldnodefault","0")
+#define %clearoldnodefault %feature("oldnodefault","")
+
+/* the %exception directive */
+#if defined(SWIGCSHARP) || defined(SWIGD)
+#define %exception %feature("except", canthrow=1)
+#else
+#define %exception %feature("except")
+#endif
+#define %noexception %feature("except","0")
+#define %clearexception %feature("except","")
+
+/* the %allowexception directive allows the %exception feature to
+ be applied to set/get variable methods */
+#define %allowexception %feature("allowexcept")
+#define %noallowexception %feature("allowexcept","0")
+#define %clearallowexception %feature("allowexcept","")
+
+/* the %exceptionvar directive, as %exception but it is only applied
+ to set/get variable methods. You don't need to use the
+ %allowexception directive when using %exceptionvar.
+*/
+#if defined(SWIGCSHARP) || defined(SWIGD)
+#define %exceptionvar %feature("exceptvar", canthrow=1)
+#else
+#define %exceptionvar %feature("exceptvar")
+#endif
+#define %noexceptionvar %feature("exceptvar","0")
+#define %clearexceptionvar %feature("exceptvar","")
+
+/* the %catches directive */
+#define %catches(tlist...) %feature("catches","("`tlist`")")
+#define %clearcatches %feature("catches","")
+
+/* the %exceptionclass directive */
+#define %exceptionclass %feature("exceptionclass")
+#define %noexceptionclass %feature("exceptionclass","0")
+#define %clearexceptionclass %feature("exceptionclass","")
+
+/* the %newobject directive */
+#define %newobject %feature("new")
+#define %nonewobject %feature("new","0")
+#define %clearnewobject %feature("new","")
+
+/* the %delobject directive */
+#define %delobject %feature("del")
+#define %nodelobject %feature("del","0")
+#define %cleardelobject %feature("del","")
+
+/* the %refobject/%unrefobject directives */
+#define %refobject %feature("ref")
+#define %norefobject %feature("ref","0")
+#define %clearrefobject %feature("ref","")
+
+#define %unrefobject %feature("unref")
+#define %nounrefobject %feature("unref","0")
+#define %clearunrefobject %feature("unref","")
+
+/* Directives for callback functions (experimental) */
+#define %callback(x) %feature("callback",`x`)
+#define %nocallback %feature("callback","0")
+#define %clearcallback %feature("callback","")
+
+/* 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")
+#define %clearfastdispatch %feature("fastdispatch","")
+
+/* directors directives */
+#define %director %feature("director")
+#define %nodirector %feature("director","0")
+#define %cleardirector %feature("director","")
+
+/* naturalvar directives */
+#define %naturalvar %feature("naturalvar")
+#define %nonaturalvar %feature("naturalvar","0")
+#define %clearnaturalvar %feature("naturalvar","")
+
+/* nspace directives */
+#define %nspace %feature("nspace")
+#define %nonspace %feature("nspace","0")
+#define %clearnspace %feature("nspace","")
+#define %nspacemove(NAMESPACE) %feature("nspace", #NAMESPACE)
+
+/* valuewrapper directives */
+#define %valuewrapper %feature("valuewrapper")
+#define %clearvaluewrapper %feature("valuewrapper","")
+#define %novaluewrapper %feature("novaluewrapper")
+#define %clearnovaluewrapper %feature("novaluewrapper","")
+
+/* Contract support - Experimental */
+#define %contract %feature("contract")
+#define %nocontract %feature("contract","0")
+#define %clearcontract %feature("contract","")
+
+/* Macro for setting a dynamic cast function */
+%define DYNAMIC_CAST(mangle,func)
+%init %{
+ mangle->dcast = (swig_dycast_func) func;
+%}
+%enddef
+
+/* aggregation support */
+/*
+ This macro performs constant aggregation. Basically the idea of
+ constant aggregation is that you can group a collection of constants
+ together. For example, suppose you have some code like this:
+
+ #define UP 1
+ #define DOWN 2
+ #define LEFT 3
+ #define RIGHT 4
+
+ Now, suppose you had a function like this:
+
+ int move(int direction)
+
+ In this case, you might want to restrict the direction argument to
+ one of the supplied constant names. To do this, you could write some
+ typemap code by hand. Alternatively, you can use the
+ %aggregate_check macro defined here to create a simple check
+ function for you. Here is an example:
+
+ %aggregate_check(int, check_direction, UP, DOWN, LEFT, RIGHT);
+
+ Now, using a typemap
+
+ %typemap(check) int direction {
+ if (!check_direction($1)) SWIG_exception(SWIG_ValueError,"Bad direction.");
+ }
+
+ or a contract (better)
+
+ %contract move(int x) {
+ require:
+ check_direction(x);
+ }
+
+*/
+
+%define %aggregate_check(TYPE, NAME, FIRST, ...)
+%wrapper %{
+static int NAME(TYPE x) {
+ static TYPE values[] = { FIRST, ##__VA_ARGS__ };
+ static int size = sizeof(values);
+ int i,j;
+ for (i = 0, j = 0; i < size; i+=sizeof(TYPE),j++) {
+ if (x == values[j]) return 1;
+ }
+ return 0;
+}
+%}
+%enddef
+
+
+/* -----------------------------------------------------------------------------
+ * %rename predicates
+ * ----------------------------------------------------------------------------- */
+/*
+ Predicates to be used with %rename, for example:
+
+ - to rename all the functions:
+
+ %rename("%(utitle)s", %$isfunction) "";
+
+ - to rename only the member methods:
+
+ %rename("m_%(utitle)s", %$isfunction, %$ismember) "";
+
+ - to rename only the global functions:
+
+ %rename("m_%(utitle)s", %$isfunction, %$not %$ismember) "";
+
+ or
+
+ %rename("g_%(utitle)s", %$isfunction, %$isglobal) "";
+
+ - to ignore the enumitems in a given class:
+
+ %rename("$ignore", %$isenumitem, %$classname="MyClass") "";
+
+ we use the prefix '%$' to avoid clashes with other swig
+ macros/directives.
+
+*/
+
+/* Note that when %$not is used with another macro, say %enum as follows: %$not %$enum, the result is "notmatch=enum" */
+%define %$not "not" %enddef
+
+%define %$isenum "match"="enum" %enddef
+%define %$isenumitem "match"="enumitem" %enddef
+%define %$isaccess "match"="access" %enddef
+%define %$isclass "match"="class","notmatch$template$templatetype"="class" %enddef
+%define %$isextend "match"="extend" %enddef
+%define %$isconstructor "match"="constructor" %enddef
+%define %$isdestructor "match"="destructor" %enddef
+%define %$isnamespace "match"="namespace" %enddef
+%define %$istemplate "match"="template" %enddef
+%define %$isconstant "match"="constant" %enddef /* %constant definition */
+%define %$isusing "match"="using" %enddef
+
+%define %$isunion "match$kind"="union" %enddef
+%define %$isfunction "match$kind"="function" %enddef
+%define %$isvariable "match$kind"="variable" %enddef
+%define %$isimmutable "match$feature:immutable"="1" %enddef
+%define %$hasconsttype "match$hasconsttype"="1" %enddef
+%define %$hasvalue "match$hasvalue"="1" %enddef
+%define %$isextension "match$isextension"="1" %enddef
+
+%define %$isstatic "match$storage"="static" %enddef
+%define %$isfriend "match$storage"="friend" %enddef
+%define %$istypedef "match$storage"="typedef" %enddef
+%define %$isvirtual "match$storage"="virtual" %enddef
+%define %$isexplicit "match$storage"="explicit" %enddef
+%define %$isextern "match$storage"="extern" %enddef
+
+%define %$ismember "match$ismember"="1" %enddef
+%define %$isglobal %$not %$ismember %enddef
+%define %$isextendmember "match$isextendmember"="1" %enddef
+%define %$innamespace "match$parentNode$nodeType"="namespace" %enddef
+
+%define %$ispublic "match$access"="public" %enddef
+%define %$isprotected "match$access"="protected" %enddef
+%define %$isprivate "match$access"="private" %enddef
+
+%define %$ismemberget "match$memberget"="1" %enddef
+%define %$ismemberset "match$memberset"="1" %enddef
+
+%define %$classname %$ismember,"match$parentNode$name" %enddef
+%define %$isnested "match$nested"="1" %enddef
+
+/* -----------------------------------------------------------------------------
+ * Common includes for warning labels, macros, fragments etc
+ * ----------------------------------------------------------------------------- */
+
+%include <swigwarnings.swg>
+%include <swigfragments.swg>
+
+/* -----------------------------------------------------------------------------
+ * Overloading support
+ * ----------------------------------------------------------------------------- */
+
+/*
+ * Function/method overloading support. This is done through typemaps,
+ * but also involves a precedence level.
+ */
+
+/* Macro for overload resolution */
+
+%define %typecheck(_x...) %typemap(typecheck, precedence=_x) %enddef
+
+/* Macros for precedence levels */
+
+%define SWIG_TYPECHECK_POINTER 0 %enddef
+%define SWIG_TYPECHECK_ITERATOR 5 %enddef
+%define SWIG_TYPECHECK_VOIDPTR 10 %enddef
+%define SWIG_TYPECHECK_BOOL 15 %enddef
+%define SWIG_TYPECHECK_UINT8 20 %enddef
+%define SWIG_TYPECHECK_INT8 25 %enddef
+%define SWIG_TYPECHECK_UINT16 30 %enddef
+%define SWIG_TYPECHECK_INT16 35 %enddef
+%define SWIG_TYPECHECK_UINT32 40 %enddef
+%define SWIG_TYPECHECK_INT32 45 %enddef
+%define SWIG_TYPECHECK_SIZE 47 %enddef
+%define SWIG_TYPECHECK_PTRDIFF 48 %enddef
+%define SWIG_TYPECHECK_UINT64 50 %enddef
+%define SWIG_TYPECHECK_INT64 55 %enddef
+%define SWIG_TYPECHECK_UINT128 60 %enddef
+%define SWIG_TYPECHECK_INT128 65 %enddef
+%define SWIG_TYPECHECK_INTEGER 70 %enddef
+%define SWIG_TYPECHECK_FLOAT 80 %enddef
+%define SWIG_TYPECHECK_DOUBLE 90 %enddef
+%define SWIG_TYPECHECK_CPLXFLT 95 %enddef
+%define SWIG_TYPECHECK_CPLXDBL 100 %enddef
+%define SWIG_TYPECHECK_COMPLEX 105 %enddef
+%define SWIG_TYPECHECK_UNICHAR 110 %enddef
+%define SWIG_TYPECHECK_STDUNISTRING 115 %enddef
+%define SWIG_TYPECHECK_UNISTRING 120 %enddef
+%define SWIG_TYPECHECK_CHAR 130 %enddef
+/* Give std::string_view a slightly higher precedence because if there are
+ * overloaded forms then it may be more efficient to pass as std::string_view
+ * (e.g. to pass as std::string requires copying the data into a std::string).
+ */
+%define SWIG_TYPECHECK_STRINGVIEW 134 %enddef
+%define SWIG_TYPECHECK_STDSTRING 135 %enddef
+%define SWIG_TYPECHECK_STRING 140 %enddef
+%define SWIG_TYPECHECK_PAIR 150 %enddef
+%define SWIG_TYPECHECK_STDARRAY 155 %enddef
+%define SWIG_TYPECHECK_VECTOR 160 %enddef
+%define SWIG_TYPECHECK_DEQUE 170 %enddef
+%define SWIG_TYPECHECK_LIST 180 %enddef
+%define SWIG_TYPECHECK_SET 190 %enddef
+%define SWIG_TYPECHECK_MULTISET 200 %enddef
+%define SWIG_TYPECHECK_MAP 210 %enddef
+%define SWIG_TYPECHECK_MULTIMAP 220 %enddef
+%define SWIG_TYPECHECK_STACK 230 %enddef
+%define SWIG_TYPECHECK_QUEUE 240 %enddef
+
+%define SWIG_TYPECHECK_BOOL_ARRAY 1015 %enddef
+%define SWIG_TYPECHECK_INT8_ARRAY 1025 %enddef
+%define SWIG_TYPECHECK_INT16_ARRAY 1035 %enddef
+%define SWIG_TYPECHECK_INT32_ARRAY 1045 %enddef
+%define SWIG_TYPECHECK_INT64_ARRAY 1055 %enddef
+%define SWIG_TYPECHECK_INT128_ARRAY 1065 %enddef
+%define SWIG_TYPECHECK_FLOAT_ARRAY 1080 %enddef
+%define SWIG_TYPECHECK_DOUBLE_ARRAY 1090 %enddef
+%define SWIG_TYPECHECK_CHAR_ARRAY 1130 %enddef
+%define SWIG_TYPECHECK_STRING_ARRAY 1140 %enddef
+%define SWIG_TYPECHECK_OBJECT_ARRAY 1150 %enddef
+
+%define SWIG_TYPECHECK_BOOL_PTR 2015 %enddef
+%define SWIG_TYPECHECK_UINT8_PTR 2020 %enddef
+%define SWIG_TYPECHECK_INT8_PTR 2025 %enddef
+%define SWIG_TYPECHECK_UINT16_PTR 2030 %enddef
+%define SWIG_TYPECHECK_INT16_PTR 2035 %enddef
+%define SWIG_TYPECHECK_UINT32_PTR 2040 %enddef
+%define SWIG_TYPECHECK_INT32_PTR 2045 %enddef
+%define SWIG_TYPECHECK_UINT64_PTR 2050 %enddef
+%define SWIG_TYPECHECK_INT64_PTR 2055 %enddef
+%define SWIG_TYPECHECK_FLOAT_PTR 2080 %enddef
+%define SWIG_TYPECHECK_DOUBLE_PTR 2090 %enddef
+%define SWIG_TYPECHECK_CHAR_PTR 2130 %enddef
+
+%define SWIG_TYPECHECK_SWIGOBJECT 5000 %enddef
+
+
+/* -----------------------------------------------------------------------------
+ * Default handling of certain overloaded operators
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+%ignoreoperator(NEW) operator new;
+%ignoreoperator(DELETE) operator delete;
+%ignoreoperator(NEWARR) operator new[];
+%ignoreoperator(DELARR) operator delete[];
+
+/* add C++ operator aliases */
+%rename("operator &&") operator and; // `and' `&&'
+%rename("operator ||") operator or; // `or' `||'
+%rename("operator !") operator not; // `not' `!'
+%rename("operator &=") operator and_eq; // `and_eq' `&='
+%rename("operator &") operator bitand; // `bitand' `&'
+%rename("operator |") operator bitor; // `bitor' `|'
+%rename("operator ~") operator compl; // `compl' `~'
+%rename("operator !=") operator not_eq; // `not_eq' `!='
+%rename("operator |=") operator or_eq; // `or_eq' `|='
+%rename("operator ^") operator xor; // `xor' `^'
+%rename("operator ^=") operator xor_eq; // `xor_eq' `^='
+
+/* Smart pointer handling */
+
+%rename(__deref__) *::operator->;
+%rename(__ref__) *::operator*();
+%rename(__ref__) *::operator*() const;
+
+/* Define std namespace */
+namespace std {
+ /* Warn about std::initializer_list usage. The constructor/method where used should probably be ignored. See docs. */
+ template<typename T> class initializer_list {};
+ %typemap(in, warning=SWIGWARN_TYPEMAP_INITIALIZER_LIST_MSG) initializer_list<T> ""
+ %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) initializer_list<T> ""
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Default char * and C array typemaps
+ * ----------------------------------------------------------------------------- */
+
+/* Set up the typemap for handling new return strings */
+
+#ifdef __cplusplus
+%typemap(newfree) char * "delete [] $1;"
+#else
+%typemap(newfree) char * "free($1);"
+#endif
+
+/* Default typemap for handling char * members */
+
+#ifdef __cplusplus
+%typemap(memberin,fragment="<string.h>") char * {
+ delete [] $1;
+ if ($input) {
+ $1 = ($1_type) (new char[strlen((const char *)$input)+1]);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(memberin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="<string.h>") const char * {
+ if ($input) {
+ $1 = ($1_type) (new char[strlen((const char *)$input)+1]);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(globalin,fragment="<string.h>") char * {
+ delete [] $1;
+ if ($input) {
+ $1 = ($1_type) (new char[strlen((const char *)$input)+1]);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(globalin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="<string.h>") const char * {
+ if ($input) {
+ $1 = ($1_type) (new char[strlen((const char *)$input)+1]);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+#else
+%typemap(memberin,fragment="<string.h>") char * {
+ free($1);
+ if ($input) {
+ $1 = ($1_type) malloc(strlen((const char *)$input)+1);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(memberin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="<string.h>") const char * {
+ if ($input) {
+ $1 = ($1_type) malloc(strlen((const char *)$input)+1);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(globalin,fragment="<string.h>") char * {
+ free($1);
+ if ($input) {
+ $1 = ($1_type) malloc(strlen((const char *)$input)+1);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+%typemap(globalin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG,fragment="<string.h>") const char * {
+ if ($input) {
+ $1 = ($1_type) malloc(strlen((const char *)$input)+1);
+ strcpy((char *)$1, (const char *)$input);
+ } else {
+ $1 = 0;
+ }
+}
+
+#endif
+
+/* Character array handling */
+
+%typemap(memberin,fragment="<string.h>") char [ANY] {
+ if($input) {
+ strncpy((char*)$1, (const char *)$input, $1_dim0-1);
+ $1[$1_dim0-1] = 0;
+ } else {
+ $1[0] = 0;
+ }
+}
+
+%typemap(globalin,fragment="<string.h>") char [ANY] {
+ if($input) {
+ strncpy((char*)$1, (const char *)$input, $1_dim0-1);
+ $1[$1_dim0-1] = 0;
+ } else {
+ $1[0] = 0;
+ }
+}
+
+%typemap(memberin,fragment="<string.h>") char [] {
+ if ($input) strcpy((char *)$1, (const char *)$input);
+ else $1[0] = 0;
+}
+
+%typemap(globalin,fragment="<string.h>") char [] {
+ if ($input) strcpy((char *)$1, (const char *)$input);
+ else $1[0] = 0;
+}
+
+/* memberin/globalin typemap for arrays. */
+
+%typemap(memberin) SWIGTYPE [ANY] {
+ size_t ii;
+ $1_basetype *b = ($1_basetype *) $1;
+ for (ii = 0; ii < (size_t)$1_size; ii++) b[ii] = *(($1_basetype *) $input + ii);
+}
+
+%typemap(globalin) SWIGTYPE [ANY] {
+ size_t ii;
+ $1_basetype *b = ($1_basetype *) $1;
+ for (ii = 0; ii < (size_t)$1_size; ii++) b[ii] = *(($1_basetype *) $input + ii);
+}
+
+/* memberin/globalin typemap for double arrays. */
+
+%typemap(memberin) SWIGTYPE [ANY][ANY] {
+ $basetype (*inp)[$1_dim1] = ($basetype (*)[$1_dim1])($input);
+ $basetype (*dest)[$1_dim1] = ($basetype (*)[$1_dim1])($1);
+ size_t ii = 0;
+ for (; ii < $1_dim0; ++ii) {
+ $basetype *ip = inp[ii];
+ $basetype *dp = dest[ii];
+ size_t jj = 0;
+ for (; jj < $1_dim1; ++jj) dp[jj] = ip[jj];
+ }
+}
+
+%typemap(globalin) SWIGTYPE [ANY][ANY] {
+ $basetype (*inp)[$1_dim1] = ($basetype (*)[$1_dim1])($input);
+ $basetype (*dest)[$1_dim1] = ($basetype (*)[$1_dim1])($1);
+ size_t ii = 0;
+ for (; ii < $1_dim0; ++ii) {
+ $basetype *ip = inp[ii];
+ $basetype *dp = dest[ii];
+ size_t jj = 0;
+ for (; jj < $1_dim1; ++jj) dp[jj] = ip[jj];
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Runtime code
+ * ----------------------------------------------------------------------------- */
+
+
+%insert("runtime") "swiglabels.swg"
+
+
+/* The SwigValueWrapper class */
+
+/*
+ * This template wrapper is used to handle C++ objects that are passed or
+ * returned by value. This is necessary to handle objects that define
+ * no default-constructor (making it difficult for SWIG to properly declare
+ * local variables).
+ *
+ * The wrapper is used as follows. First consider a function like this:
+ *
+ * Vector cross_product(Vector a, Vector b)
+ *
+ * Now, if Vector is defined as a C++ class with no default constructor,
+ * code is generated as follows:
+ *
+ * Vector *wrap_cross_product(Vector *inarg1, Vector *inarg2) {
+ * SwigValueWrapper<Vector> arg1;
+ * SwigValueWrapper<Vector> arg2;
+ * SwigValueWrapper<Vector> result;
+ *
+ * arg1 = *inarg1;
+ * arg2 = *inarg2;
+ * ...
+ * result = cross_product(arg1,arg2);
+ * ...
+ * return new Vector(result);
+ * }
+ *
+ * In the wrappers, the template SwigValueWrapper simply provides a thin
+ * layer around a Vector *. However, it does this in a way that allows
+ * the object to be bound after the variable declaration (which is not possible
+ * with the bare object when it lacks a default constructor).
+ *
+ * An observant reader will notice that the code after the variable declarations
+ * is *identical* to the code used for classes that do define default constructors.
+ * Thus, this neat trick allows us to fix this special case without having to
+ * make massive changes to typemaps and other parts of the SWIG code generator.
+ *
+ * Note: this code is not included when SWIG runs in C-mode, when classes
+ * define default constructors, or when pointers and references are used.
+ * SWIG tries to avoid doing this except in very special circumstances.
+ *
+ * Note: This solution suffers from making a large number of copies
+ * of the underlying object. However, this is needed in the interest of
+ * safety and in order to cover all of the possible ways in which a value
+ * might be assigned. For example:
+ *
+ * arg1 = *inarg1; // Assignment from a pointer
+ * arg1 = Vector(1,2,3); // Assignment from a value
+ *
+ * SwigValueWrapper is a drop in replacement to modify normal value semantics by
+ * using the heap instead of the stack to copy/move the underlying object it is
+ * managing. Smart pointers also manage an underlying object on the heap, so
+ * SwigValueWrapper has characteristics of a smart pointer. The reset function
+ * is specific smart pointer functionality, but cannot be a non-static member as
+ * when SWIG modifies typemap code it assumes non-static member function calls
+ * are routed to the underlying object, changing for example $1.f() to (&x)->f().
+ * The reset function was added as an optimisation to avoid some copying/moving
+ * and to take ownership of an object already created on the heap.
+ *
+ * The class offers a strong guarantee of exception safety.
+ * With regards to the implementation, the private SwigSmartPointer nested class is
+ * a simple smart pointer providing exception safety, much like std::auto_ptr.
+ *
+ * This wrapping technique was suggested by William Fulton and is henceforth
+ * known as the "Fulton Transform" :-).
+ */
+
+#ifdef __cplusplus
+// Placed in the header section to ensure the language specific header files are
+// the first included headers and not <utility>
+%insert("header") %{
+#ifdef __cplusplus
+#include <utility>
+/* SwigValueWrapper is described in swig.swg */
+template<typename T> class SwigValueWrapper {
+ struct SwigSmartPointer {
+ T *ptr;
+ SwigSmartPointer(T *p) : ptr(p) { }
+ ~SwigSmartPointer() { delete ptr; }
+ SwigSmartPointer& operator=(SwigSmartPointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; }
+ void reset(T *p) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = p; }
+ } pointer;
+ SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs);
+ SwigValueWrapper(const SwigValueWrapper<T>& rhs);
+public:
+ SwigValueWrapper() : pointer(0) { }
+ SwigValueWrapper& operator=(const T& t) { SwigSmartPointer tmp(new T(t)); pointer = tmp; return *this; }
+#if __cplusplus >=201103L
+ SwigValueWrapper& operator=(T&& t) { SwigSmartPointer tmp(new T(std::move(t))); pointer = tmp; return *this; }
+ operator T&&() const { return std::move(*pointer.ptr); }
+#else
+ operator T&() const { return *pointer.ptr; }
+#endif
+ T *operator&() const { return pointer.ptr; }
+ static void reset(SwigValueWrapper& t, T *p) { t.pointer.reset(p); }
+};
+
+/*
+ * SwigValueInit() is a generic initialisation solution as the following approach:
+ *
+ * T c_result = T();
+ *
+ * doesn't compile for all types for example:
+ *
+ * unsigned int c_result = unsigned int();
+ */
+template <typename T> T SwigValueInit() {
+ return T();
+}
+
+#if __cplusplus >=201103L
+# define SWIG_STD_MOVE(OBJ) std::move(OBJ)
+#else
+# define SWIG_STD_MOVE(OBJ) OBJ
+#endif
+
+#endif
+%}
+#endif
+
+%insert("runtime") "swigcompat.swg"
diff --git a/contrib/tools/swig/Lib/swigarch.i b/contrib/tools/swig/Lib/swigarch.i
new file mode 100644
index 00000000000..2f7614940fc
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigarch.i
@@ -0,0 +1,33 @@
+/* -----------------------------------------------------------------------------
+ * swigarch.i
+ *
+ * SWIG library file for 32bit/64bit code specialization and checking.
+ *
+ * Use only in extreme cases, when no arch. independent code can be
+ * generated
+ *
+ * To activate 32-bit architecture checks, use
+ *
+ * swig -DSWIGWORDSIZE32
+ *
+ * This adds checks that long is 32-bits when compiling the generated wrappers.
+ *
+ * To activate 64-bit architecture specific code, use
+ *
+ * swig -DSWIGWORDSIZE64
+ *
+ * This adds checks that long is 64-bits when compiling the generated wrappers.
+ * Some target languages also generate code that expects long to be 64-bits.
+ *
+ * If you don't specify the SWIGWORDSIZE (the default case), SWIG will
+ * generate architecture independent and/or 32bits code, with no extra
+ * checks for the sizeof long.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef SWIGWORDSIZE32
+%fragment("long_check_wordsize32");
+#endif
+
+#ifdef SWIGWORDSIZE64
+%fragment("long_check_wordsize64");
+#endif
diff --git a/contrib/tools/swig/Lib/swigcompat.swg b/contrib/tools/swig/Lib/swigcompat.swg
new file mode 100644
index 00000000000..cf69b921fab
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigcompat.swg
@@ -0,0 +1,27 @@
+/* -----------------------------------------------------------------------------
+ * swigcompat.swg
+ *
+ * Macros to provide support compatibility with older C and C++ standards.
+ *
+ * Note that SWIG expects __cplusplus to be defined to the appropriate C++ standard.
+ * MSVC users are urged to check and examine the /Zc:__cplusplus compiler option.
+ * See https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus.
+ * ----------------------------------------------------------------------------- */
+
+/* C99 and C++11 should provide snprintf, but define SWIG_NO_SNPRINTF
+ * if you're missing it.
+ */
+#if ((defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || \
+ (defined __cplusplus && __cplusplus >= 201103L) || \
+ defined SWIG_HAVE_SNPRINTF) && \
+ !defined SWIG_NO_SNPRINTF
+# define SWIG_snprintf(O,S,F,A) snprintf(O,S,F,A)
+# define SWIG_snprintf2(O,S,F,A,B) snprintf(O,S,F,A,B)
+#else
+/* Fallback versions ignore the buffer size, but most of our uses either have a
+ * fixed maximum possible size or dynamically allocate a buffer that's large
+ * enough.
+ */
+# define SWIG_snprintf(O,S,F,A) sprintf(O,F,A)
+# define SWIG_snprintf2(O,S,F,A,B) sprintf(O,F,A,B)
+#endif
diff --git a/contrib/tools/swig/Lib/swigerrors.swg b/contrib/tools/swig/Lib/swigerrors.swg
new file mode 100644
index 00000000000..4d5a8e473d1
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigerrors.swg
@@ -0,0 +1,15 @@
+/* SWIG Errors applicable to all language modules, values are reserved from -1 to -99 */
+#define SWIG_UnknownError -1
+#define SWIG_IOError -2
+#define SWIG_RuntimeError -3
+#define SWIG_IndexError -4
+#define SWIG_TypeError -5
+#define SWIG_DivisionByZero -6
+#define SWIG_OverflowError -7
+#define SWIG_SyntaxError -8
+#define SWIG_ValueError -9
+#define SWIG_SystemError -10
+#define SWIG_AttributeError -11
+#define SWIG_MemoryError -12
+#define SWIG_NullReferenceError -13
+
diff --git a/contrib/tools/swig/Lib/swigfragments.swg b/contrib/tools/swig/Lib/swigfragments.swg
new file mode 100644
index 00000000000..75f05bc711f
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigfragments.swg
@@ -0,0 +1,129 @@
+/* -----------------------------------------------------------------------------
+ * swigfragments.swg
+ *
+ * Common fragments
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * Fragments for C header files
+ * ----------------------------------------------------------------------------- */
+
+%fragment("<float.h>", "header") %{
+#include <float.h>
+%}
+
+/* Default compiler options for gcc allow long_long but not LLONG_MAX.
+ * Define SWIG_NO_LLONG_MAX if this added limits support is not wanted. */
+%fragment("<limits.h>", "header") %{
+#include <limits.h>
+#if !defined(SWIG_NO_LLONG_MAX)
+# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
+# define LLONG_MAX __LONG_LONG_MAX__
+# define LLONG_MIN (-LLONG_MAX - 1LL)
+# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
+# endif
+#endif
+%}
+
+%fragment("<math.h>", "header") %{
+#include <math.h>
+%}
+
+%fragment("<string.h>", "header") %{
+#include <string.h>
+%}
+
+%fragment("<stddef.h>", "header") %{
+#include <stddef.h>
+%}
+
+%fragment("<stdio.h>", "header") %{
+#include <stdio.h>
+#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__BORLANDC__) || defined(_WATCOM)
+# ifndef snprintf
+# define snprintf _snprintf
+# endif
+#endif
+%}
+
+%fragment("<stdlib.h>", "header") %{
+#include <stdlib.h>
+#ifdef _MSC_VER
+# ifndef strtoull
+# define strtoull _strtoui64
+# endif
+# ifndef strtoll
+# define strtoll _strtoi64
+# endif
+#endif
+%}
+
+%fragment("<wchar.h>", "header") %{
+#include <wchar.h>
+#include <limits.h>
+#ifndef WCHAR_MIN
+# define WCHAR_MIN 0
+#endif
+#ifndef WCHAR_MAX
+# define WCHAR_MAX 65535
+#endif
+%}
+
+/* -----------------------------------------------------------------------------
+ * Fragments for C++ header files
+ * ----------------------------------------------------------------------------- */
+
+%fragment("<algorithm>", "header") %{
+#include <algorithm>
+%}
+
+%fragment("<memory>", "header") %{
+#include <memory>
+%}
+
+%fragment("<stdexcept>", "header") %{
+#include <stdexcept>
+%}
+
+%fragment("<string>", "header") %{
+#include <string>
+%}
+
+%fragment("<string_view>", "header") %{
+#include <string_view>
+%}
+
+%fragment("<type_traits>", "header") %{
+#include <type_traits>
+%}
+
+%fragment("<iostream>", "header") %{
+#include <iostream>
+%}
+
+/* -----------------------------------------------------------------------------
+ * Other common fragments
+ * ----------------------------------------------------------------------------- */
+
+%fragment("long_check_wordsize32", "header", fragment="<limits.h>") %{
+#if !defined(SWIG_NO_WORDSIZE32_CHECK)
+#if (__WORDSIZE == 64) || (LONG_MAX != INT_MAX)
+# error "SWIG generated code is invalid on this 64-bit architecture, please regenerate without defining SWIGWORDSIZE32 or define SWIGWORDSIZE64"
+#endif
+#endif
+%}
+
+%fragment("long_check_wordsize64", "header", fragment="<limits.h>") %{
+#if !defined(SWIG_NO_WORDSIZE64_CHECK)
+#if (__WORDSIZE == 32) || (LONG_MAX == INT_MAX)
+# error "SWIG generated code is invalid on this 32-bit architecture, please regenerate without defining SWIGWORDSIZE64 or define SWIGWORDSIZE32"
+#endif
+#endif
+%}
+
+#ifdef SWIGWORDSIZE64
+%fragment("long_check_wordsize", "header", fragment="long_check_wordsize64") {}
+#else
+%fragment("long_check_wordsize", "header", fragment="long_check_wordsize32") {}
+#endif
+
diff --git a/contrib/tools/swig/Lib/swiginit.swg b/contrib/tools/swig/Lib/swiginit.swg
new file mode 100644
index 00000000000..e50b1b46dcf
--- /dev/null
+++ b/contrib/tools/swig/Lib/swiginit.swg
@@ -0,0 +1,233 @@
+/* -----------------------------------------------------------------------------
+ * Type initialization:
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
+ * swig_cast_info structures and swig_cast_info structures store pointers back
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
+ * swig_module, and does all the lookup, filling in the swig_module.types
+ * array with the correct data and linking the correct swig_cast_info
+ * structures together.
+ *
+ * The generated swig_type_info structures are assigned statically to an initial
+ * array. We just loop through that array, and handle each type individually.
+ * First we lookup if this type has been already loaded, and if so, use the
+ * loaded structure instead of the generated one. Then we have to fill in the
+ * cast linked list. The cast data is initially stored in something like a
+ * two-dimensional array. Each row corresponds to a type (there are the same
+ * number of rows as there are in the swig_type_initial array). Each entry in
+ * a column is one of the swig_cast_info structures for that type.
+ * The cast_initial array is actually an array of arrays, because each row has
+ * a variable number of columns. So to actually build the cast linked list,
+ * we find the array of casts associated with the type, and loop through it
+ * adding the casts to the list. The one last trick we need to do is making
+ * sure the type pointer in the swig_cast_info struct is correct.
+ *
+ * First off, we lookup the cast->type name to see if it is already loaded.
+ * There are three cases to handle:
+ * 1) If the cast->type has already been loaded AND the type we are adding
+ * casting info to has not been loaded (it is in this module), THEN we
+ * replace the cast->type pointer with the type pointer that has already
+ * been loaded.
+ * 2) If BOTH types (the one we are adding casting info to, and the
+ * cast->type) are loaded, THEN the cast info has already been loaded by
+ * the previous module so we just ignore it.
+ * 3) Finally, if cast->type has not already been loaded, then we add that
+ * swig_cast_info to the linked list (because the cast->type) pointer will
+ * be correct.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* c-mode */
+#endif
+#endif
+
+#if 0
+#define SWIGRUNTIME_DEBUG
+#endif
+
+#ifndef SWIG_INIT_CLIENT_DATA_TYPE
+#define SWIG_INIT_CLIENT_DATA_TYPE void *
+#endif
+
+SWIGRUNTIME void
+SWIG_InitializeModule(SWIG_INIT_CLIENT_DATA_TYPE clientdata) {
+ size_t i;
+ swig_module_info *module_head, *iter;
+ int init;
+
+ /* check to see if the circular list has been setup, if not, set it up */
+ if (swig_module.next==0) {
+ /* Initialize the swig_module */
+ swig_module.type_initial = swig_type_initial;
+ swig_module.cast_initial = swig_cast_initial;
+ swig_module.next = &swig_module;
+ init = 1;
+ } else {
+ init = 0;
+ }
+
+ /* Try and load any already created modules */
+ module_head = SWIG_GetModule(clientdata);
+ if (!module_head) {
+ /* This is the first module loaded for this interpreter */
+ /* so set the swig module into the interpreter */
+ SWIG_SetModule(clientdata, &swig_module);
+ } else {
+ /* the interpreter has loaded a SWIG module, but has it loaded this one? */
+ iter=module_head;
+ do {
+ if (iter==&swig_module) {
+ /* Our module is already in the list, so there's nothing more to do. */
+ return;
+ }
+ iter=iter->next;
+ } while (iter!= module_head);
+
+ /* otherwise we must add our module into the list */
+ swig_module.next = module_head->next;
+ module_head->next = &swig_module;
+ }
+
+ /* When multiple interpreters are used, a module could have already been initialized in
+ a different interpreter, but not yet have a pointer in this interpreter.
+ In this case, we do not want to continue adding types... everything should be
+ set up already */
+ if (init == 0) return;
+
+ /* Now work on filling in swig_module.types */
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: size %lu\n", (unsigned long)swig_module.size);
+#endif
+ for (i = 0; i < swig_module.size; ++i) {
+ swig_type_info *type = 0;
+ swig_type_info *ret;
+ swig_cast_info *cast;
+
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name);
+#endif
+
+ /* if there is another module already loaded */
+ if (swig_module.next != &swig_module) {
+ type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
+ }
+ if (type) {
+ /* Overwrite clientdata field */
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: found type %s\n", type->name);
+#endif
+ if (swig_module.type_initial[i]->clientdata) {
+ type->clientdata = swig_module.type_initial[i]->clientdata;
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
+#endif
+ }
+ } else {
+ type = swig_module.type_initial[i];
+ }
+
+ /* Insert casting types */
+ cast = swig_module.cast_initial[i];
+ while (cast->type) {
+
+ /* Don't need to add information already in the list */
+ ret = 0;
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
+#endif
+ if (swig_module.next != &swig_module) {
+ ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
+#ifdef SWIGRUNTIME_DEBUG
+ if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
+#endif
+ }
+ if (ret) {
+ if (type == swig_module.type_initial[i]) {
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
+#endif
+ cast->type = ret;
+ ret = 0;
+ } else {
+ /* Check for casting already in the list */
+ swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
+#ifdef SWIGRUNTIME_DEBUG
+ if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
+#endif
+ if (!ocast) ret = 0;
+ }
+ }
+
+ if (!ret) {
+#ifdef SWIGRUNTIME_DEBUG
+ printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
+#endif
+ if (type->cast) {
+ type->cast->prev = cast;
+ cast->next = type->cast;
+ }
+ type->cast = cast;
+ }
+ cast++;
+ }
+ /* Set entry in modules->types array equal to the type */
+ swig_module.types[i] = type;
+ }
+ swig_module.types[i] = 0;
+
+#ifdef SWIGRUNTIME_DEBUG
+ printf("**** SWIG_InitializeModule: Cast List ******\n");
+ for (i = 0; i < swig_module.size; ++i) {
+ int j = 0;
+ swig_cast_info *cast = swig_module.cast_initial[i];
+ printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name);
+ while (cast->type) {
+ printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
+ cast++;
+ ++j;
+ }
+ printf("---- Total casts: %d\n",j);
+ }
+ printf("**** SWIG_InitializeModule: Cast List ******\n");
+#endif
+}
+
+/* This function will propagate the clientdata field of type to
+* any new swig_type_info structures that have been added into the list
+* of equivalent types. It is like calling
+* SWIG_TypeClientData(type, clientdata) a second time.
+*/
+SWIGRUNTIME void
+SWIG_PropagateClientData(void) {
+ size_t i;
+ swig_cast_info *equiv;
+ static int init_run = 0;
+
+ if (init_run) return;
+ init_run = 1;
+
+ for (i = 0; i < swig_module.size; i++) {
+ if (swig_module.types[i]->clientdata) {
+ equiv = swig_module.types[i]->cast;
+ while (equiv) {
+ if (!equiv->converter) {
+ if (equiv->type && !equiv->type->clientdata)
+ SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
+ }
+ equiv = equiv->next;
+ }
+ }
+ }
+}
+
+#ifdef __cplusplus
+#if 0
+{ /* c-mode */
+#endif
+}
+#endif
diff --git a/contrib/tools/swig/Lib/swiglabels.swg b/contrib/tools/swig/Lib/swiglabels.swg
new file mode 100644
index 00000000000..58d87e92a6e
--- /dev/null
+++ b/contrib/tools/swig/Lib/swiglabels.swg
@@ -0,0 +1,129 @@
+/* -----------------------------------------------------------------------------
+ * This section contains generic SWIG labels for method/variable
+ * declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+# define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+# define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+# define SWIGINLINE inline
+# else
+# define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+# elif defined(__ICC)
+# define SWIGUNUSED __attribute__ ((__unused__))
+# else
+# define SWIGUNUSED
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+# pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+# define SWIGUNUSEDPARM(p)
+# else
+# define SWIGUNUSEDPARM(p) p SWIGUNUSED
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if defined(__GNUC__)
+# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# ifndef GCC_HASCLASSVISIBILITY
+# define GCC_HASCLASSVISIBILITY
+# endif
+# endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# if defined(STATIC_LINKED)
+# define SWIGEXPORT
+# else
+# define SWIGEXPORT __declspec(dllexport)
+# endif
+# else
+# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+# define SWIGEXPORT __attribute__ ((visibility("default")))
+# else
+# define SWIGEXPORT
+# endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# define SWIGSTDCALL __stdcall
+# else
+# define SWIGSTDCALL
+# endif
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used. So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
+
+#if defined(__cplusplus) && __cplusplus >=201103L
+# define SWIG_NULLPTR nullptr
+#else
+# define SWIG_NULLPTR NULL
+#endif
diff --git a/contrib/tools/swig/Lib/swigrun.i b/contrib/tools/swig/Lib/swigrun.i
new file mode 100644
index 00000000000..6026a915162
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigrun.i
@@ -0,0 +1,8 @@
+/* -----------------------------------------------------------------------------
+ * swigrun.i
+ *
+ * Empty module (for now). Placeholder for runtime libs
+ * ----------------------------------------------------------------------------- */
+
+%module swigrun
+
diff --git a/contrib/tools/swig/Lib/swigrun.swg b/contrib/tools/swig/Lib/swigrun.swg
new file mode 100644
index 00000000000..824185c0202
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigrun.swg
@@ -0,0 +1,581 @@
+/* -----------------------------------------------------------------------------
+ * swigrun.swg
+ *
+ * This file contains generic C API SWIG runtime support for pointer
+ * type checking.
+ * ----------------------------------------------------------------------------- */
+
+/* This should only be incremented when either the layout of swig_type_info changes,
+ or for whatever reason, the runtime changes incompatibly */
+#define SWIG_RUNTIME_VERSION "4"
+
+/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
+#ifdef SWIG_TYPE_TABLE
+# define SWIG_QUOTE_STRING(x) #x
+# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
+# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
+#else
+# define SWIG_TYPE_TABLE_NAME
+#endif
+
+/*
+ You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
+ creating a static or dynamic library from the SWIG runtime code.
+ In 99.9% of the cases, SWIG just needs to declare them as 'static'.
+
+ But only do this if strictly necessary, ie, if you have problems
+ with your compiler or suchlike.
+*/
+
+#ifndef SWIGRUNTIME
+# define SWIGRUNTIME SWIGINTERN
+#endif
+
+#ifndef SWIGRUNTIMEINLINE
+# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
+#endif
+
+/* Generic buffer size */
+#ifndef SWIG_BUFFER_SIZE
+# define SWIG_BUFFER_SIZE 1024
+#endif
+
+/* Flags for pointer conversions */
+#define SWIG_POINTER_DISOWN 0x1
+#define SWIG_CAST_NEW_MEMORY 0x2
+#define SWIG_POINTER_NO_NULL 0x4
+#define SWIG_POINTER_CLEAR 0x8
+#define SWIG_POINTER_RELEASE (SWIG_POINTER_CLEAR | SWIG_POINTER_DISOWN)
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_OWN 0x1
+
+
+/*
+ Flags/methods for returning states.
+
+ The SWIG conversion methods, as ConvertPtr, return an integer
+ that tells if the conversion was successful or not. And if not,
+ an error code can be returned (see swigerrors.swg for the codes).
+
+ Use the following macros/flags to set or process the returning
+ states.
+
+ In old versions of SWIG, code such as the following was usually written:
+
+ if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
+ // success code
+ } else {
+ //fail code
+ }
+
+ Now you can be more explicit:
+
+ int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
+ if (SWIG_IsOK(res)) {
+ // success code
+ } else {
+ // fail code
+ }
+
+ which is the same really, but now you can also do
+
+ Type *ptr;
+ int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
+ if (SWIG_IsOK(res)) {
+ // success code
+ if (SWIG_IsNewObj(res) {
+ ...
+ delete *ptr;
+ } else {
+ ...
+ }
+ } else {
+ // fail code
+ }
+
+ I.e., now SWIG_ConvertPtr can return new objects and you can
+ identify the case and take care of the deallocation. Of course that
+ also requires SWIG_ConvertPtr to return new result values, such as
+
+ int SWIG_ConvertPtr(obj, ptr,...) {
+ if (<obj is ok>) {
+ if (<need new object>) {
+ *ptr = <ptr to new allocated object>;
+ return SWIG_NEWOBJ;
+ } else {
+ *ptr = <ptr to old object>;
+ return SWIG_OLDOBJ;
+ }
+ } else {
+ return SWIG_BADOBJ;
+ }
+ }
+
+ Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
+ more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
+ SWIG errors code.
+
+ Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
+ allows returning the 'cast rank', for example, if you have this
+
+ int food(double)
+ int fooi(int);
+
+ and you call
+
+ food(1) // cast rank '1' (1 -> 1.0)
+ fooi(1) // cast rank '0'
+
+ just use the SWIG_AddCast()/SWIG_CheckState()
+*/
+
+#define SWIG_OK (0)
+/* Runtime errors are < 0 */
+#define SWIG_ERROR (-1)
+/* Errors in range -1 to -99 are in swigerrors.swg (errors for all languages including those not using the runtime) */
+/* Errors in range -100 to -199 are language specific errors defined in *errors.swg */
+/* Errors < -200 are generic runtime specific errors */
+#define SWIG_ERROR_RELEASE_NOT_OWNED (-200)
+
+#define SWIG_IsOK(r) (r >= 0)
+#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError)
+
+/* The CastRankLimit says how many bits are used for the cast rank */
+#define SWIG_CASTRANKLIMIT (1 << 8)
+/* The NewMask denotes the object was created (using new/malloc) */
+#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1)
+/* The TmpMask is for in/out typemaps that use temporary objects */
+#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1)
+/* Simple returning values */
+#define SWIG_BADOBJ (SWIG_ERROR)
+#define SWIG_OLDOBJ (SWIG_OK)
+#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK)
+#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK)
+/* Check, add and del object mask methods */
+#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
+#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
+#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
+#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
+#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
+#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
+
+/* Cast-Rank Mode */
+#if defined(SWIG_CASTRANK_MODE)
+# ifndef SWIG_TypeRank
+# define SWIG_TypeRank unsigned long
+# endif
+# ifndef SWIG_MAXCASTRANK /* Default cast allowed */
+# define SWIG_MAXCASTRANK (2)
+# endif
+# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1)
+# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK)
+SWIGINTERNINLINE int SWIG_AddCast(int r) {
+ return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
+}
+SWIGINTERNINLINE int SWIG_CheckState(int r) {
+ return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0;
+}
+#else /* no cast-rank mode */
+# define SWIG_AddCast(r) (r)
+# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
+#endif
+
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *(*swig_converter_func)(void *, int *);
+typedef struct swig_type_info *(*swig_dycast_func)(void **);
+
+/* Structure to store information on one type */
+typedef struct swig_type_info {
+ const char *name; /* mangled name of this type */
+ const char *str; /* human readable name of this type */
+ swig_dycast_func dcast; /* dynamic cast function down a hierarchy */
+ struct swig_cast_info *cast; /* linked list of types that can cast into this type */
+ void *clientdata; /* language specific type data */
+ int owndata; /* flag if the structure owns the clientdata */
+} swig_type_info;
+
+/* Structure to store a type and conversion function used for casting */
+typedef struct swig_cast_info {
+ swig_type_info *type; /* pointer to type that is equivalent to this type */
+ swig_converter_func converter; /* function to cast the void pointers */
+ struct swig_cast_info *next; /* pointer to next cast in linked list */
+ struct swig_cast_info *prev; /* pointer to the previous cast */
+} swig_cast_info;
+
+/* Structure used to store module information
+ * Each module generates one structure like this, and the runtime collects
+ * all of these structures and stores them in a circularly linked list.*/
+typedef struct swig_module_info {
+ swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */
+ size_t size; /* Number of types in this module */
+ struct swig_module_info *next; /* Pointer to next element in circularly linked list */
+ swig_type_info **type_initial; /* Array of initially generated type structures */
+ swig_cast_info **cast_initial; /* Array of initially generated casting structures */
+ void *clientdata; /* Language specific module data */
+} swig_module_info;
+
+/*
+ Compare two type names skipping the space characters, therefore
+ "char*" == "char *" and "Class<int>" == "Class<int >", etc.
+
+ Return 0 when the two name types are equivalent, as in
+ strncmp, but skipping ' '.
+*/
+SWIGRUNTIME int
+SWIG_TypeNameComp(const char *f1, const char *l1,
+ const char *f2, const char *l2) {
+ for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
+ while ((*f1 == ' ') && (f1 != l1)) ++f1;
+ while ((*f2 == ' ') && (f2 != l2)) ++f2;
+ if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
+ }
+ return (int)((l1 - f1) - (l2 - f2));
+}
+
+/*
+ Check type equivalence in a name list like <name1>|<name2>|...
+ Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+*/
+SWIGRUNTIME int
+SWIG_TypeCmp(const char *nb, const char *tb) {
+ int equiv = 1;
+ const char* te = tb + strlen(tb);
+ const char* ne = nb;
+ while (equiv != 0 && *ne) {
+ for (nb = ne; *ne; ++ne) {
+ if (*ne == '|') break;
+ }
+ equiv = SWIG_TypeNameComp(nb, ne, tb, te);
+ if (*ne) ++ne;
+ }
+ return equiv;
+}
+
+/*
+ Check type equivalence in a name list like <name1>|<name2>|...
+ Return 0 if not equal, 1 if equal
+*/
+SWIGRUNTIME int
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+ return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0;
+}
+
+/*
+ Check the typename
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheck(const char *c, swig_type_info *ty) {
+ if (ty) {
+ swig_cast_info *iter = ty->cast;
+ while (iter) {
+ if (strcmp(iter->type->name, c) == 0) {
+ if (iter == ty->cast)
+ return iter;
+ /* Move iter to the top of the linked list */
+ iter->prev->next = iter->next;
+ if (iter->next)
+ iter->next->prev = iter->prev;
+ iter->next = ty->cast;
+ iter->prev = 0;
+ if (ty->cast) ty->cast->prev = iter;
+ ty->cast = iter;
+ return iter;
+ }
+ iter = iter->next;
+ }
+ }
+ return 0;
+}
+
+/*
+ Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheckStruct(const swig_type_info *from, swig_type_info *ty) {
+ if (ty) {
+ swig_cast_info *iter = ty->cast;
+ while (iter) {
+ if (iter->type == from) {
+ if (iter == ty->cast)
+ return iter;
+ /* Move iter to the top of the linked list */
+ iter->prev->next = iter->next;
+ if (iter->next)
+ iter->next->prev = iter->prev;
+ iter->next = ty->cast;
+ iter->prev = 0;
+ if (ty->cast) ty->cast->prev = iter;
+ ty->cast = iter;
+ return iter;
+ }
+ iter = iter->next;
+ }
+ }
+ return 0;
+}
+
+/*
+ Cast a pointer up an inheritance hierarchy
+*/
+SWIGRUNTIMEINLINE void *
+SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
+ return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
+}
+
+/*
+ Dynamic pointer casting. Down an inheritance hierarchy
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
+ swig_type_info *lastty = ty;
+ if (!ty || !ty->dcast) return ty;
+ while (ty && (ty->dcast)) {
+ ty = (*ty->dcast)(ptr);
+ if (ty) lastty = ty;
+ }
+ return lastty;
+}
+
+/*
+ Return the name associated with this type
+*/
+SWIGRUNTIMEINLINE const char *
+SWIG_TypeName(const swig_type_info *ty) {
+ return ty->name;
+}
+
+/*
+ Return the pretty name associated with this type,
+ that is an unmangled type name in a form presentable to the user.
+*/
+SWIGRUNTIME const char *
+SWIG_TypePrettyName(const swig_type_info *type) {
+ /* The "str" field contains the equivalent pretty names of the
+ type, separated by vertical-bar characters. Choose the last
+ name. It should be the most specific; a fully resolved name
+ but not necessarily with default template parameters expanded. */
+ if (!type) return NULL;
+ if (type->str != NULL) {
+ const char *last_name = type->str;
+ const char *s;
+ for (s = type->str; *s; s++)
+ if (*s == '|') last_name = s+1;
+ return last_name;
+ }
+ else
+ return type->name;
+}
+
+/*
+ Set the clientdata field for a type
+*/
+SWIGRUNTIME void
+SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
+ swig_cast_info *cast = ti->cast;
+ /* if (ti->clientdata == clientdata) return; */
+ ti->clientdata = clientdata;
+
+ while (cast) {
+ if (!cast->converter) {
+ swig_type_info *tc = cast->type;
+ if (!tc->clientdata) {
+ SWIG_TypeClientData(tc, clientdata);
+ }
+ }
+ cast = cast->next;
+ }
+}
+SWIGRUNTIME void
+SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
+ SWIG_TypeClientData(ti, clientdata);
+ ti->owndata = 1;
+}
+
+/*
+ Search for a swig_type_info structure only by mangled name
+ Search is a O(log #types)
+
+ We start searching at module start, and finish searching when start == end.
+ Note: if start == end at the beginning of the function, we go all the way around
+ the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_MangledTypeQueryModule(swig_module_info *start,
+ swig_module_info *end,
+ const char *name) {
+ swig_module_info *iter = start;
+ do {
+ if (iter->size) {
+ size_t l = 0;
+ size_t r = iter->size - 1;
+ do {
+ /* since l+r >= 0, we can (>> 1) instead (/ 2) */
+ size_t i = (l + r) >> 1;
+ const char *iname = iter->types[i]->name;
+ if (iname) {
+ int compare = strcmp(name, iname);
+ if (compare == 0) {
+ return iter->types[i];
+ } else if (compare < 0) {
+ if (i) {
+ r = i - 1;
+ } else {
+ break;
+ }
+ } else if (compare > 0) {
+ l = i + 1;
+ }
+ } else {
+ break; /* should never happen */
+ }
+ } while (l <= r);
+ }
+ iter = iter->next;
+ } while (iter != end);
+ return 0;
+}
+
+/*
+ Search for a swig_type_info structure for either a mangled name or a human readable name.
+ It first searches the mangled names of the types, which is a O(log #types)
+ If a type is not found it then searches the human readable names, which is O(#types).
+
+ We start searching at module start, and finish searching when start == end.
+ Note: if start == end at the beginning of the function, we go all the way around
+ the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeQueryModule(swig_module_info *start,
+ swig_module_info *end,
+ const char *name) {
+ /* STEP 1: Search the name field using binary search */
+ swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
+ if (ret) {
+ return ret;
+ } else {
+ /* STEP 2: If the type hasn't been found, do a complete search
+ of the str field (the human readable name) */
+ swig_module_info *iter = start;
+ do {
+ size_t i = 0;
+ for (; i < iter->size; ++i) {
+ if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
+ return iter->types[i];
+ }
+ iter = iter->next;
+ } while (iter != end);
+ }
+
+ /* neither found a match */
+ return 0;
+}
+
+/*
+ Pack binary data into a string
+*/
+SWIGRUNTIME char *
+SWIG_PackData(char *c, void *ptr, size_t sz) {
+ static const char hex[17] = "0123456789abcdef";
+ const unsigned char *u = (unsigned char *) ptr;
+ const unsigned char *eu = u + sz;
+ for (; u != eu; ++u) {
+ unsigned char uu = *u;
+ *(c++) = hex[(uu & 0xf0) >> 4];
+ *(c++) = hex[uu & 0xf];
+ }
+ return c;
+}
+
+/*
+ Unpack binary data from a string
+*/
+SWIGRUNTIME const char *
+SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
+ unsigned char *u = (unsigned char *) ptr;
+ const unsigned char *eu = u + sz;
+ for (; u != eu; ++u) {
+ char d = *(c++);
+ unsigned char uu;
+ if ((d >= '0') && (d <= '9'))
+ uu = (unsigned char)((d - '0') << 4);
+ else if ((d >= 'a') && (d <= 'f'))
+ uu = (unsigned char)((d - ('a'-10)) << 4);
+ else
+ return (char *) 0;
+ d = *(c++);
+ if ((d >= '0') && (d <= '9'))
+ uu |= (unsigned char)(d - '0');
+ else if ((d >= 'a') && (d <= 'f'))
+ uu |= (unsigned char)(d - ('a'-10));
+ else
+ return (char *) 0;
+ *u = uu;
+ }
+ return c;
+}
+
+/*
+ Pack 'void *' into a string buffer.
+*/
+SWIGRUNTIME char *
+SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
+ char *r = buff;
+ if ((2*sizeof(void *) + 2) > bsz) return 0;
+ *(r++) = '_';
+ r = SWIG_PackData(r,&ptr,sizeof(void *));
+ if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
+ strcpy(r,name);
+ return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
+ if (*c != '_') {
+ if (strcmp(c,"NULL") == 0) {
+ *ptr = (void *) 0;
+ return name;
+ } else {
+ return 0;
+ }
+ }
+ return SWIG_UnpackData(++c,ptr,sizeof(void *));
+}
+
+SWIGRUNTIME char *
+SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
+ char *r = buff;
+ size_t lname = (name ? strlen(name) : 0);
+ if ((2*sz + 2 + lname) > bsz) return 0;
+ *(r++) = '_';
+ r = SWIG_PackData(r,ptr,sz);
+ if (lname) {
+ strncpy(r,name,lname+1);
+ } else {
+ *r = 0;
+ }
+ return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
+ if (*c != '_') {
+ if (strcmp(c,"NULL") == 0) {
+ memset(ptr,0,sz);
+ return name;
+ } else {
+ return 0;
+ }
+ }
+ return SWIG_UnpackData(++c,ptr,sz);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/tools/swig/Lib/swigwarn.swg b/contrib/tools/swig/Lib/swigwarn.swg
new file mode 100644
index 00000000000..0320db8f70d
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigwarn.swg
@@ -0,0 +1,315 @@
+/* SWIG warning codes - generated from swigwarn.h - do not edit */
+
+
+%define SWIGWARN_NONE 0 %enddef
+
+/* -- Deprecated features -- */
+
+/* Unused since 4.2.0: #define WARN_DEPRECATED_EXTERN 101 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_VAL 102 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_OUT 103 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_DISABLEDOC 104 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_ENABLEDOC 105 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_DOCONLY 106 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_STYLE 107 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_LOCALSTYLE 108 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_TITLE 109 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_SECTION 110 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_SUBSECTION 111 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_SUBSUBSECTION 112 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_ADDMETHODS 113 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_READONLY 114 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_READWRITE 115 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_EXCEPT 116 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NEW 117 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_EXCEPT_TM 118 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_IGNORE_TM 119 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_OPTC 120 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NAME 121 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NOEXTERN 122 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NODEFAULT 123 */
+/* Unused since 4.1.0: #define WARN_DEPRECATED_TYPEMAP_LANG 124 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_INPUT_FILE 125 */
+/* Unused since 4.3.0: #define WARN_DEPRECATED_NESTED_WORKAROUND 126 */
+
+/* -- Preprocessor -- */
+
+%define SWIGWARN_PP_MISSING_FILE 201 %enddef
+%define SWIGWARN_PP_EVALUATION 202 %enddef
+%define SWIGWARN_PP_INCLUDEALL_IMPORTALL 203 %enddef
+%define SWIGWARN_PP_CPP_WARNING 204 %enddef
+%define SWIGWARN_PP_CPP_ERROR 205 %enddef
+%define SWIGWARN_PP_UNEXPECTED_TOKENS 206 %enddef
+
+/* -- C/C++ Parser -- */
+
+%define SWIGWARN_PARSE_CLASS_KEYWORD 301 %enddef
+%define SWIGWARN_PARSE_REDEFINED 302 %enddef
+%define SWIGWARN_PARSE_EXTEND_UNDEF 303 %enddef
+%define SWIGWARN_PARSE_UNSUPPORTED_VALUE 304 %enddef
+%define SWIGWARN_PARSE_BAD_VALUE 305 %enddef
+/* Unused since 1.3.32: #define WARN_PARSE_PRIVATE 306 */
+/* Unused since 4.2.0: #define WARN_PARSE_BAD_DEFAULT 307 */
+%define SWIGWARN_PARSE_NAMESPACE_ALIAS 308 %enddef
+%define SWIGWARN_PARSE_PRIVATE_INHERIT 309 %enddef
+/* Unused since 1.3.18: #define WARN_PARSE_TEMPLATE_REPEAT 310 */
+/* Unused since 1.3.18: #define WARN_PARSE_TEMPLATE_PARTIAL 311 */
+%define SWIGWARN_PARSE_UNNAMED_NESTED_CLASS 312 %enddef
+%define SWIGWARN_PARSE_UNDEFINED_EXTERN 313 %enddef
+%define SWIGWARN_PARSE_KEYWORD 314 %enddef
+%define SWIGWARN_PARSE_USING_UNDEF 315 %enddef
+/* Unused since 1.3.18: #define WARN_PARSE_MODULE_REPEAT 316 */
+%define SWIGWARN_PARSE_TEMPLATE_SP_UNDEF 317 %enddef
+%define SWIGWARN_PARSE_TEMPLATE_AMBIG 318 %enddef
+%define SWIGWARN_PARSE_NO_ACCESS 319 %enddef
+%define SWIGWARN_PARSE_EXPLICIT_TEMPLATE 320 %enddef
+%define SWIGWARN_PARSE_BUILTIN_NAME 321 %enddef
+%define SWIGWARN_PARSE_REDUNDANT 322 %enddef
+%define SWIGWARN_PARSE_REC_INHERITANCE 323 %enddef
+%define SWIGWARN_PARSE_NESTED_TEMPLATE 324 %enddef
+%define SWIGWARN_PARSE_NAMED_NESTED_CLASS 325 %enddef
+%define SWIGWARN_PARSE_EXTEND_NAME 326 %enddef
+%define SWIGWARN_PARSE_EXTERN_TEMPLATE 327 %enddef
+%define SWIGWARN_PARSE_ASSIGNED_VALUE 328 %enddef
+%define SWIGWARN_PARSE_USING_CONSTRUCTOR 329 %enddef
+%define SWIGWARN_PARSE_TEMPLATE_FORWARD 330 %enddef
+%define SWIGWARN_PARSE_TEMPLATE_NESTED 331 %enddef
+
+%define SWIGWARN_CPP11_LAMBDA 340 %enddef
+/* Unused since 3.0.11: #define WARN_CPP11_ALIAS_DECLARATION 341 */
+/* Unused since 3.0.11: #define WARN_CPP11_ALIAS_TEMPLATE 342 */
+/* Unused since 4.2.0: #define WARN_CPP11_VARIADIC_TEMPLATE 343 */
+%define SWIGWARN_CPP11_DECLTYPE 344 %enddef
+%define SWIGWARN_CPP14_AUTO 345 %enddef
+%define SWIGWARN_CPP11_AUTO 346 %enddef
+
+%define SWIGWARN_IGNORE_OPERATOR_NEW 350 %enddef /* new */
+%define SWIGWARN_IGNORE_OPERATOR_DELETE 351 %enddef /* delete */
+%define SWIGWARN_IGNORE_OPERATOR_PLUS 352 %enddef /* + */
+%define SWIGWARN_IGNORE_OPERATOR_MINUS 353 %enddef /* - */
+%define SWIGWARN_IGNORE_OPERATOR_MUL 354 %enddef /* * */
+%define SWIGWARN_IGNORE_OPERATOR_DIV 355 %enddef /* / */
+%define SWIGWARN_IGNORE_OPERATOR_MOD 356 %enddef /* % */
+%define SWIGWARN_IGNORE_OPERATOR_XOR 357 %enddef /* ^ */
+%define SWIGWARN_IGNORE_OPERATOR_AND 358 %enddef /* & */
+%define SWIGWARN_IGNORE_OPERATOR_OR 359 %enddef /* | */
+%define SWIGWARN_IGNORE_OPERATOR_NOT 360 %enddef /* ~ */
+%define SWIGWARN_IGNORE_OPERATOR_LNOT 361 %enddef /* ! */
+%define SWIGWARN_IGNORE_OPERATOR_EQ 362 %enddef /* = */
+%define SWIGWARN_IGNORE_OPERATOR_LT 363 %enddef /* < */
+%define SWIGWARN_IGNORE_OPERATOR_GT 364 %enddef /* > */
+%define SWIGWARN_IGNORE_OPERATOR_PLUSEQ 365 %enddef /* += */
+%define SWIGWARN_IGNORE_OPERATOR_MINUSEQ 366 %enddef /* -= */
+%define SWIGWARN_IGNORE_OPERATOR_MULEQ 367 %enddef /* *= */
+%define SWIGWARN_IGNORE_OPERATOR_DIVEQ 368 %enddef /* /= */
+%define SWIGWARN_IGNORE_OPERATOR_MODEQ 369 %enddef /* %= */
+%define SWIGWARN_IGNORE_OPERATOR_XOREQ 370 %enddef /* ^= */
+%define SWIGWARN_IGNORE_OPERATOR_ANDEQ 371 %enddef /* &= */
+%define SWIGWARN_IGNORE_OPERATOR_OREQ 372 %enddef /* |= */
+%define SWIGWARN_IGNORE_OPERATOR_LSHIFT 373 %enddef /* << */
+%define SWIGWARN_IGNORE_OPERATOR_RSHIFT 374 %enddef /* >> */
+%define SWIGWARN_IGNORE_OPERATOR_LSHIFTEQ 375 %enddef /* <<= */
+%define SWIGWARN_IGNORE_OPERATOR_RSHIFTEQ 376 %enddef /* >>= */
+%define SWIGWARN_IGNORE_OPERATOR_EQUALTO 377 %enddef /* == */
+%define SWIGWARN_IGNORE_OPERATOR_NOTEQUAL 378 %enddef /* != */
+%define SWIGWARN_IGNORE_OPERATOR_LTEQUAL 379 %enddef /* <= */
+%define SWIGWARN_IGNORE_OPERATOR_GTEQUAL 380 %enddef /* >= */
+%define SWIGWARN_IGNORE_OPERATOR_LAND 381 %enddef /* && */
+%define SWIGWARN_IGNORE_OPERATOR_LOR 382 %enddef /* || */
+%define SWIGWARN_IGNORE_OPERATOR_PLUSPLUS 383 %enddef /* ++ */
+%define SWIGWARN_IGNORE_OPERATOR_MINUSMINUS 384 %enddef /* -- */
+%define SWIGWARN_IGNORE_OPERATOR_COMMA 385 %enddef /* , */
+%define SWIGWARN_IGNORE_OPERATOR_ARROWSTAR 386 %enddef /* ->* */
+%define SWIGWARN_IGNORE_OPERATOR_ARROW 387 %enddef /* -> */
+%define SWIGWARN_IGNORE_OPERATOR_CALL 388 %enddef /* () */
+%define SWIGWARN_IGNORE_OPERATOR_INDEX 389 %enddef /* [] */
+%define SWIGWARN_IGNORE_OPERATOR_UPLUS 390 %enddef /* + */
+%define SWIGWARN_IGNORE_OPERATOR_UMINUS 391 %enddef /* - */
+%define SWIGWARN_IGNORE_OPERATOR_UMUL 392 %enddef /* * */
+%define SWIGWARN_IGNORE_OPERATOR_UAND 393 %enddef /* & */
+%define SWIGWARN_IGNORE_OPERATOR_NEWARR 394 %enddef /* new [] */
+%define SWIGWARN_IGNORE_OPERATOR_DELARR 395 %enddef /* delete [] */
+%define SWIGWARN_IGNORE_OPERATOR_REF 396 %enddef /* operator *() */
+%define SWIGWARN_IGNORE_OPERATOR_LTEQUALGT 397 %enddef /* <=> */
+
+/* please leave 350-399 free for WARN_IGNORE_OPERATOR_* */
+
+/* -- Type system and typemaps -- */
+
+%define SWIGWARN_TYPE_UNDEFINED_CLASS 401 %enddef
+%define SWIGWARN_TYPE_INCOMPLETE 402 %enddef
+%define SWIGWARN_TYPE_ABSTRACT 403 %enddef
+%define SWIGWARN_TYPE_REDEFINED 404 %enddef
+%define SWIGWARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405 %enddef
+%define SWIGWARN_TYPE_NSPACE_SETTING 406 %enddef
+
+/* Unused since 4.1.0: #define WARN_TYPEMAP_SOURCETARGET 450 */
+%define SWIGWARN_TYPEMAP_CHARLEAK 451 %enddef
+/* Unused since 1.3.32: #define WARN_TYPEMAP_SWIGTYPE 452 */
+%define SWIGWARN_TYPEMAP_APPLY_UNDEF 453 %enddef
+%define SWIGWARN_TYPEMAP_SWIGTYPELEAK 454 %enddef
+%define SWIGWARN_TYPEMAP_WCHARLEAK 455 %enddef
+
+%define SWIGWARN_TYPEMAP_IN_UNDEF 460 %enddef
+%define SWIGWARN_TYPEMAP_OUT_UNDEF 461 %enddef
+%define SWIGWARN_TYPEMAP_VARIN_UNDEF 462 %enddef
+%define SWIGWARN_TYPEMAP_VAROUT_UNDEF 463 %enddef
+%define SWIGWARN_TYPEMAP_CONST_UNDEF 464 %enddef
+%define SWIGWARN_TYPEMAP_UNDEF 465 %enddef
+%define SWIGWARN_TYPEMAP_VAR_UNDEF 466 %enddef
+%define SWIGWARN_TYPEMAP_TYPECHECK 467 %enddef
+%define SWIGWARN_TYPEMAP_THROW 468 %enddef
+%define SWIGWARN_TYPEMAP_DIRECTORIN_UNDEF 469 %enddef
+%define SWIGWARN_TYPEMAP_THREAD_UNSAFE 470 %enddef /* mostly used in directorout typemaps */
+%define SWIGWARN_TYPEMAP_DIRECTOROUT_UNDEF 471 %enddef
+%define SWIGWARN_TYPEMAP_TYPECHECK_UNDEF 472 %enddef
+%define SWIGWARN_TYPEMAP_DIRECTOROUT_PTR 473 %enddef
+%define SWIGWARN_TYPEMAP_OUT_OPTIMAL_IGNORED 474 %enddef
+%define SWIGWARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE 475 %enddef
+%define SWIGWARN_TYPEMAP_INITIALIZER_LIST 476 %enddef
+%define SWIGWARN_TYPEMAP_DIRECTORTHROWS_UNDEF 477 %enddef
+
+/* -- Fragments -- */
+%define SWIGWARN_FRAGMENT_NOT_FOUND 490 %enddef
+
+/* -- General code generation -- */
+
+%define SWIGWARN_LANG_OVERLOAD_DECL 501 %enddef
+%define SWIGWARN_LANG_OVERLOAD_CONSTRUCT 502 %enddef
+%define SWIGWARN_LANG_IDENTIFIER 503 %enddef
+%define SWIGWARN_LANG_RETURN_TYPE 504 %enddef
+%define SWIGWARN_LANG_VARARGS 505 %enddef
+%define SWIGWARN_LANG_VARARGS_KEYWORD 506 %enddef
+%define SWIGWARN_LANG_NATIVE_UNIMPL 507 %enddef
+%define SWIGWARN_LANG_DEREF_SHADOW 508 %enddef
+%define SWIGWARN_LANG_OVERLOAD_SHADOW 509 %enddef
+%define SWIGWARN_LANG_FRIEND_IGNORE 510 %enddef /* No longer issued */
+%define SWIGWARN_LANG_OVERLOAD_KEYWORD 511 %enddef
+%define SWIGWARN_LANG_OVERLOAD_CONST 512 %enddef
+%define SWIGWARN_LANG_CLASS_UNNAMED 513 %enddef
+%define SWIGWARN_LANG_DIRECTOR_VDESTRUCT 514 %enddef
+%define SWIGWARN_LANG_DISCARD_CONST 515 %enddef
+%define SWIGWARN_LANG_OVERLOAD_IGNORED 516 %enddef
+%define SWIGWARN_LANG_DIRECTOR_ABSTRACT 517 %enddef
+%define SWIGWARN_LANG_PORTABILITY_FILENAME 518 %enddef
+%define SWIGWARN_LANG_TEMPLATE_METHOD_IGNORE 519 %enddef
+%define SWIGWARN_LANG_SMARTPTR_MISSING 520 %enddef
+%define SWIGWARN_LANG_ILLEGAL_DESTRUCTOR 521 %enddef
+%define SWIGWARN_LANG_EXTEND_CONSTRUCTOR 522 %enddef
+%define SWIGWARN_LANG_EXTEND_DESTRUCTOR 523 %enddef
+%define SWIGWARN_LANG_EXPERIMENTAL 524 %enddef
+%define SWIGWARN_LANG_DIRECTOR_FINAL 525 %enddef
+%define SWIGWARN_LANG_USING_NAME_DIFFERENT 526 %enddef
+%define SWIGWARN_LANG_DEPRECATED 527 %enddef
+
+/* -- Doxygen comments -- */
+
+%define SWIGWARN_DOXYGEN_UNKNOWN_COMMAND 560 %enddef
+%define SWIGWARN_DOXYGEN_UNEXPECTED_END_OF_COMMENT 561 %enddef
+%define SWIGWARN_DOXYGEN_COMMAND_EXPECTED 562 %enddef
+%define SWIGWARN_DOXYGEN_HTML_ERROR 563 %enddef
+%define SWIGWARN_DOXYGEN_COMMAND_ERROR 564 %enddef
+%define SWIGWARN_DOXYGEN_UNKNOWN_CHARACTER 565 %enddef
+%define SWIGWARN_DOXYGEN_UNEXPECTED_ITERATOR_VALUE 566 %enddef
+
+/* -- Reserved (600-699) -- */
+
+/* -- Language module specific warnings (700 - 899) -- */
+
+
+%define SWIGWARN_D_TYPEMAP_CTYPE_UNDEF 700 %enddef
+%define SWIGWARN_D_TYPEMAP_IMTYPE_UNDEF 701 %enddef
+%define SWIGWARN_D_TYPEMAP_DTYPE_UNDEF 702 %enddef
+%define SWIGWARN_D_MULTIPLE_INHERITANCE 703 %enddef
+%define SWIGWARN_D_TYPEMAP_CLASSMOD_UNDEF 704 %enddef
+%define SWIGWARN_D_TYPEMAP_DBODY_UNDEF 705 %enddef
+%define SWIGWARN_D_TYPEMAP_DOUT_UNDEF 706 %enddef
+%define SWIGWARN_D_TYPEMAP_DIN_UNDEF 707 %enddef
+%define SWIGWARN_D_TYPEMAP_DDIRECTORIN_UNDEF 708 %enddef
+%define SWIGWARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF 709 %enddef
+%define SWIGWARN_D_EXCODE_MISSING 710 %enddef
+%define SWIGWARN_D_CANTHROW_MISSING 711 %enddef
+%define SWIGWARN_D_NO_DIRECTORCONNECT_ATTR 712 %enddef
+%define SWIGWARN_D_NAME_COLLISION 713 %enddef
+
+/* please leave 700-719 free for D */
+
+%define SWIGWARN_SCILAB_TRUNCATED_NAME 720 %enddef
+
+/* please leave 720-739 free for Scilab */
+
+%define SWIGWARN_PYTHON_INDENT_MISMATCH 740 %enddef
+
+/* please leave 740-749 free for Python */
+
+/* Unused since 4.2.0: #define WARN_R_MISSING_RTYPECHECK_TYPEMAP 750 */
+%define SWIGWARN_R_TYPEMAP_RTYPECHECK_UNDEF 751 %enddef
+
+/* please leave 750-759 free for R */
+
+%define SWIGWARN_C_TYPEMAP_CTYPE_UNDEF 760 %enddef
+%define SWIGWARN_C_UNSUPPORTTED 761 %enddef
+
+/* please leave 760-779 free for C */
+
+%define SWIGWARN_RUBY_WRONG_NAME 801 %enddef
+%define SWIGWARN_RUBY_MULTIPLE_INHERITANCE 802 %enddef
+
+/* please leave 800-809 free for Ruby */
+
+%define SWIGWARN_JAVA_TYPEMAP_JNI_UNDEF 810 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JTYPE_UNDEF 811 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JSTYPE_UNDEF 812 %enddef
+%define SWIGWARN_JAVA_MULTIPLE_INHERITANCE 813 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_GETCPTR_UNDEF 814 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_CLASSMOD_UNDEF 815 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JAVABODY_UNDEF 816 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JAVAOUT_UNDEF 817 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JAVAIN_UNDEF 818 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF 819 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JAVADIRECTOROUT_UNDEF 820 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF 821 %enddef
+%define SWIGWARN_JAVA_COVARIANT_RET 822 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF 823 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_DIRECTORIN_NODESC 824 %enddef
+%define SWIGWARN_JAVA_NO_DIRECTORCONNECT_ATTR 825 %enddef
+%define SWIGWARN_JAVA_NSPACE_WITHOUT_PACKAGE 826 %enddef
+%define SWIGWARN_JAVA_TYPEMAP_INTERFACEMODIFIERS_UNDEF 827 %enddef
+
+/* please leave 810-829 free for Java */
+
+%define SWIGWARN_CSHARP_TYPEMAP_CTYPE_UNDEF 830 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSTYPE_UNDEF 831 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF 832 %enddef
+%define SWIGWARN_CSHARP_MULTIPLE_INHERITANCE 833 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_GETCPTR_UNDEF 834 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF 835 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSBODY_UNDEF 836 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSOUT_UNDEF 837 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSIN_UNDEF 838 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF 839 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSDIRECTOROUT_UNDEF 840 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF 841 %enddef
+%define SWIGWARN_CSHARP_COVARIANT_RET 842 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF 843 %enddef
+%define SWIGWARN_CSHARP_EXCODE 844 %enddef
+%define SWIGWARN_CSHARP_CANTHROW 845 %enddef
+%define SWIGWARN_CSHARP_NO_DIRECTORCONNECT_ATTR 846 %enddef
+%define SWIGWARN_CSHARP_TYPEMAP_INTERFACEMODIFIERS_UNDEF 847 %enddef
+
+/* please leave 830-849 free for C# */
+
+/* 850-860 were used by Modula 3 (removed in SWIG 4.1.0) - avoid reusing for now */
+
+%define SWIGWARN_PHP_MULTIPLE_INHERITANCE 870 %enddef
+%define SWIGWARN_PHP_UNKNOWN_PRAGMA 871 %enddef
+/* Unused since 4.1.0: define WARN_PHP_PUBLIC_BASE 872 */
+
+/* please leave 870-889 free for PHP */
+
+%define SWIGWARN_GO_NAME_CONFLICT 890 %enddef
+
+/* please leave 890-899 free for Go */
+
+/* -- User defined warnings (900 - 999) -- */
+
diff --git a/contrib/tools/swig/Lib/swigwarnings.swg b/contrib/tools/swig/Lib/swigwarnings.swg
new file mode 100644
index 00000000000..2dfea660e98
--- /dev/null
+++ b/contrib/tools/swig/Lib/swigwarnings.swg
@@ -0,0 +1,131 @@
+/*
+ Include the internal swig macro codes. These macros correspond to
+ the one found in Source/Include/swigwarn.h plus the 'SWIG' prefix.
+
+ For example, in the include file 'swigwarn.h' you will find
+
+ #define WARN_TYPEMAP_CHARLEAK ...
+
+ and in the 'swigwarn.swg' interface, you will see
+
+ %define SWIGWARN_TYPEMAP_CHARLEAK ...
+
+ This code can be used in warning filters as follows:
+
+ %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK);
+
+ Warnings messages used in typemaps. Message names will be the same
+ as those in Lib/swigwarn.swg but with the suffix _MSG.
+
+ For example, for the code SWIGWARN_TYPEMAP_CHARLEAK, once you use
+
+ %typemapmsg(CHARLEAK,<msg>);
+
+ you use the message in your typemap as
+
+ %typemap(varin,warning=SWIGWARN_TYPEMAP_CHARLEAK_MSG) char *
+
+ while you suppress the warning using
+
+ %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK);
+
+ as described above.
+*/
+
+/* -----------------------------------------------------------------------------
+ * SWIG warning codes
+ * ----------------------------------------------------------------------------- */
+
+%include <swigwarn.swg>
+
+/* -----------------------------------------------------------------------------
+ * Auxiliary macros
+ * ----------------------------------------------------------------------------- */
+
+/* Macro to define warning messages */
+#define %_warningmsg(Val, Msg...) `Val`":"Msg
+#define %warningmsg(Val, Msg...) %_warningmsg(Val, Msg)
+
+/* -----------------------------------------------------------------------------
+ * Typemap related warning messages
+ * ----------------------------------------------------------------------------- */
+
+%define SWIGWARN_TYPEMAP_CHARLEAK_MSG "451:Setting a const char * variable may leak memory." %enddef
+%define SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG "454:Setting a pointer/reference variable may leak memory." %enddef
+%define SWIGWARN_TYPEMAP_WCHARLEAK_MSG "455:Setting a const wchar_t * variable may leak memory." %enddef
+%define SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG "470:Thread/reentrant unsafe wrapping, consider returning by value instead." %enddef
+%define SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG "473:Returning a reference, pointer or pointer wrapper in a director method is not recommended." %enddef
+%define SWIGWARN_TYPEMAP_INITIALIZER_LIST_MSG "476:Initialization using std::initializer_list." %enddef
+
+/* -----------------------------------------------------------------------------
+ * Operator related warning messages
+ * ----------------------------------------------------------------------------- */
+
+%define SWIGWARN_IGNORE_OPERATOR_NEW_MSG "350:operator new ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_DELETE_MSG "351:operator delete ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_PLUS_MSG "352:operator+ ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MINUS_MSG "353:operator- ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MUL_MSG "354:operator* ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_DIV_MSG "355:operator/ ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MOD_MSG "356:operator% ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_XOR_MSG "357:operator^ ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_AND_MSG "358:operator& ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_OR_MSG "359:operator| ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_NOT_MSG "360:operator~ ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LNOT_MSG "361:operator! ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_EQ_MSG "362:operator= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LT_MSG "363:operator< ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_GT_MSG "364:operator> ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_PLUSEQ_MSG "365:operator+= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MINUSEQ_MSG "366:operator-= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MULEQ_MSG "367:operator*= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_DIVEQ_MSG "368:operator/= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MODEQ_MSG "369:operator%= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_XOREQ_MSG "370:operator^= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_ANDEQ_MSG "371:operator&= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_OREQ_MSG "372:operator|= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LSHIFT_MSG "373:operator<< ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_RSHIFT_MSG "374:operator>> ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LSHIFTEQ_MSG "375:operator<<= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_RSHIFTEQ_MSG "376:operator>>= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_EQUALTO_MSG "377:operator== ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_NOTEQUAL_MSG "378:operator!= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LTEQUAL_MSG "379:operator<= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_GTEQUAL_MSG "380:operator>= ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LAND_MSG "381:operator&& ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LOR_MSG "382:operator|| ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_PLUSPLUS_MSG "383:operator++ ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_MINUSMINUS_MSG "384:operator-- ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_COMMA_MSG "385:operator-- ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_ARROWSTAR_MSG "386:operator->* ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_ARROW_MSG "387:operator-> ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_CALL_MSG "388:operator() ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_INDEX_MSG "389:operator[] ignored (consider using %%extend)" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_UPLUS_MSG "390:operator+ ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_UMINUS_MSG "391:operator- ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_UMUL_MSG "392:operator* ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_UAND_MSG "393:operator& ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_NEWARR_MSG "394:operator new[] ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_DELARR_MSG "395:operator delete[] ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_REF_MSG "396:operator*() ignored" %enddef
+%define SWIGWARN_IGNORE_OPERATOR_LTEQUALGT_MSG "397:operator<=> ignored" %enddef
+
+#define %ignoreoperator(Oper) %ignorewarn(SWIGWARN_IGNORE_OPERATOR_##Oper##_MSG)
+
+/* -----------------------------------------------------------------------------
+ * Macros for keyword and built-in names
+ * ----------------------------------------------------------------------------- */
+
+#define %keywordwarn(msg...) %namewarn(%warningmsg(SWIGWARN_PARSE_KEYWORD, msg))
+#define %builtinwarn(msg...) %namewarn(%warningmsg(SWIGWARN_PARSE_BUILTIN_NAME, msg), %$isfunction)
+
+
+/* -----------------------------------------------------------------------------
+ * Warning filter feature
+ * ----------------------------------------------------------------------------- */
+
+#define %_warnfilter(filter...) %feature("warnfilter",`filter`)
+#define %warnfilter(filter...) %_warnfilter(filter)
+
+
+
diff --git a/contrib/tools/swig/Lib/typemaps/README b/contrib/tools/swig/Lib/typemaps/README
new file mode 100644
index 00000000000..65134578d35
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/README
@@ -0,0 +1,54 @@
+Still in development, but if you are interested into looking around,
+start with
+
+
+ swigtypemaps.swg
+
+which is the head file. Also read the docs for %fragments in
+
+ fragments.swg
+
+and follow the definitions in one of the supported languages:
+
+ python, perl, ruby, tcl
+
+
+
+
+/* -----------------------------------------------------------------------------
+ * Internal typemap specializations
+ * ----------------------------------------------------------------------------- */
+
+
+carrays.swg Implement the carrays.i library
+cdata.swg Implement the cdata.i library
+cmalloc.swg Implement the cmalloc.i library
+cpointer.swg Implement the cpointer.i library
+cstring.swg Implement the cstring.i library typemaps for char *
+cwstring.swg Implement the cstring.i library typemaps for wchar_t *
+exception.swg Implement the exception.i library
+implicit.swg Allow the use of implicit C++ constructors
+
+string.swg Typemaps for char * string
+wstring.swg Typemaps for wchar_t * string
+std_string.swg Typemaps for std::string
+std_wstring.swg Typemaps for std::wstring
+swigtype.swg Typemaps for the SWIGTYPE type
+void.swg Typemaps for the 'void' type
+enumint.swg Typemaps for enums treated as 'int'
+swigobject.swg Typemaps for the SWIG_Object as in PyObject, Tcl_Obj, etc.
+misctypes.swg Typemaps for miscellaneos types (size_t, ptrdiff_t, etc)
+ptrtypes.swg Typemaps for types with a 'ptr' behavior
+valtypes.swg Typemaps for 'by value' types
+inoutlist.swg IN/OUTPUT/INOUT typemaps, where the OUTPUT values are returned in a list
+primtypes.swg Common macros to manage primitive types (short,int,double,etc)
+
+cstrings.swg Common macros to implemented the cstring/cwstring libraries
+std_strings.swg Common macros to implemented the std::string/std::wstring typemaps
+strings.swg Common macros and typemaps for string and wstring (char *, wchar_t *)
+
+swigmacros.swg Basic macros
+fragments.swg Macros for fragment manipulations
+
+
+typemaps.swg The old typemaps.i library, not needed anymore
diff --git a/contrib/tools/swig/Lib/typemaps/attribute.swg b/contrib/tools/swig/Lib/typemaps/attribute.swg
new file mode 100644
index 00000000000..abdf44dfdc7
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/attribute.swg
@@ -0,0 +1,150 @@
+/* -----------------------------------------------------------------------------
+ * attribute.swg
+ *
+ * Attribute implementation
+ * ----------------------------------------------------------------------------- */
+
+/*
+ The following macros convert a pair of set/get methods
+ into a "native" attribute.
+*/
+
+//
+// Define SWIG_ATTRIBUTE_TEMPLATE if you want to use templates instead of macros for the C++ get and set wrapper methods
+// Does not always generate compilable code, use at your peril!
+//
+//#define SWIG_ATTRIBUTE_TEMPLATE
+
+%define %attribute_custom(Class, AttributeType, AttributeName, GetMethod, SetMethod, GetMethodCall, SetMethodCall)
+ %ignore Class::GetMethod();
+ %ignore Class::GetMethod() const;
+ #if #SetMethod != #AttributeName
+ %ignore Class::SetMethod;
+ #endif
+ %extend Class {
+ AttributeType AttributeName;
+ }
+#if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE)
+ %{
+ template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(const C* self_) {
+ return GetMethodCall;
+ }
+ template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(C* self_) {
+ return GetMethodCall;
+ }
+ template < class C > inline void %mangle(Class) ##_## AttributeName ## _set(C* self_, AttributeType val_) {
+ SetMethodCall;
+ }
+ %}
+#else
+ %{
+ #define %mangle(Class) ##_## AttributeName ## _get(self_) GetMethodCall
+ #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) SetMethodCall
+ %}
+#endif
+%enddef
+
+%define %attribute_readonly(Class, AttributeType, AttributeName, GetMethod, GetMethodCall)
+ %ignore Class::GetMethod();
+ %ignore Class::GetMethod() const;
+ %immutable Class::AttributeName;
+ %extend Class {
+ AttributeType AttributeName;
+ }
+#if defined(__cplusplus) && defined(SWIG_ATTRIBUTE_TEMPLATE)
+ %{
+ template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(const C* self_) {
+ return GetMethodCall;
+ }
+ template < class C > inline AttributeType %mangle(Class) ##_## AttributeName ## _get(C* self_) {
+ return GetMethodCall;
+ }
+ %}
+#else
+ %{
+ #define %mangle(Class) ##_## AttributeName ## _get(self_) GetMethodCall
+ %}
+#endif
+%enddef
+
+
+// User macros
+
+%define %attribute(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
+ #if #SetMethod != ""
+ %attribute_custom(%arg(Class), %arg(AttributeType), AttributeName, GetMethod, SetMethod, self_->GetMethod(), self_->SetMethod(val_))
+ #else
+ %attribute_readonly(%arg(Class), %arg(AttributeType), AttributeName, GetMethod, self_->GetMethod())
+ #endif
+%enddef
+
+%define %attribute2(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
+ #if #SetMethod != ""
+ %attribute_custom(%arg(Class), %arg(AttributeType), AttributeName, GetMethod, SetMethod, &self_->GetMethod(), self_->SetMethod(*val_))
+ #else
+ %attribute_readonly(%arg(Class), %arg(AttributeType), AttributeName, GetMethod, &self_->GetMethod())
+ #endif
+%enddef
+
+%define %attributeref(Class, AttributeType, AttributeName, AccessorMethod...)
+ #if #AccessorMethod != ""
+ %attribute_custom(%arg(Class), %arg(AttributeType), AttributeName, AccessorMethod, AccessorMethod, self_->AccessorMethod(), self_->AccessorMethod() = val_)
+ #else
+ %attribute_custom(%arg(Class), %arg(AttributeType), AttributeName, AttributeName, AttributeName, self_->AttributeName(), self_->AttributeName() = val_)
+ #endif
+%enddef
+
+%define %attribute2ref(Class, AttributeType, AttributeName, AccessorMethod...)
+ #if #AccessorMethod != ""
+ %attribute_custom(%arg(Class), %arg(AttributeType), AttributeName, AccessorMethod, AccessorMethod, &self_->AccessorMethod(), self_->AccessorMethod() = *val_)
+ #else
+ %attribute_custom(%arg(Class), %arg(AttributeType), AttributeName, AttributeName, AttributeName, &self_->AttributeName(), self_->AttributeName() = *val_)
+ #endif
+%enddef
+
+%define %attributeval(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
+ %{
+ #define %mangle(Class) ##_## AttributeName ## _get(self_) new AttributeType(self_->GetMethod())
+ %}
+ #if #SetMethod != ""
+ %{
+ #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) self_->SetMethod(*val_)
+ %}
+ #if #SetMethod != #AttributeName
+ %ignore Class::SetMethod;
+ #endif
+ #else
+ %immutable Class::AttributeName;
+ #endif
+ %ignore Class::GetMethod();
+ %ignore Class::GetMethod() const;
+ %newobject Class::AttributeName;
+ %extend Class {
+ AttributeType AttributeName;
+ }
+%enddef
+
+
+%define %attributestring(Class, AttributeType, AttributeName, GetMethod, SetMethod...)
+ %{
+ #define %mangle(Class) ##_## AttributeName ## _get(self_) *new AttributeType(self_->GetMethod())
+ %}
+ #if #SetMethod != ""
+ %{
+ #define %mangle(Class) ##_## AttributeName ## _set(self_, val_) self_->SetMethod(val_)
+ %}
+ #if #SetMethod != #AttributeName
+ %ignore Class::SetMethod;
+ #endif
+ #else
+ %immutable Class::AttributeName;
+ #endif
+ %ignore Class::GetMethod();
+ %ignore Class::GetMethod() const;
+ %newobject Class::AttributeName;
+ %typemap(newfree) const AttributeType &AttributeName "delete $1;"
+ %extend Class {
+ AttributeType AttributeName;
+ }
+%enddef
+
diff --git a/contrib/tools/swig/Lib/typemaps/carrays.swg b/contrib/tools/swig/Lib/typemaps/carrays.swg
new file mode 100644
index 00000000000..d02e70fab30
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/carrays.swg
@@ -0,0 +1,114 @@
+/* -----------------------------------------------------------------------------
+ * carrays.swg
+ *
+ * This library file contains macros that can be used to manipulate simple
+ * pointers as arrays.
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * %array_functions(TYPE,NAME)
+ *
+ * Generates functions for creating and accessing elements of a C array
+ * (as pointers). Creates the following functions:
+ *
+ * TYPE *new_NAME(size_t nelements)
+ * void delete_NAME(TYPE *);
+ * TYPE NAME_getitem(TYPE *, size_t index);
+ * void NAME_setitem(TYPE *, size_t index, TYPE value);
+ *
+ * ----------------------------------------------------------------------------- */
+
+%define %array_functions(TYPE,NAME)
+%{
+ static TYPE *new_##NAME(size_t nelements) {
+ return %new_array(nelements, TYPE);
+ }
+
+ static void delete_##NAME(TYPE *ary) {
+ %delete_array(ary);
+ }
+
+ static TYPE NAME##_getitem(TYPE *ary, size_t index) {
+ return ary[index];
+ }
+ static void NAME##_setitem(TYPE *ary, size_t index, TYPE value) {
+ ary[index] = value;
+ }
+%}
+
+TYPE *new_##NAME(size_t nelements);
+void delete_##NAME(TYPE *ary);
+TYPE NAME##_getitem(TYPE *ary, size_t index);
+void NAME##_setitem(TYPE *ary, size_t index, TYPE value);
+
+%enddef
+
+
+/* -----------------------------------------------------------------------------
+ * %array_class(TYPE,NAME)
+ *
+ * Generates a class wrapper around a C array. The class has the following
+ * interface:
+ *
+ * struct NAME {
+ * NAME(size_t nelements);
+ * ~NAME();
+ * TYPE getitem(size_t index);
+ * void setitem(size_t index, TYPE value);
+ * TYPE * cast();
+ * static NAME *frompointer(TYPE *t);
+ * }
+ *
+ * Use
+ *
+ * %array_class_wrap(TYPE,NAME,GET,SET)
+ *
+ * if you want different names for the get/set methods.
+ * ----------------------------------------------------------------------------- */
+
+%define %array_class_wrap(TYPE,NAME,getitem,setitem)
+%{
+typedef TYPE NAME;
+%}
+
+
+typedef struct {
+} NAME;
+
+%extend NAME {
+
+ NAME(size_t nelements) {
+ return %new_array(nelements, TYPE);
+ }
+
+ ~NAME() {
+ %delete_array(self);
+ }
+
+ TYPE getitem(size_t index) {
+ return self[index];
+ }
+
+ void setitem(size_t index, TYPE value) {
+ self[index] = value;
+ }
+
+ TYPE * cast() {
+ return self;
+ }
+
+ static NAME *frompointer(TYPE *t) {
+ return %static_cast(t, NAME *);
+ }
+};
+
+%types(NAME = TYPE);
+
+%enddef
+
+
+#ifndef %array_class
+%define %array_class(TYPE,NAME)
+ %array_class_wrap(TYPE,NAME,getitem,setitem)
+%enddef
+#endif
diff --git a/contrib/tools/swig/Lib/typemaps/cdata_begin.swg b/contrib/tools/swig/Lib/typemaps/cdata_begin.swg
new file mode 100644
index 00000000000..6e914f58e6d
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cdata_begin.swg
@@ -0,0 +1,12 @@
+/* -----------------------------------------------------------------------------
+ * cdata_begin.swg
+ *
+ * raw C data struct.
+ * ----------------------------------------------------------------------------- */
+
+%{
+typedef struct SWIGCDATA {
+ char *data;
+ size_t len;
+} SWIGCDATA;
+%}
diff --git a/contrib/tools/swig/Lib/typemaps/cdata_end.swg b/contrib/tools/swig/Lib/typemaps/cdata_end.swg
new file mode 100644
index 00000000000..8306873549d
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cdata_end.swg
@@ -0,0 +1,71 @@
+/* -----------------------------------------------------------------------------
+ * cdata_end.swg
+ *
+ * This library file contains macros for manipulating raw C data.
+ * ----------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------
+ * Typemap for passing bytes with length
+ * ------------------------------------------------------------ */
+#ifndef SWIG_CDATA_APPLIED
+
+%apply (const void *BYTES, size_t LENGTH) { (const void *BYTES, int LENGTH) }
+%apply (void *BYTES, size_t LENGTH) { (void *BYTES, int LENGTH) }
+/* typemap for memmove() function */
+%apply (const void *BYTES, size_t LENGTH) { (const void *indata, size_t inlen) }
+
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Typemaps for returning binary data
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * %cdata(TYPE [, NAME])
+ *
+ * Convert raw C data to binary
+ * ----------------------------------------------------------------------------- */
+
+%define %cdata(TYPE,NAME...)
+
+%insert("header") {
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if #NAME == ""
+static SWIGCDATA cdata_##TYPE(TYPE *ptr, size_t nelements)
+#else
+static SWIGCDATA cdata_##NAME(TYPE *ptr, size_t nelements)
+#endif
+{
+ SWIGCDATA d;
+ d.data = (char *) ptr;
+#if #TYPE != "void"
+ d.len = nelements*sizeof(TYPE);
+#else
+ d.len = nelements;
+#endif
+ return d;
+}
+#ifdef __cplusplus
+}
+#endif
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+#if #NAME == ""
+SWIGCDATA cdata_##TYPE(TYPE *ptr, size_t nelements = 1);
+#else
+SWIGCDATA cdata_##NAME(TYPE *ptr, size_t nelements = 1);
+#endif
+%enddef
+
+%rename(cdata) ::cdata_void(void *ptr, size_t nelements = 1);
+
+%cdata(void);
+
+/* Memory move function. Due to multi-argument typemaps this appears to be wrapped as
+void memmove(void *data, const char *s); */
+void memmove(void *data, const void *indata, size_t inlen);
diff --git a/contrib/tools/swig/Lib/typemaps/cmalloc.swg b/contrib/tools/swig/Lib/typemaps/cmalloc.swg
new file mode 100644
index 00000000000..45a6ab990ec
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cmalloc.swg
@@ -0,0 +1,110 @@
+/* -----------------------------------------------------------------------------
+ * cmalloc.swg
+ *
+ * This library file contains macros that can be used to create objects using
+ * the C malloc function.
+ * ----------------------------------------------------------------------------- */
+
+%{
+#include <stdlib.h>
+%}
+
+/* %malloc(TYPE [, NAME = TYPE])
+ %calloc(TYPE [, NAME = TYPE])
+ %realloc(TYPE [, NAME = TYPE])
+ %free(TYPE [, NAME = TYPE])
+ %allocators(TYPE [,NAME = TYPE])
+
+ Creates functions for allocating/reallocating memory.
+
+ TYPE *malloc_NAME(size_t nbytes = sizeof(TYPE);
+ TYPE *calloc_NAME(size_t nobj=1, size_t size=sizeof(TYPE));
+ TYPE *realloc_NAME(TYPE *ptr, size_t nbytes);
+ void free_NAME(TYPE *ptr);
+
+*/
+
+%define %malloc(TYPE,NAME...)
+#if #NAME != ""
+%rename(malloc_##NAME) ::malloc(size_t nbytes);
+#else
+%rename(malloc_##TYPE) ::malloc(size_t nbytes);
+#endif
+
+#if #TYPE != "void"
+%typemap(default) size_t nbytes "$1 = (size_t) sizeof(TYPE);"
+#endif
+TYPE *malloc(size_t nbytes);
+%typemap(default) size_t nbytes;
+%enddef
+
+%define %calloc(TYPE,NAME...)
+#if #NAME != ""
+%rename(calloc_##NAME) ::calloc(size_t nobj, size_t sz);
+#else
+%rename(calloc_##TYPE) ::calloc(size_t nobj, size_t sz);
+#endif
+#if #TYPE != "void"
+%typemap(default) size_t sz "$1 = (size_t) sizeof(TYPE);"
+#else
+%typemap(default) size_t sz "$1 = 1;"
+#endif
+%typemap(default) size_t nobj "$1 = 1;"
+TYPE *calloc(size_t nobj, size_t sz);
+%typemap(default) size_t sz;
+%typemap(default) size_t nobj;
+%enddef
+
+%define %realloc(TYPE,NAME...)
+%insert("header") {
+#if #NAME != ""
+TYPE *realloc_##NAME(TYPE *ptr, size_t nitems)
+#else
+TYPE *realloc_##TYPE(TYPE *ptr, size_t nitems)
+#endif
+{
+#if #TYPE != "void"
+return (TYPE *) realloc(ptr, nitems*sizeof(TYPE));
+#else
+return (TYPE *) realloc(ptr, nitems);
+#endif
+}
+}
+#if #NAME != ""
+TYPE *realloc_##NAME(TYPE *ptr, size_t nitems);
+#else
+TYPE *realloc_##TYPE(TYPE *ptr, size_t nitems);
+#endif
+%enddef
+
+%define %free(TYPE,NAME...)
+#if #NAME != ""
+%rename(free_##NAME) ::free(TYPE *ptr);
+#else
+%rename(free_##TYPE) ::free(TYPE *ptr);
+#endif
+void free(TYPE *ptr);
+%enddef
+
+%define %sizeof(TYPE,NAME...)
+#if #NAME != ""
+%constant size_t sizeof_##NAME = sizeof(TYPE);
+#else
+%constant size_t sizeof_##TYPE = sizeof(TYPE);
+#endif
+%enddef
+
+%define %allocators(TYPE,NAME...)
+%malloc(TYPE,NAME)
+%calloc(TYPE,NAME)
+%realloc(TYPE,NAME)
+%free(TYPE,NAME)
+#if #TYPE != "void"
+%sizeof(TYPE,NAME)
+#endif
+%enddef
+
+
+
+
+
diff --git a/contrib/tools/swig/Lib/typemaps/cpointer.swg b/contrib/tools/swig/Lib/typemaps/cpointer.swg
new file mode 100644
index 00000000000..a5ac07d8552
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cpointer.swg
@@ -0,0 +1,157 @@
+/* -----------------------------------------------------------------------------
+ * cpointer.swg
+ *
+ * This library file contains macros that can be used to manipulate simple
+ * pointer objects.
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * %pointer_class(type,name)
+ *
+ * Places a simple proxy around a simple type like 'int', 'float', or whatever.
+ * The proxy provides this interface:
+ *
+ * class type {
+ * public:
+ * type();
+ * ~type();
+ * type value();
+ * void assign(type value);
+ * };
+ *
+ * Example:
+ *
+ * %pointer_class(int, intp);
+ *
+ * int add(int *x, int *y) { return *x + *y; }
+ *
+ * In python (with proxies)
+ *
+ * >>> a = intp()
+ * >>> a.assign(10)
+ * >>> a.value()
+ * 10
+ * >>> b = intp()
+ * >>> b.assign(20)
+ * >>> print add(a,b)
+ * 30
+ *
+ * As a general rule, this macro should not be used on class/structures that
+ * are already defined in the interface.
+ * ----------------------------------------------------------------------------- */
+
+
+%define %pointer_class(TYPE, NAME)
+%{
+typedef TYPE NAME;
+%}
+
+typedef struct {
+} NAME;
+
+%extend NAME {
+ NAME() {
+ return %new_instance(TYPE);
+ }
+ ~NAME() {
+ %delete($self);
+ }
+}
+
+%extend NAME {
+
+ void assign(TYPE value) {
+ *$self = value;
+ }
+ TYPE value() {
+ return *$self;
+ }
+ TYPE * cast() {
+ return $self;
+ }
+ static NAME * frompointer(TYPE *t) {
+ return (NAME *) t;
+ }
+}
+
+%types(NAME = TYPE);
+
+%enddef
+
+/* -----------------------------------------------------------------------------
+ * %pointer_functions(type,name)
+ *
+ * Create functions for allocating/deallocating pointers. This can be used
+ * if you don't want to create a proxy class or if the pointer is complex.
+ *
+ * %pointer_functions(int, intp)
+ *
+ * int add(int *x, int *y) { return *x + *y; }
+ *
+ * In python (with proxies)
+ *
+ * >>> a = copy_intp(10)
+ * >>> intp_value(a)
+ * 10
+ * >>> b = new_intp()
+ * >>> intp_assign(b,20)
+ * >>> print add(a,b)
+ * 30
+ * >>> delete_intp(a)
+ * >>> delete_intp(b)
+ *
+ * ----------------------------------------------------------------------------- */
+
+%define %pointer_functions(TYPE,NAME)
+%{
+ static TYPE *new_##NAME(void) {
+ return %new_instance(TYPE);
+ }
+
+ static TYPE *copy_##NAME(TYPE value) {
+ return %new_copy(value, TYPE);
+ }
+
+ static void delete_##NAME(TYPE *obj) {
+ %delete(obj);
+ }
+
+ static void NAME ##_assign(TYPE *obj, TYPE value) {
+ *obj = value;
+ }
+
+ static TYPE NAME ##_value(TYPE *obj) {
+ return *obj;
+ }
+%}
+
+TYPE *new_##NAME(void);
+TYPE *copy_##NAME(TYPE value);
+void delete_##NAME(TYPE *obj);
+void NAME##_assign(TYPE *obj, TYPE value);
+TYPE NAME##_value(TYPE *obj);
+
+%enddef
+
+/* -----------------------------------------------------------------------------
+ * %pointer_cast(type1,type2,name)
+ *
+ * Generates a pointer casting function.
+ * ----------------------------------------------------------------------------- */
+
+%define %pointer_cast(TYPE1,TYPE2,NAME)
+%inline %{
+TYPE2 NAME(TYPE1 x) {
+ return %static_cast(x, TYPE2);
+}
+%}
+%enddef
+
+
+
+
+
+
+
+
diff --git a/contrib/tools/swig/Lib/typemaps/cstring.swg b/contrib/tools/swig/Lib/typemaps/cstring.swg
new file mode 100644
index 00000000000..e774c431254
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cstring.swg
@@ -0,0 +1,9 @@
+%include <typemaps/cstrings.swg>
+
+%typemaps_cstring(%cstring,
+ char,
+ SWIG_AsCharPtr,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtr,
+ SWIG_FromCharPtrAndSize);
+
diff --git a/contrib/tools/swig/Lib/typemaps/cstrings.swg b/contrib/tools/swig/Lib/typemaps/cstrings.swg
new file mode 100644
index 00000000000..332f9f85385
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cstrings.swg
@@ -0,0 +1,288 @@
+/* -----------------------------------------------------------------------------
+ * cstrings.swg
+ *
+ * This file provides typemaps and macros for dealing with various forms
+ * of C character string handling. The primary use of this module
+ * is in returning character data that has been allocated or changed in
+ * some way.
+ * ----------------------------------------------------------------------------- */
+
+%define %typemaps_cstring(Name, Char,
+ SWIG_AsCharPtr,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtr,
+ SWIG_FromCharPtrAndSize)
+
+
+/* %cstring_input_binary(TYPEMAP, SIZE)
+ *
+ * Macro makes a function accept binary string data along with
+ * a size. For example:
+ *
+ * %cstring_input_binary(Char *buff, int size);
+ * void foo(Char *buff, int size) {
+ * }
+ *
+ */
+
+%define Name ## _input_binary(TYPEMAP, SIZE)
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) (TYPEMAP, SIZE)
+ (int res, Char *buf = 0, size_t size = 0, int alloc = 0) {
+ res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ $1 = ($1_ltype) buf;
+ $2 = ($2_ltype) size - 1;
+}
+%typemap(freearg,noblock=1,match="in") (TYPEMAP, SIZE) {
+ if (alloc$argnum == SWIG_NEWOBJ) %delete_array(buf$argnum);
+}
+%enddef
+
+
+
+/*
+ * %cstring_bounded_output(TYPEMAP, MAX)
+ *
+ * This macro is used to return a NULL-terminated output string of
+ * some maximum length. For example:
+ *
+ * %cstring_bounded_output(Char *outx, 512);
+ * void foo(Char *outx) {
+ * strcpy(outx,"blah blah\n");
+ * }
+ *
+ */
+
+%define Name ## _bounded_output(TYPEMAP,MAX)
+%typemap(in,noblock=1,numinputs=0) TYPEMAP (Char temp[MAX+1]) {
+ $1 = ($1_ltype) temp;
+}
+%typemap(freearg,match="in") TYPEMAP ""
+%typemap(argout,noblock=1,fragment= #SWIG_FromCharPtr ) TYPEMAP {
+ $1[MAX] = 0;
+ %append_output(SWIG_FromCharPtr($1));
+}
+%enddef
+
+
+
+/*
+ * %cstring_chunk_output(TYPEMAP, SIZE)
+ *
+ * This macro is used to return a chunk of binary string data.
+ * Embedded NULLs are okay. For example:
+ *
+ * %cstring_chunk_output(Char *outx, 512);
+ * void foo(Char *outx) {
+ * memmove(outx, somedata, 512);
+ * }
+ *
+ */
+
+%define Name ## _chunk_output(TYPEMAP,SIZE)
+%typemap(in,noblock=1,numinputs=0) TYPEMAP(Char temp[SIZE]) {
+ $1 = ($1_ltype) temp;
+}
+%typemap(freearg,match="in") TYPEMAP ""
+%typemap(argout,noblock=1,fragment= #SWIG_FromCharPtrAndSize) TYPEMAP {
+ %append_output(SWIG_FromCharPtrAndSize($1,SIZE));
+}
+%enddef
+
+
+
+/*
+ * %cstring_bounded_mutable(TYPEMAP, SIZE)
+ *
+ * This macro is used to wrap a string that's going to mutate.
+ *
+ * %cstring_bounded_mutable(Char *in, 512);
+ * void foo(in *x) {
+ * while (*x) {
+ * *x = toupper(*x);
+ * x++;
+ * }
+ * }
+ *
+ */
+
+
+%define Name ## _bounded_mutable(TYPEMAP,MAX)
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) TYPEMAP
+ (int res,Char temp[MAX+1], Char *t = 0, size_t n = 0, int alloc = 0) {
+ res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "TYPEMAP", $symname, $argnum);
+ }
+ if ( n > (size_t) MAX ) n = (size_t) MAX;
+ memcpy(temp, t, sizeof(Char)*n);
+ if (alloc == SWIG_NEWOBJ) %delete_array(t);
+ temp[n - 1] = 0;
+ $1 = ($1_ltype) temp;
+}
+%typemap(freearg,match="in") TYPEMAP ""
+%typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) TYPEMAP {
+ $1[MAX] = 0;
+ %append_output(SWIG_FromCharPtr($1));
+}
+%enddef
+
+
+/*
+ * %cstring_mutable(TYPEMAP [, expansion])
+ *
+ * This macro is used to wrap a string that will mutate in place.
+ * It may change size up to a user-defined expansion.
+ *
+ * %cstring_mutable(Char *in);
+ * void foo(in *x) {
+ * while (*x) {
+ * *x = toupper(*x);
+ * x++;
+ * }
+ * }
+ *
+ */
+
+%define Name ## _mutable(TYPEMAP,EXP...)
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) TYPEMAP (int res, Char *t = 0, size_t n = 0, int alloc = 0, size_t expansion = 0) {
+#if #EXP != ""
+ expansion += EXP;
+#endif
+ res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "TYPEMAP", $symname, $argnum);
+ }
+ $1 = %new_array(n+expansion, $*1_ltype);
+ memcpy($1,t,sizeof(Char)*n);
+ if (alloc == SWIG_NEWOBJ) %delete_array(t);
+ $1[n-1] = 0;
+}
+%typemap(freearg,match="in") TYPEMAP ""
+%typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) TYPEMAP {
+ %append_output(SWIG_FromCharPtr($1));
+ %delete_array($1);
+}
+%enddef
+
+
+/*
+ * %cstring_output_maxsize(TYPEMAP, SIZE)
+ *
+ * This macro returns data in a string of some user-defined size.
+ *
+ * %cstring_output_maxsize(Char *outx, int max) {
+ * void foo(Char *outx, int max) {
+ * strcpy(outx,"blah blah\n");
+ * }
+ */
+
+%define Name ## _output_maxsize(TYPEMAP, SIZE)
+%typemap(in,noblock=1,fragment=SWIG_AsVal_frag(size_t)) (TYPEMAP, SIZE) (int res, size_t size, Char *buff = 0) {
+ res = SWIG_AsVal(size_t)($input, &size);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ buff= %new_array(size+1, Char);
+ $2 = %numeric_cast(size, $2_ltype);
+ $1 = %static_cast(buff, $1_ltype);
+}
+%typemap(freearg,noblock=1,match="in") (TYPEMAP,SIZE) {
+ if (buff$argnum) %delete_array(buff$argnum);
+}
+%typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) (TYPEMAP,SIZE) {
+ %append_output(SWIG_FromCharPtr($1));
+}
+%enddef
+
+/*
+ * %cstring_output_withsize(TYPEMAP, SIZE)
+ *
+ * This macro is used to return Character data along with a size
+ * parameter.
+ *
+ * %cstring_output_withsize(Char *outx, int *max) {
+ * void foo(Char *outx, int *max) {
+ * strcpy(outx,"blah blah\n");
+ * *max = strlen(outx);
+ * }
+ */
+
+%define Name ## _output_withsize(TYPEMAP, SIZE)
+%typemap(in,noblock=1,fragment=SWIG_AsVal_frag(size_t)) (TYPEMAP, SIZE) (int res, size_t n, Char *buff = 0, $*2_ltype size) {
+ res = SWIG_AsVal(size_t)($input, &n);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum);
+ }
+ buff= %new_array(n+1, Char);
+ $1 = %static_cast(buff, $1_ltype);
+ size = %numeric_cast(n,$*2_ltype);
+ $2 = &size;
+}
+%typemap(freearg,noblock=1,match="in")(TYPEMAP,SIZE) {
+ if (buff$argnum) %delete_array(buff$argnum);
+}
+%typemap(argout,noblock=1,fragment=#SWIG_FromCharPtrAndSize) (TYPEMAP,SIZE) {
+ %append_output(SWIG_FromCharPtrAndSize($1,*$2));
+}
+%enddef
+
+
+/*
+ * %cstring_output_allocate(TYPEMAP, RELEASE)
+ *
+ * This macro is used to return Character data that was
+ * allocated with new or malloc.
+ *
+ * %cstring_output_allocate(Char **outx, free(*$1));
+ * void foo(Char **outx) {
+ * *outx = (Char *) malloc(512);
+ * strcpy(outx,"blah blah\n");
+ * }
+ */
+
+%define Name ## _output_allocate(TYPEMAP, RELEASE)
+%typemap(in,noblock=1,numinputs=0) TYPEMAP($*1_ltype temp = 0) {
+ $1 = &temp;
+}
+%typemap(freearg,match="in") TYPEMAP ""
+%typemap(argout,noblock=1,fragment=#SWIG_FromCharPtr) TYPEMAP {
+ if (*$1) {
+ %append_output(SWIG_FromCharPtr(*$1));
+ RELEASE;
+ }
+}
+%enddef
+
+
+/*
+ * %cstring_output_allocate_size(TYPEMAP, SIZE, RELEASE)
+ *
+ * This macro is used to return Character data that was
+ * allocated with new or malloc.
+ *
+ * %cstring_output_allocate_size(Char **outx, int *sz, free(*$1));
+ * void foo(Char **outx, int *sz) {
+ * *outx = (Char *) malloc(512);
+ * strcpy(outx,"blah blah\n");
+ * *sz = strlen(outx);
+ * }
+ */
+
+%define Name ## _output_allocate_size(TYPEMAP, SIZE, RELEASE)
+%typemap(in,noblock=1,numinputs=0) (TYPEMAP, SIZE) ($*1_ltype temp = 0, $*2_ltype tempn) {
+ $1 = &temp; $2 = &tempn;
+}
+%typemap(freearg,match="in") (TYPEMAP,SIZE) ""
+%typemap(argout,noblock=1,fragment=#SWIG_FromCharPtrAndSize)(TYPEMAP,SIZE) {
+ if (*$1) {
+ %append_output(SWIG_FromCharPtrAndSize(*$1,*$2));
+ RELEASE;
+ }
+}
+%enddef
+
+%enddef
+
diff --git a/contrib/tools/swig/Lib/typemaps/cwstring.swg b/contrib/tools/swig/Lib/typemaps/cwstring.swg
new file mode 100644
index 00000000000..933f9a3a647
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/cwstring.swg
@@ -0,0 +1,10 @@
+%include <typemaps/cstrings.swg>
+%include <typemaps/wstring.swg>
+
+%typemaps_cstring(%cwstring,
+ wchar_t,
+ SWIG_AsWCharPtr,
+ SWIG_AsWCharPtrAndSize,
+ SWIG_FromWCharPtr,
+ SWIG_FromWCharPtrAndSize);
+
diff --git a/contrib/tools/swig/Lib/typemaps/enumint.swg b/contrib/tools/swig/Lib/typemaps/enumint.swg
new file mode 100644
index 00000000000..b7e2956a267
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/enumint.swg
@@ -0,0 +1,39 @@
+/* ------------------------------------------------------------
+ * Enums mapped as integer values
+ * ------------------------------------------------------------ */
+
+%apply int { enum SWIGTYPE };
+%apply const int& { const enum SWIGTYPE & };
+%apply const int& { const enum SWIGTYPE && };
+
+%typemap(in,fragment=SWIG_AsVal_frag(int),noblock=1) const enum SWIGTYPE & (int val, int ecode, $basetype temp) {
+ ecode = SWIG_AsVal(int)($input, &val);
+ if (!SWIG_IsOK(ecode)) {
+ %argument_fail(ecode, "$type", $symname, $argnum);
+ } else {
+ temp = %static_cast(val,$basetype);
+ $1 = &temp;
+ }
+}
+
+%typemap(in,fragment=SWIG_AsVal_frag(int),noblock=1) const enum SWIGTYPE && (int val, int ecode, $basetype temp) {
+ ecode = SWIG_AsVal(int)($input, &val);
+ if (!SWIG_IsOK(ecode)) {
+ %argument_fail(ecode, "$type", $symname, $argnum);
+ } else {
+ temp = %static_cast(val,$basetype);
+ $1 = &temp;
+ }
+}
+
+%typemap(varin,fragment=SWIG_AsVal_frag(int),noblock=1) enum SWIGTYPE {
+ if (sizeof(int) != sizeof($1)) {
+ %variable_fail(SWIG_AttributeError,"$type", "arch, read-only $name");
+ } else {
+ int ecode = SWIG_AsVal(int)($input, %reinterpret_cast(&$1,int*));
+ if (!SWIG_IsOK(ecode)) {
+ %variable_fail(ecode, "$type", "$name");
+ }
+ }
+}
+
diff --git a/contrib/tools/swig/Lib/typemaps/exception.swg b/contrib/tools/swig/Lib/typemaps/exception.swg
new file mode 100644
index 00000000000..aece8326f50
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/exception.swg
@@ -0,0 +1,87 @@
+/* -----------------------------------------------------------------------------
+ * exceptions.swg
+ *
+ * This SWIG library file provides language independent exception handling
+ * ----------------------------------------------------------------------------- */
+
+%include <typemaps/swigmacros.swg>
+
+
+/* macros for error manipulation */
+#define %nullref_fmt() "invalid null reference "
+#define %varfail_fmt(_type,_name) "in variable '"`_name`"' of type '"`_type`"'"
+#ifndef %argfail_fmt
+#define %argfail_fmt(_type,_name,_argn) "in method '" `_name` "', argument " `_argn`" of type '" `_type`"'"
+#endif
+#define %outfail_fmt(_type) "in output value of type '"_type"'"
+#ifndef %argnullref_fmt
+#define %argnullref_fmt(_type,_name,_argn) %nullref_fmt() %argfail_fmt(_type, _name, _argn)
+#endif
+#define %varnullref_fmt(_type,_name) %nullref_fmt() %varfail_fmt(_type, _name)
+#define %outnullref_fmt(_type) %nullref_fmt() %outfail_fmt(_type)
+#define %releasenotownedfail_fmt(_type,_name,_argn) "in method '" `_name` "', cannot release ownership as memory is not owned for argument " `_argn`" of type '" `_type`"'"
+
+/* setting an error */
+#define %error(code,msg...) SWIG_Error(code, msg)
+#define %type_error(msg...) SWIG_Error(SWIG_TypeError, msg)
+
+
+
+%insert("runtime") {
+
+%define_as(SWIG_exception_fail(code, msg), %block(%error(code, msg); SWIG_fail))
+
+%define_as(SWIG_contract_assert(expr, msg), do { if (!(expr)) { %error(SWIG_RuntimeError, msg); SWIG_fail; } } while (0))
+
+}
+
+#ifdef __cplusplus
+/*
+ You can use the SWIG_CATCH_STDEXCEPT macro with the %exception
+ directive as follows:
+
+ %exception {
+ try {
+ $action
+ }
+ catch (my_except& e) {
+ ...
+ }
+ SWIG_CATCH_STDEXCEPT // catch std::exception
+ catch (...) {
+ SWIG_exception_fail(SWIG_UnknownError, "Unknown exception");
+ }
+ }
+*/
+
+%fragment("<stdexcept>");
+
+%define SWIG_CATCH_STDEXCEPT
+ /* catching std::exception */
+ catch (std::invalid_argument& e) {
+ SWIG_exception_fail(SWIG_ValueError, e.what() );
+ } catch (std::domain_error& e) {
+ SWIG_exception_fail(SWIG_ValueError, e.what() );
+ } catch (std::overflow_error& e) {
+ SWIG_exception_fail(SWIG_OverflowError, e.what() );
+ } catch (std::out_of_range& e) {
+ SWIG_exception_fail(SWIG_IndexError, e.what() );
+ } catch (std::length_error& e) {
+ SWIG_exception_fail(SWIG_IndexError, e.what() );
+ } catch (std::runtime_error& e) {
+ SWIG_exception_fail(SWIG_RuntimeError, e.what() );
+ } catch (std::exception& e) {
+ SWIG_exception_fail(SWIG_SystemError, e.what() );
+ }
+%enddef
+%define SWIG_CATCH_UNKNOWN
+ catch (std::exception& e) {
+ SWIG_exception_fail(SWIG_SystemError, e.what() );
+ }
+ catch (...) {
+ SWIG_exception_fail(SWIG_UnknownError, "unknown exception");
+ }
+%enddef
+
+
+#endif /* __cplusplus */
diff --git a/contrib/tools/swig/Lib/typemaps/factory.swg b/contrib/tools/swig/Lib/typemaps/factory.swg
new file mode 100644
index 00000000000..bccceb1d7a2
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/factory.swg
@@ -0,0 +1,88 @@
+/*
+ Implement a more natural wrap for factory methods, for example, if
+ you have:
+
+ ---- geometry.h --------
+ struct Geometry {
+ enum GeomType{
+ POINT,
+ CIRCLE
+ };
+
+ virtual ~Geometry() {}
+ virtual int draw() = 0;
+
+ //
+ // Factory method for all the Geometry objects
+ //
+ static Geometry *create(GeomType i);
+ };
+
+ struct Point : Geometry {
+ int draw() { return 1; }
+ double width() { return 1.0; }
+ };
+
+ struct Circle : Geometry {
+ int draw() { return 2; }
+ double radius() { return 1.5; }
+ };
+
+ //
+ // Factory method for all the Geometry objects
+ //
+ Geometry *Geometry::create(GeomType type) {
+ switch (type) {
+ case POINT: return new Point();
+ case CIRCLE: return new Circle();
+ default: return 0;
+ }
+ }
+ ---- geometry.h --------
+
+
+ You can use the %factory with the Geometry::create method as follows:
+
+ %newobject Geometry::create;
+ %factory(Geometry *Geometry::create, Point, Circle);
+ %include "geometry.h"
+
+ and Geometry::create will return a 'Point' or 'Circle' instance
+ instead of the plain 'Geometry' type. For example, in python:
+
+ circle = Geometry.create(Geometry.CIRCLE)
+ r = circle.radius()
+
+ where circle is a Circle proxy instance.
+
+ NOTES: remember to fully qualify all the type names and don't
+ use %factory inside a namespace declaration, ie, instead of
+
+ namespace Foo {
+ %factory(Geometry *Geometry::create, Point, Circle);
+ }
+
+ use
+
+ %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle);
+
+
+*/
+
+%define %_factory_dispatch(Type)
+if (!dcast) {
+ Type *dobj = dynamic_cast<Type *>($1);
+ if (dobj) {
+ dcast = 1;
+ %set_output(SWIG_NewPointerObj(%as_voidptr(dobj),$descriptor(Type *), $owner | %newpointer_flags));
+ }
+}%enddef
+
+%define %factory(Method,Types...)
+%typemap(out) Method {
+ int dcast = 0;
+ %formacro(%_factory_dispatch, Types)
+ if (!dcast) {
+ %set_output(SWIG_NewPointerObj(%as_voidptr($1),$descriptor, $owner | %newpointer_flags));
+ }
+}%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/fragments.swg b/contrib/tools/swig/Lib/typemaps/fragments.swg
new file mode 100644
index 00000000000..789b649e335
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/fragments.swg
@@ -0,0 +1,231 @@
+/*
+ Fragments
+ =========
+ See the "Typemap fragments" section in the documentation for understanding
+ fragments. Below is some info on how fragments and automatic type
+ specialization is used.
+
+ Macros that make the automatic generation of typemaps easier are provided.
+
+ Consider the following code:
+
+ %fragment(SWIG_From_frag(bool), "header") {
+ static PyObject*
+ SWIG_From_dec(bool)(bool value)
+ {
+ PyObject *obj = value ? Py_True : Py_False;
+ SWIG_Py_INCREF(obj);
+ return obj;
+ }
+ }
+
+ %typemap(out, fragment=SWIG_From_frag(bool)) bool {
+ $result = SWIG_From(bool)($1));
+ }
+
+ Here the macros
+
+ SWIG_From_frag => fragment
+ SWIG_From_dec => declaration
+ SWIG_From => call
+
+ allow you to define/include a fragment, and declare and call the
+ 'from-bool' method as needed. In the simpler case, these macros
+ just return something like
+
+ SWIG_From_frag(bool) => "SWIG_From_bool"
+ SWIG_From_dec(bool) => SWIG_From_bool
+ SWIG_From(bool) => SWIG_From_bool
+
+ But they are specialized for the different languages requirements,
+ such as perl or tcl that requires passing the interpreter pointer,
+ and also they can manage C++ ugly types, for example:
+
+ SWIG_From_frag(std::complex<double>) => "SWIG_From_std_complex_Sl_double_Sg_"
+ SWIG_From_dec(std::complex<double>) => SWIG_From_std_complex_Sl_double_Sg_
+ SWIG_From(std::complex<double>) => SWIG_From_std_complex_Sl_double_Sg_
+
+
+ Hence, to declare methods to use with typemaps, always use the
+ SWIG_From* macros. In the same way, the SWIG_AsVal* and SWIG_AsPtr*
+ set of macros are provided.
+
+*/
+
+
+/* -----------------------------------------------------------------------------
+ * Define the basic macros to 'normalize' the type fragments
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_AS_DECL_ARGS
+#define SWIG_AS_DECL_ARGS
+#endif
+
+#ifndef SWIG_FROM_DECL_ARGS
+#define SWIG_FROM_DECL_ARGS
+#endif
+
+#ifndef SWIG_AS_CALL_ARGS
+#define SWIG_AS_CALL_ARGS
+#endif
+
+#ifndef SWIG_FROM_CALL_ARGS
+#define SWIG_FROM_CALL_ARGS
+#endif
+
+#define %fragment_name(Name, Type...) %string_name(Name) "_" {Type}
+
+#define SWIG_Traits_frag(Type...) %fragment_name(Traits, Type)
+#define SWIG_AsPtr_frag(Type...) %fragment_name(AsPtr, Type)
+#define SWIG_AsVal_frag(Type...) %fragment_name(AsVal, Type)
+#define SWIG_From_frag(Type...) %fragment_name(From, Type)
+
+#define SWIG_AsVal_name(Type...) %symbol_name(AsVal, Type)
+#define SWIG_AsPtr_name(Type...) %symbol_name(AsPtr, Type)
+#define SWIG_From_name(Type...) %symbol_name(From, Type)
+
+#define SWIG_AsVal_dec(Type...) SWIG_AsVal_name(Type) SWIG_AS_DECL_ARGS
+#define SWIG_AsPtr_dec(Type...) SWIG_AsPtr_name(Type) SWIG_AS_DECL_ARGS
+#define SWIG_From_dec(Type...) SWIG_From_name(Type) SWIG_FROM_DECL_ARGS
+
+#define SWIG_AsVal(Type...) SWIG_AsVal_name(Type) SWIG_AS_CALL_ARGS
+#define SWIG_AsPtr(Type...) SWIG_AsPtr_name(Type) SWIG_AS_CALL_ARGS
+#define SWIG_From(Type...) SWIG_From_name(Type) SWIG_FROM_CALL_ARGS
+
+/* ------------------------------------------------------------
+ * common fragments
+ * ------------------------------------------------------------ */
+
+%fragment("SWIG_isfinite","header",fragment="<math.h>,<float.h>") %{
+/* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */
+#ifndef SWIG_isfinite
+/* isfinite() is a macro for C99 */
+# if defined(isfinite)
+# define SWIG_isfinite(X) (isfinite(X))
+# elif defined(__cplusplus) && __cplusplus >= 201103L
+/* Use a template so that this works whether isfinite() is std::isfinite() or
+ * in the global namespace. The reality seems to vary between compiler
+ * versions.
+ *
+ * Make sure namespace std exists to avoid compiler warnings.
+ *
+ * extern "C++" is required as this fragment can end up inside an extern "C" { } block
+ */
+namespace std { }
+extern "C++" template<typename T>
+inline int SWIG_isfinite_func(T x) {
+ using namespace std;
+ return isfinite(x);
+}
+# define SWIG_isfinite(X) (SWIG_isfinite_func(X))
+# elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+# define SWIG_isfinite(X) (__builtin_isfinite(X))
+# elif defined(_MSC_VER)
+# define SWIG_isfinite(X) (_finite(X))
+# elif defined(__sun) && defined(__SVR4)
+# include <ieeefp.h>
+# define SWIG_isfinite(X) (finite(X))
+# endif
+#endif
+%}
+
+%fragment("SWIG_Float_Overflow_Check","header",fragment="<float.h>,SWIG_isfinite") %{
+/* Accept infinite as a valid float value unless we are unable to check if a value is finite */
+#ifdef SWIG_isfinite
+# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX) && SWIG_isfinite(X))
+#else
+# define SWIG_Float_Overflow_Check(X) ((X < -FLT_MAX || X > FLT_MAX))
+#endif
+%}
+
+/* -----------------------------------------------------------------------------
+ * special macros for fragments
+ * ----------------------------------------------------------------------------- */
+
+/* Macros to derive numeric types */
+
+%define %numeric_type_from(Type, Base)
+%fragment(SWIG_From_frag(Type),"header",
+ fragment=SWIG_From_frag(Base)) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From_dec(Type)(Type value)
+{
+ return SWIG_From(Base)(value);
+}
+}
+%enddef
+
+%define %numeric_type_asval(Type, Base, Frag, OverflowCond)
+%fragment(SWIG_AsVal_frag(Type),"header",
+ fragment=Frag,
+ fragment=SWIG_AsVal_frag(Base)) {
+SWIGINTERN int
+SWIG_AsVal_dec(Type)(SWIG_Object obj, Type *val)
+{
+ Base v;
+ int res = SWIG_AsVal(Base)(obj, &v);
+ if (SWIG_IsOK(res)) {
+ if (OverflowCond) {
+ return SWIG_OverflowError;
+ } else {
+ if (val) *val = %numeric_cast(v, Type);
+ }
+ }
+ return res;
+}
+}
+%enddef
+
+#define %numeric_signed_type_asval(Type, Base, Frag, Min, Max) \
+%numeric_type_asval(Type, Base, Frag, (v < Min || v > Max))
+
+#define %numeric_unsigned_type_asval(Type, Base, Frag, Max) \
+%numeric_type_asval(Type, Base, Frag, (v > Max))
+
+
+/* Macro for 'signed long' derived types */
+
+%define %numeric_slong(Type, Frag, Min, Max)
+%numeric_type_from(Type, long)
+%numeric_signed_type_asval(Type, long, Frag , Min, Max)
+%enddef
+
+/* Macro for 'unsigned long' derived types */
+
+%define %numeric_ulong(Type, Frag, Max)
+%numeric_type_from(Type, unsigned long)
+%numeric_unsigned_type_asval(Type, unsigned long, Frag, Max)
+%enddef
+
+
+/* Macro for floating point derived types (original macro) */
+
+%define %numeric_double(Type, Frag, Min, Max)
+%numeric_type_from(Type, double)
+%numeric_signed_type_asval(Type, double, Frag , Min, Max)
+%enddef
+
+/* Macro for floating point derived types */
+
+%define %numeric_float(Type, Frag, OverflowCond)
+%numeric_type_from(Type, double)
+%numeric_type_asval(Type, double, Frag, OverflowCond)
+%enddef
+
+
+/* Macros for missing fragments */
+
+%define %ensure_fragment(Fragment)
+%fragment(`Fragment`,"header") {
+%#error "SWIG language implementation must provide the Fragment fragment"
+}
+%enddef
+
+%define %ensure_type_fragments(Type)
+%fragment(SWIG_From_frag(Type),"header") {
+%#error "SWIG language implementation must provide a SWIG_From_frag(Type) fragment"
+}
+%fragment(SWIG_AsVal_frag(Type),"header") {
+%#error "SWIG language implementation must provide a SWIG_AsVal_frag(Type) fragment"
+}
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/implicit.swg b/contrib/tools/swig/Lib/typemaps/implicit.swg
new file mode 100644
index 00000000000..5536e0a22d0
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/implicit.swg
@@ -0,0 +1,208 @@
+/*
+ The %implicit macro allows a SwigType (Class) to be accepted
+ as an input parameter and use its implicit constructors when needed.
+
+ For example:
+
+
+ %implicit(A, int, double, B);
+
+ %inline
+ {
+ struct B { };
+ struct A
+ {
+ int ii;
+ A(int i) { ii = 1; }
+ A(double d) { ii = 2; }
+ A(const B& b) { ii = 3; }
+ };
+
+ int get(A a) { return a.ii; }
+ }
+
+ Here, you can call 'get' as
+
+ get(1) ==> get(A(1))
+ get(2.0) ==> get(A(2.0))
+ get(B()) ==> get(A(B()))
+
+ and swig will construct an 'A' temporary variable using the
+ corresponding implicit constructor.
+
+
+ The plain implicit macro takes care of simple type list. If it doesn't
+ work because you are passing template types with commas, then use
+ the %implicit_{1,2,3} versions and/or the %arg macro.
+
+*/
+
+%define %implicit_type(Type...)
+%traits_swigtype(Type);
+%enddef
+
+%define %implicit_frag(Type...) ,fragment=SWIG_Traits_frag(Type) %enddef
+
+%define %implicit_code(Type...)
+{
+ Type _v;
+ int res = swig::asval<Type >(obj, &_v);
+ if (SWIG_IsOK(res)) {
+ if (val) *val = new value_type(static_cast<const Type& >(_v));
+ return SWIG_AddNewMask(res);
+ }
+}
+%enddef
+
+/* implicit */
+
+%define %implicit(Type, ...)
+
+%formacro_1(%implicit_type,__VA_ARGS__);
+
+%fragment(SWIG_Traits_frag(Type),"header",
+ fragment="StdTraits"
+ %formacro_1(%implicit_frag,__VA_ARGS__)) %{
+namespace swig {
+ template <> struct traits<Type > {
+ typedef pointer_category category;
+ static const char* type_name() { return "Type"; }
+ };
+
+ template <> struct traits_asptr< Type > {
+ typedef Type value_type;
+ static int asptr(SWIG_Object obj, value_type **val) {
+ Type *vptr;
+ static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
+ int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res)) {
+ if (val) *val = vptr;
+ return res;
+ } else {
+ %formacro_1(%implicit_code,__VA_ARGS__)
+ }
+ return SWIG_TypeError;
+ }
+ };
+}
+%}
+
+%typemap_traits_ptr(%checkcode(POINTER),Type);
+%enddef
+
+/* implicit_1 */
+
+
+%define %implicit_1(Type, Imp1)
+%traits_swigtype(Imp1);
+
+%fragment(SWIG_Traits_frag(Type),"header",
+ fragment="StdTraits",
+ fragment=SWIG_Traits_frag(Imp1)) %{
+namespace swig {
+ template <> struct traits< Type > {
+ typedef pointer_category category;
+ static const char* type_name() { return "Type"; }
+ };
+
+ template <> struct traits_asptr< Type > {
+ typedef Type value_type;
+ static int asptr(SWIG_Object obj, value_type **val) {
+ Type *vptr;
+ static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
+ int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res)) {
+ if (val) *val = vptr;
+ return res;
+ } else {
+ %implicit_code(Imp1);
+ }
+ return SWIG_TypeError;
+ }
+ };
+}
+%}
+
+%typemap_traits_ptr(%checkcode(POINTER),Type);
+
+%enddef
+
+/* implicit_2 */
+
+%define %implicit_2(Type, Imp1, Imp2)
+%traits_swigtype(Imp1);
+%traits_swigtype(Imp2);
+
+%fragment(SWIG_Traits_frag(Type),"header",
+ fragment="StdTraits",
+ fragment=SWIG_Traits_frag(Imp1),
+ fragment=SWIG_Traits_frag(Imp2)) %{
+namespace swig {
+ template <> struct traits< Type > {
+ typedef pointer_category category;
+ static const char* type_name() { return "Type"; }
+ };
+
+ template <> struct traits_asptr< Type > {
+ typedef Type value_type;
+ static int asptr(SWIG_Object obj, value_type **val) {
+ Type *vptr;
+ static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
+ int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res)) {
+ if (val) *val = vptr;
+ return SWIG_OLDOBJ;
+ } else {
+ %implicit_code(Imp1);
+ %implicit_code(Imp2);
+ }
+ return SWIG_TypeError;
+ }
+ };
+}
+%}
+
+%typemap_traits_ptr(%checkcode(POINTER),Type);
+%enddef
+
+
+/* implicit_3 */
+
+%define %implicit_3(Type, Imp1, Imp2, Imp3)
+%traits_swigtype(Imp1);
+%traits_swigtype(Imp2);
+%traits_swigtype(Imp3);
+
+%fragment(SWIG_Traits_frag(Type),"header",
+ fragment="StdTraits",
+ fragment=SWIG_Traits_frag(Imp1),
+ fragment=SWIG_Traits_frag(Imp2),
+ fragment=SWIG_Traits_frag(Imp3)) %{
+namespace swig {
+ template <> struct traits< Type > {
+ typedef pointer_category category;
+ static const char* type_name() { return "Type"; }
+ };
+
+ template <> struct traits_asptr< Type > {
+ typedef Type value_type;
+ static int asptr(SWIG_Object obj, value_type **val) {
+ Type *vptr;
+ static swig_type_info* descriptor = SWIG_TypeQuery("Type *");
+ int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&vptr, descriptor, 0) : SWIG_ERROR;
+ if (SWIG_IsOK(res)) {
+ if (val) *val = vptr;
+ return res;
+ } else {
+ %implicit_code(Imp1);
+ %implicit_code(Imp2);
+ %implicit_code(Imp3);
+ }
+ return SWIG_TypeError;
+ }
+ };
+}
+%}
+
+%typemap_traits_ptr(%checkcode(POINTER),Type);
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/inoutlist.swg b/contrib/tools/swig/Lib/typemaps/inoutlist.swg
new file mode 100644
index 00000000000..09f7b4e8c14
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/inoutlist.swg
@@ -0,0 +1,279 @@
+/* ------------------------------------------------------------
+ *
+ * Define the IN/OUTPUT typemaps assuming the output parameters are
+ * returned in a list, i.e., they are not directly modified.
+ *
+ * The user should provide the %append_output(result, obj) method,
+ * via a macro, which append a particular object to the result.
+ *
+ *
+ * In Tcl, for example, the file is used as:
+ *
+ * #define %append_output(obj) Tcl_ListObjAppendElement(interp,Tcl_GetObjResult(interp),obj);
+ * %include <typemaps/inoutlist.swg>
+ *
+ * while in Python it is used as:
+ *
+ * #define %append_output(obj) $result = SWIG_Python_AppendResult($result, obj)
+ * %include <typemaps/inoutlist.swg>
+ *
+ * where the method SWIG_Python_AppendResult is defined inside the
+ * %append_output fragment.
+ *
+ * If you forget to define %append_output, this file will generate
+ * an error.
+ *
+ * ------------------------------------------------------------ */
+
+
+//
+// Uncomment the following definition if you don't want the in/out
+// typemaps by default, ie, you prefer to use typemaps.i.
+//
+//#define SWIG_INOUT_NODEF
+
+//
+// Use the following definition to enable the INPUT parameters to
+// accept both 'by value' and 'pointer' objects.
+//
+#define SWIG_INPUT_ACCEPT_PTRS
+
+// ------------------------------------------------------------------------
+// Pointer handling
+//
+// These mappings provide support for input/output arguments and common
+// uses for C/C++ pointers.
+// ------------------------------------------------------------------------
+
+// INPUT typemaps.
+// These remap a C pointer to be an "INPUT" value which is passed by value
+// instead of reference.
+
+/*
+The following methods can be applied to turn a pointer into a simple
+"input" value. That is, instead of passing a pointer to an object,
+you would use a real value instead.
+
+To use these, suppose you had a C function like this :
+
+ double fadd(double *a, double *b) {
+ return *a+*b;
+ }
+
+You could wrap it with SWIG as follows :
+
+ double fadd(double *INPUT, double *INPUT);
+
+or you can use the %apply directive :
+
+ %apply double *INPUT { double *a, double *b };
+ double fadd(double *a, double *b);
+
+*/
+#if defined(SWIG_INPUT_ACCEPT_PTRS)
+#define %check_input_ptr(input,arg,desc,disown) (SWIG_IsOK((res = SWIG_ConvertPtr(input,%as_voidptrptr(arg),desc,disown))))
+#else
+#define %check_input_ptr(input,arg,desc,disown) (SWIG_IsOK((res = SWIG_ERROR)))
+#endif
+
+%define %_value_input_typemap(code, asval_meth, asval_frag, Type)
+ %typemap(in,noblock=1,fragment=asval_frag) Type *INPUT ($*ltype temp, int res = 0), Type &INPUT($*ltype temp, int res = 0) {
+ if (!%check_input_ptr($input,&$1,$descriptor,$disown)) {
+ Type val;
+ int ecode = asval_meth($input, &val);
+ if (!SWIG_IsOK(ecode)) {
+ %argument_fail(ecode, "$*ltype",$symname, $argnum);
+ }
+ temp = %static_cast(val, $*ltype);
+ $1 = &temp;
+ res = SWIG_AddTmpMask(ecode);
+ }
+ }
+ %typemap(freearg,noblock=1,match="in") Type *INPUT, Type &INPUT {
+ if (SWIG_IsNewObj(res$argnum)) %delete($1);
+ }
+ %typemap(typecheck,noblock=1,precedence=code,fragment=asval_frag) Type *INPUT, Type &INPUT {
+ void *ptr = 0;
+ int res = asval_meth($input, 0);
+ $1 = SWIG_CheckState(res);
+ if (!$1) {
+ $1 = %check_input_ptr($input,&ptr,$1_descriptor,0);
+ }
+ }
+%enddef
+
+%define %_ptr_input_typemap(code,asptr_meth,asptr_frag,Type)
+ %typemap(in,noblock=1,fragment=asptr_frag) Type *INPUT(int res = 0) {
+ res = asptr_meth($input, &$1);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ res = SWIG_AddTmpMask(res);
+ }
+ %typemap(in,noblock=1,fragment=asptr_frag) Type &INPUT(int res = 0) {
+ res = asptr_meth($input, &$1);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ if (!$1) {
+ %argument_nullref("$type",$symname, $argnum);
+ }
+ res = SWIG_AddTmpMask(res);
+ }
+ %typemap(freearg,noblock=1,match="in") Type *INPUT, Type &INPUT {
+ if (SWIG_IsNewObj(res$argnum)) %delete($1);
+ }
+ %typemap(typecheck,noblock=1,precedence=code,fragment=asptr_frag) Type *INPUT, Type &INPUT {
+ int res = asptr_meth($input, (Type**)0);
+ $1 = SWIG_CheckState(res);
+ }
+%enddef
+
+// OUTPUT typemaps. These typemaps are used for parameters that
+// are output only. The output value is appended to the result as
+// a list element.
+
+/*
+The following methods can be applied to turn a pointer into an "output"
+value. When calling a function, no input value would be given for
+a parameter, but an output value would be returned. In the case of
+multiple output values, they are returned in the form of a list.
+
+For example, suppose you were trying to wrap the modf() function in the
+C math library which splits x into integral and fractional parts (and
+returns the integer part in one of its parameters):
+
+ double modf(double x, double *ip);
+
+You could wrap it with SWIG as follows :
+
+ double modf(double x, double *OUTPUT);
+
+or you can use the %apply directive :
+
+ %apply double *OUTPUT { double *ip };
+ double modf(double x, double *ip);
+
+The output of the function would be a list containing both output
+values.
+
+*/
+
+%define %_value_output_typemap(from_meth, from_frag, Type)
+ %typemap(in,numinputs=0,noblock=1)
+ Type *OUTPUT ($*1_ltype temp, int res = SWIG_TMPOBJ),
+ Type &OUTPUT ($*1_ltype temp, int res = SWIG_TMPOBJ) {
+ $1 = &temp;
+ }
+ %typemap(argout,noblock=1,fragment=from_frag) Type *OUTPUT, Type &OUTPUT {
+ if (SWIG_IsTmpObj(res$argnum)) {
+ %append_output(from_meth((*$1)));
+ } else {
+ int new_flags = SWIG_IsNewObj(res$argnum) ? (SWIG_POINTER_OWN | %newpointer_flags) : %newpointer_flags;
+ %append_output(SWIG_NewPointerObj((void*)($1), $1_descriptor, new_flags));
+ }
+ }
+%enddef
+
+
+// INOUT
+// Mappings for an argument that is both an input and output
+// parameter
+
+/*
+The following methods can be applied to make a function parameter both
+an input and output value. This combines the behavior of both the
+"INPUT" and "OUTPUT" methods described earlier. Output values are
+returned in the form of a list.
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ void neg(double *INOUT);
+
+or you can use the %apply directive :
+
+ %apply double *INOUT { double *x };
+ void neg(double *x);
+
+Unlike C, this mapping does not directly modify the input value.
+Rather, the modified input value shows up as the return value of the
+function. Thus, to apply this function to a variable you might do
+this :
+
+ x = neg(x)
+
+*/
+
+%define %_value_inout_typemap(Type)
+ %typemap(in) Type *INOUT = Type *INPUT;
+ %typemap(in) Type &INOUT = Type &INPUT;
+ %typemap(typecheck) Type *INOUT = Type *INPUT;
+ %typemap(typecheck) Type &INOUT = Type &INPUT;
+ %typemap(argout) Type *INOUT = Type *OUTPUT;
+ %typemap(argout) Type &INOUT = Type &OUTPUT;
+%enddef
+
+
+%define %_ptr_inout_typemap(Type)
+ %_value_inout_typemap(%arg(Type))
+ %typemap(typecheck) Type *INOUT = Type *INPUT;
+ %typemap(typecheck) Type &INOUT = Type &INPUT;
+ %typemap(freearg) Type *INOUT = Type *INPUT;
+ %typemap(freearg) Type &INOUT = Type &INPUT;
+%enddef
+
+#ifndef SWIG_INOUT_NODEF
+
+%define %value_input_typemap(code,asval_meth, asval_frag, Type...)
+ %_value_input_typemap(%arg(code),%arg(asval_meth),%arg(asval_frag),%arg(Type))
+%enddef
+
+%define %ptr_input_typemap(code,asval_meth,asval_frag,Type...)
+ %_ptr_input_typemap(%arg(code),%arg(asval_meth),%arg(asval_frag),%arg(Type))
+%enddef
+
+%define %value_output_typemap(from_meth,from_frag,Type...)
+ %_value_output_typemap(%arg(from_meth),%arg(from_frag),%arg(Type))
+%enddef
+
+#define %value_inout_typemap(Type...) %_value_inout_typemap(%arg(Type))
+#define %ptr_inout_typemap(Type...) %_ptr_inout_typemap(%arg(Type))
+
+#else /* You need to include typemaps.i */
+
+
+#define %value_output_typemap(Type...)
+#define %value_input_typemap(Type...)
+#define %value_inout_typemap(Type...)
+#define %ptr_input_typemap(Type...)
+#define %ptr_inout_typemap(Type...)
+
+#endif /* SWIG_INOUT_DEFAULT */
+
+/*----------------------------------------------------------------------
+ Front ends.
+
+ use the following macros to define your own IN/OUTPUT/INOUT typemaps
+
+ ------------------------------------------------------------------------*/
+%define %typemaps_inout(Code, AsValMeth, FromMeth, AsValFrag, FromFrag, Type...)
+ %_value_input_typemap(%arg(Code), %arg(AsValMeth),
+ %arg(AsValFrag), %arg(Type));
+ %_value_output_typemap(%arg(FromMeth), %arg(FromFrag), %arg(Type));
+ %_value_inout_typemap(%arg(Type));
+%enddef
+
+%define %typemaps_inoutn(Code,Type...)
+ %typemaps_inout(%arg(Code),
+ %arg(SWIG_AsVal(Type)),
+ %arg(SWIG_From(Type)),
+ %arg(SWIG_AsVal_frag(Type)),
+ %arg(SWIG_From_frag(Type)),
+ %arg(Type));
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/misctypes.swg b/contrib/tools/swig/Lib/typemaps/misctypes.swg
new file mode 100644
index 00000000000..09c81d74335
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/misctypes.swg
@@ -0,0 +1,21 @@
+
+/* ------------------------------------------------------------
+ * --- ANSI/Posix C/C++ types ---
+ * ------------------------------------------------------------ */
+
+
+#ifdef __cplusplus
+
+%apply size_t { std::size_t };
+%apply const size_t& { const std::size_t& };
+
+%apply ptrdiff_t { std::ptrdiff_t };
+%apply const ptrdiff_t& { const std::ptrdiff_t& };
+
+#ifndef SWIG_INOUT_NODEF
+%apply size_t& { std::size_t& };
+%apply ptrdiff_t& { std::ptrdiff_t& };
+#endif
+
+#endif
+
diff --git a/contrib/tools/swig/Lib/typemaps/primtypes.swg b/contrib/tools/swig/Lib/typemaps/primtypes.swg
new file mode 100644
index 00000000000..85a0b8d9b8e
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/primtypes.swg
@@ -0,0 +1,369 @@
+/* ------------------------------------------------------------
+ * Primitive type fragments and macros
+ * ------------------------------------------------------------ */
+
+/*
+ This file provide fragments and macros for the C/C++ primitive types.
+
+ The file defines default fragments for the following types:
+
+ bool
+ signed char
+ unsigned char
+ signed wchar_t // in C++
+ unsigned wchar_t // in C++
+ short
+ unsigned short
+ int
+ unsigned int
+ float
+ size_t
+ ptrdiff_t
+
+ which can always be redefined in the swig target language if needed.
+
+ The fragments for the following types, however, always need to be
+ defined in the target language:
+
+ long
+ unsigned long
+ long long
+ unsigned long long
+ double
+
+ If they are not provided, an #error directive will appear in the
+ wrapped code.
+
+ --------------------------------------------------------------------
+
+ This file provides the macro
+
+ %typemaps_primitive(CheckCode, Type)
+
+ which generates the typemaps for a primitive type with a given
+ checkcode. It is assumed that the primitive type is 'normalized' and
+ the corresponding SWIG_AsVal(Type) and SWIG_From(Type) methods are
+ provided via fragments.
+
+
+ The following auxiliary macros (explained with bash pseudo code) are
+ also defined:
+
+ %apply_ctypes(Macro)
+ for i in C Type
+ do
+ Macro($i)
+ done
+
+ %apply_cpptypes(Macro)
+ for i in C++ Type
+ do
+ Macro($i)
+ done
+
+ %apply_ctypes_2(Macro2)
+ for i in C Type
+ do
+ for j in C Type
+ do
+ Macro_2($i, $j)
+ done
+ done
+
+ %apply_cpptypes_2(Macro2)
+ for i in C++ Type
+ do
+ for j in C++ Type
+ do
+ Macro_2($i, $j)
+ done
+ done
+
+ %apply_checkctypes(Macro2)
+ for i in Check Type
+ do
+ Macro2(%checkcode($i), $i)
+ done
+
+*/
+
+
+/* ------------------------------------------------------------
+ * Primitive type fragments
+ * ------------------------------------------------------------ */
+/* boolean */
+
+%fragment(SWIG_From_frag(bool),"header",fragment=SWIG_From_frag(long)) {
+SWIGINTERN SWIG_Object
+SWIG_From_dec(bool)(bool value)
+{
+ return SWIG_From(long)(value ? 1 : 0);
+}
+}
+
+%fragment(SWIG_AsVal_frag(bool),"header",fragment=SWIG_AsVal_frag(long)) {
+SWIGINTERN int
+SWIG_AsVal_dec(bool)(SWIG_Object obj, bool *val)
+{
+ long v;
+ int res = SWIG_AsVal(long)(obj, val ? &v : 0);
+ if (SWIG_IsOK(res)) {
+ if (val) *val = v ? true : false;
+ return res;
+ }
+ return SWIG_TypeError;
+}
+}
+
+/* signed/unsigned char */
+
+%numeric_slong(signed char, "<limits.h>", SCHAR_MIN, SCHAR_MAX)
+%numeric_ulong(unsigned char, "<limits.h>", UCHAR_MAX)
+
+/* short/unsigned short */
+
+%numeric_slong(short, "<limits.h>", SHRT_MIN, SHRT_MAX)
+%numeric_ulong(unsigned short, "<limits.h>", USHRT_MAX)
+
+/* int/unsigned int */
+
+%numeric_slong(int, "<limits.h>", INT_MIN, INT_MAX)
+%numeric_ulong(unsigned int, "<limits.h>", UINT_MAX)
+
+/* signed/unsigned wchar_t */
+
+#ifdef __cplusplus
+%numeric_slong(signed wchar_t, "<wchar.h>", WCHAR_MIN, WCHAR_MAX)
+%numeric_ulong(unsigned wchar_t, "<wchar.h>", UWCHAR_MAX)
+#endif
+
+/* float */
+
+%numeric_float(float, "SWIG_Float_Overflow_Check", SWIG_Float_Overflow_Check(v))
+
+/* long/unsigned long */
+
+%ensure_type_fragments(long)
+%ensure_type_fragments(unsigned long)
+
+/* long long/unsigned long long */
+
+%fragment("SWIG_LongLongAvailable","header", fragment="<limits.h>") %{
+#if defined(LLONG_MAX) && !defined(SWIG_LONG_LONG_AVAILABLE)
+# define SWIG_LONG_LONG_AVAILABLE
+#endif
+%}
+
+%ensure_type_fragments(long long)
+%ensure_type_fragments(unsigned long long)
+
+/* double */
+
+%ensure_type_fragments(double)
+
+/* size_t */
+
+%fragment(SWIG_From_frag(size_t),"header",fragment=SWIG_From_frag(unsigned long),fragment=SWIG_From_frag(unsigned long long)) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From_dec(size_t)(size_t value)
+{
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ if (sizeof(size_t) <= sizeof(unsigned long)) {
+%#endif
+ return SWIG_From(unsigned long)(%numeric_cast(value, unsigned long));
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ } else {
+ /* assume sizeof(size_t) <= sizeof(unsigned long long) */
+ return SWIG_From(unsigned long long)(%numeric_cast(value, unsigned long long));
+ }
+%#endif
+}
+}
+
+%fragment(SWIG_AsVal_frag(size_t),"header",fragment=SWIG_AsVal_frag(unsigned long),fragment=SWIG_AsVal_frag(unsigned long long)) {
+SWIGINTERNINLINE int
+SWIG_AsVal_dec(size_t)(SWIG_Object obj, size_t *val)
+{
+ int res = SWIG_TypeError;
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ if (sizeof(size_t) <= sizeof(unsigned long)) {
+%#endif
+ unsigned long v;
+ res = SWIG_AsVal(unsigned long)(obj, val ? &v : 0);
+ if (SWIG_IsOK(res) && val) *val = %numeric_cast(v, size_t);
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ } else if (sizeof(size_t) <= sizeof(unsigned long long)) {
+ unsigned long long v;
+ res = SWIG_AsVal(unsigned long long)(obj, val ? &v : 0);
+ if (SWIG_IsOK(res) && val) *val = %numeric_cast(v, size_t);
+ }
+%#endif
+ return res;
+}
+}
+
+/* ptrdiff_t */
+
+%fragment(SWIG_From_frag(ptrdiff_t),"header",fragment=SWIG_From_frag(long),fragment=SWIG_From_frag(long long)) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From_dec(ptrdiff_t)(ptrdiff_t value)
+{
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ if (sizeof(ptrdiff_t) <= sizeof(long)) {
+%#endif
+ return SWIG_From(long)(%numeric_cast(value, long));
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ } else {
+ /* assume sizeof(ptrdiff_t) <= sizeof(long long) */
+ return SWIG_From(long long)(%numeric_cast(value, long long));
+ }
+%#endif
+}
+}
+
+%fragment(SWIG_AsVal_frag(ptrdiff_t),"header",fragment=SWIG_AsVal_frag(long),fragment=SWIG_AsVal_frag(long long)) {
+SWIGINTERNINLINE int
+SWIG_AsVal_dec(ptrdiff_t)(SWIG_Object obj, ptrdiff_t *val)
+{
+ int res = SWIG_TypeError;
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ if (sizeof(ptrdiff_t) <= sizeof(long)) {
+%#endif
+ long v;
+ res = SWIG_AsVal(long)(obj, val ? &v : 0);
+ if (SWIG_IsOK(res) && val) *val = %numeric_cast(v, ptrdiff_t);
+%#ifdef SWIG_LONG_LONG_AVAILABLE
+ } else if (sizeof(ptrdiff_t) <= sizeof(long long)) {
+ long long v;
+ res = SWIG_AsVal(long long)(obj, val ? &v : 0);
+ if (SWIG_IsOK(res) && val) *val = %numeric_cast(v, ptrdiff_t);
+ }
+%#endif
+ return res;
+}
+}
+
+
+%fragment("SWIG_CanCastAsInteger","header",
+ fragment=SWIG_AsVal_frag(double),
+ fragment="<float.h>",
+ fragment="<math.h>") {
+SWIGINTERNINLINE int
+SWIG_CanCastAsInteger(double *d, double min, double max) {
+ double x = *d;
+ if ((min <= x && x <= max)) {
+ double fx, cx, rd;
+ errno = 0;
+ fx = floor(x);
+ cx = ceil(x);
+ rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */
+ if ((errno == EDOM) || (errno == ERANGE)) {
+ errno = 0;
+ } else {
+ double summ, reps, diff;
+ if (rd < x) {
+ diff = x - rd;
+ } else if (rd > x) {
+ diff = rd - x;
+ } else {
+ return 1;
+ }
+ summ = rd + x;
+ reps = diff/summ;
+ if (reps < 8*DBL_EPSILON) {
+ *d = rd;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+}
+
+/* ------------------------------------------------------------
+ * Generate the typemaps for primitive type
+ * ------------------------------------------------------------ */
+
+#define %typemaps_primitive(Code, Type) %typemaps_asvalfromn(%arg(Code), Type)
+
+/* ------------------------------------------------------------
+ * Primitive Type Macros
+ * ------------------------------------------------------------ */
+
+/* useful macros to derive typemap declarations from primitive types */
+
+%define _apply_macro(macro, arg2, arg1...)
+#if #arg1 != ""
+macro(%arg(arg1),arg2);
+#else
+macro(arg2);
+#endif
+%enddef
+
+/* Apply macro to the C-types */
+%define %apply_ctypes(Macro, Arg2...)
+_apply_macro(Macro, bool , Arg2);
+_apply_macro(Macro, signed char , Arg2);
+_apply_macro(Macro, unsigned char , Arg2);
+_apply_macro(Macro, short , Arg2);
+_apply_macro(Macro, unsigned short , Arg2);
+_apply_macro(Macro, int , Arg2);
+_apply_macro(Macro, unsigned int , Arg2);
+_apply_macro(Macro, long , Arg2);
+_apply_macro(Macro, unsigned long , Arg2);
+_apply_macro(Macro, long long , Arg2);
+_apply_macro(Macro, unsigned long long , Arg2);
+_apply_macro(Macro, float , Arg2);
+_apply_macro(Macro, double , Arg2);
+_apply_macro(Macro, char , Arg2);
+_apply_macro(Macro, wchar_t , Arg2);
+_apply_macro(Macro, size_t , Arg2);
+_apply_macro(Macro, ptrdiff_t , Arg2);
+%enddef
+
+/* apply the Macro2(Type1, Type2) to all C types */
+#define %apply_ctypes_2(Macro2) %apply_ctypes(%apply_ctypes, Macro2)
+
+
+/* apply the Macro(Type) to all C++ types */
+%define %apply_cpptypes(Macro, Arg2...)
+%apply_ctypes(Macro, Arg2)
+_apply_macro(Macro, std::size_t, Arg2);
+_apply_macro(Macro, std::ptrdiff_t, Arg2);
+_apply_macro(Macro, std::string, Arg2);
+_apply_macro(Macro, std::wstring, Arg2);
+_apply_macro(Macro, std::complex<float>, Arg2);
+_apply_macro(Macro, std::complex<double>, Arg2);
+%enddef
+
+/* apply the Macro2(Type1, Type2) to all C++ types */
+#define %apply_cpptypes_2(Macro2) %apply_cpptypes(%apply_cpptypes, Macro2)
+
+/* apply the Macro2(CheckCode,Type) to all Checked Types */
+%define %apply_checkctypes(Macro2)
+Macro2(%checkcode(BOOL), bool);
+Macro2(%checkcode(INT8), signed char);
+Macro2(%checkcode(UINT8), unsigned char);
+Macro2(%checkcode(INT16), short);
+Macro2(%checkcode(UINT16), unsigned short);
+Macro2(%checkcode(INT32), int);
+Macro2(%checkcode(UINT32), unsigned int);
+Macro2(%checkcode(INT64), long);
+Macro2(%checkcode(UINT64), unsigned long);
+Macro2(%checkcode(INT128), long long);
+Macro2(%checkcode(UINT128), unsigned long long);
+Macro2(%checkcode(FLOAT), float);
+Macro2(%checkcode(DOUBLE), double);
+Macro2(%checkcode(CHAR), char);
+Macro2(%checkcode(UNICHAR), wchar_t);
+Macro2(%checkcode(SIZE), size_t);
+Macro2(%checkcode(PTRDIFF), ptrdiff_t);
+%enddef
+
+
+/* ------------------------------------------------------------
+ * Generate the typemaps for all the primitive types with checkcode
+ * ------------------------------------------------------------ */
+
+%apply_checkctypes(%typemaps_primitive);
+
diff --git a/contrib/tools/swig/Lib/typemaps/ptrtypes.swg b/contrib/tools/swig/Lib/typemaps/ptrtypes.swg
new file mode 100644
index 00000000000..8619b31800e
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/ptrtypes.swg
@@ -0,0 +1,228 @@
+/* -----------------------------------------------------------------------------
+ * ptrtypes.swg
+ *
+ * Value typemaps (Type, const Type&) for "Ptr" types, such as swig
+ * wrapped classes, that define the AsPtr/From methods
+ *
+ * To apply them, just use one of the following macros:
+ *
+ * %typemaps_asptr(CheckCode, AsPtrMeth, AsPtrFrag, Type)
+ * %typemaps_asptrfrom(CheckCode, AsPtrMeth, FromMeth, AsPtrFrag, FromFrag, Type)
+ *
+ * or the simpler and normalize form:
+ *
+ * %typemaps_asptrfromn(CheckCode, Type)
+ *
+ * Also, you can use the individual typemap definitions:
+ *
+ * %ptr_in_typemap(asptr_meth,frag,Type)
+ * %ptr_varin_typemap(asptr_meth,frag,Type)
+ * %ptr_typecheck_typemap(check,asptr_meth,frag,Type)
+ * %ptr_directorout_typemap(asptr_meth,frag,Type)
+ * ----------------------------------------------------------------------------- */
+
+%include <typemaps/valtypes.swg>
+
+/* in */
+
+%define %ptr_in_typemap(asptr_meth,frag,Type...)
+ %typemap(in,fragment=frag) Type {
+ Type *ptr = (Type *)0;
+ int res = asptr_meth($input, &ptr);
+ if (!SWIG_IsOK(res) || !ptr) {
+ %argument_fail((ptr ? res : SWIG_TypeError), "$type", $symname, $argnum);
+ }
+ $1 = *ptr;
+ if (SWIG_IsNewObj(res)) %delete(ptr);
+ }
+ %typemap(freearg) Type ""
+ %typemap(in,fragment=frag) const Type & (int res = SWIG_OLDOBJ) {
+ Type *ptr = (Type *)0;
+ res = asptr_meth($input, &ptr);
+ if (!SWIG_IsOK(res)) { %argument_fail(res,"$type",$symname, $argnum); }
+ if (!ptr) { %argument_nullref("$type",$symname, $argnum); }
+ $1 = ptr;
+ }
+ %typemap(freearg,noblock=1) const Type & {
+ if (SWIG_IsNewObj(res$argnum)) %delete($1);
+ }
+%enddef
+
+/* varin */
+
+%define %ptr_varin_typemap(asptr_meth,frag,Type...)
+ %typemap(varin,fragment=frag) Type {
+ Type *ptr = (Type *)0;
+ int res = asptr_meth($input, &ptr);
+ if (!SWIG_IsOK(res) || !ptr) {
+ %variable_fail((ptr ? res : SWIG_TypeError), "$type", "$name");
+ }
+ $1 = *ptr;
+ if (SWIG_IsNewObj(res)) %delete(ptr);
+ }
+%enddef
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+/* directorout */
+
+%define %ptr_directorout_typemap(asptr_meth,frag,Type...)
+ %typemap(directorargout,noblock=1,fragment=frag) Type *DIRECTOROUT ($*ltype temp, int swig_ores) {
+ Type *swig_optr = 0;
+ swig_ores = $result ? asptr_meth($result, &swig_optr) : 0;
+ if (!SWIG_IsOK(swig_ores) || !swig_optr) {
+ %dirout_fail((swig_optr ? swig_ores : SWIG_TypeError),"$type");
+ }
+ temp = *swig_optr;
+ $1 = &temp;
+ if (SWIG_IsNewObj(swig_ores)) %delete(swig_optr);
+ }
+
+ %typemap(directorout,noblock=1,fragment=frag) Type {
+ Type *swig_optr = 0;
+ int swig_ores = asptr_meth($input, &swig_optr);
+ if (!SWIG_IsOK(swig_ores) || !swig_optr) {
+ %dirout_fail((swig_optr ? swig_ores : SWIG_TypeError),"$type");
+ }
+ $result = *swig_optr;
+ if (SWIG_IsNewObj(swig_ores)) %delete(swig_optr);
+ }
+
+ %typemap(directorout,noblock=1,fragment=frag,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) Type* {
+ Type *swig_optr = 0;
+ int swig_ores = asptr_meth($input, &swig_optr);
+ if (!SWIG_IsOK(swig_ores)) {
+ %dirout_fail(swig_ores,"$type");
+ }
+ $result = swig_optr;
+ if (SWIG_IsNewObj(swig_ores)) {
+ swig_acquire_ownership(swig_optr);
+ }
+ }
+ %typemap(directorfree,noblock=1) Type*
+ {
+ if (director) {
+ director->swig_release_ownership(%as_voidptr($input));
+ }
+ }
+
+ %typemap(directorout,noblock=1,fragment=frag,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) Type& {
+ Type *swig_optr = 0;
+ int swig_ores = asptr_meth($input, &swig_optr);
+ if (!SWIG_IsOK(swig_ores)) {
+ %dirout_fail(swig_ores,"$type");
+ } else {
+ if (!swig_optr) {
+ %dirout_nullref("$type");
+ }
+ }
+ $result = swig_optr;
+ if (SWIG_IsNewObj(swig_ores)) {
+ swig_acquire_ownership(swig_optr);
+ }
+ }
+ %typemap(directorfree,noblock=1) Type&
+ {
+ if (director) {
+ director->swig_release_ownership(%as_voidptr($input));
+ }
+ }
+
+
+ %typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type
+
+%enddef
+
+#else
+
+#define %ptr_directorout_typemap(asptr_meth,frag,Type...)
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
+/* typecheck */
+
+%define %ptr_typecheck_typemap(check,asptr_meth,frag,Type...)
+%typemap(typecheck,noblock=1,precedence=check,fragment=frag) Type * {
+ int res = asptr_meth($input, (Type**)(0));
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,noblock=1,precedence=check,fragment=frag) Type, const Type& {
+ int res = asptr_meth($input, (Type**)(0));
+ $1 = SWIG_CheckState(res);
+}
+%enddef
+
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with asptr method
+ *---------------------------------------------------------------------*/
+
+%define %typemaps_asptr(CheckCode, AsPtrMeth, AsPtrFrag, Type...)
+ %fragment(SWIG_AsVal_frag(Type),"header",fragment=SWIG_AsPtr_frag(Type)) {
+ SWIGINTERNINLINE int
+ SWIG_AsVal(Type)(SWIG_Object obj, Type *val)
+ {
+ Type *v = (Type *)0;
+ int res = SWIG_AsPtr(Type)(obj, &v);
+ if (!SWIG_IsOK(res)) return res;
+ if (v) {
+ if (val) *val = *v;
+ if (SWIG_IsNewObj(res)) {
+ %delete(v);
+ res = SWIG_DelNewMask(res);
+ }
+ return res;
+ }
+ return SWIG_ERROR;
+ }
+ }
+ %ptr_in_typemap(%arg(AsPtrMeth), %arg(AsPtrFrag), Type);
+ %ptr_varin_typemap(%arg(AsPtrMeth), %arg(AsPtrFrag), Type);
+ %ptr_directorout_typemap(%arg(AsPtrMeth), %arg(AsPtrFrag), Type);
+ %ptr_typecheck_typemap(%arg(CheckCode), %arg(AsPtrMeth),%arg(AsPtrFrag), Type);
+ %ptr_input_typemap(%arg(CheckCode),%arg(AsPtrMeth),%arg(AsPtrFrag),Type);
+%enddef
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with from method for ptr types
+ * Same as typemaps_from but without varout typemap
+ *---------------------------------------------------------------------*/
+
+%define %ptr_typemaps_from(FromMeth, FromFrag, Type...)
+ %value_out_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ /* No varout typemap */
+ %value_constcode_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_directorin_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_throws_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_output_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+%enddef
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with asptr/from methods
+ *---------------------------------------------------------------------*/
+
+%define %typemaps_asptrfrom(CheckCode, AsPtrMeth, FromMeth, AsPtrFrag, FromFrag, Type...)
+ %typemaps_asptr(%arg(CheckCode), %arg(AsPtrMeth), %arg(AsPtrFrag), Type)
+ %ptr_typemaps_from(%arg(FromMeth), %arg(FromFrag), Type);
+ %ptr_inout_typemap(Type);
+%enddef
+
+// Same as typemaps_asptrfrom but defines a varout typemap to wrap with value semantics instead of the default pointer semantics
+%define %_typemaps_asptrfrom(CheckCode, AsPtrMeth, FromMeth, AsPtrFrag, FromFrag, Type...)
+ %typemaps_asptr(%arg(CheckCode), %arg(AsPtrMeth), %arg(AsPtrFrag), Type)
+ %typemaps_from(%arg(FromMeth), %arg(FromFrag), Type);
+ %ptr_inout_typemap(Type);
+%enddef
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with for 'normalized' asptr/from methods
+ *---------------------------------------------------------------------*/
+
+%define %typemaps_asptrfromn(CheckCode, Type...)
+%_typemaps_asptrfrom(%arg(CheckCode),
+ %arg(SWIG_AsPtr(Type)),
+ %arg(SWIG_From(Type)),
+ %arg(SWIG_AsPtr_frag(Type)),
+ %arg(SWIG_From_frag(Type)),
+ Type);
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/std_except.swg b/contrib/tools/swig/Lib/typemaps/std_except.swg
new file mode 100644
index 00000000000..75d066490fd
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/std_except.swg
@@ -0,0 +1,37 @@
+%include <typemaps/exception.swg>
+
+/*
+ Mark all of std exception classes as "exception classes" via
+ the "exceptionclass" feature.
+
+ If needed, you can disable it by using %noexceptionclass.
+*/
+
+%define %std_exception_map(Exception, Code)
+ %exceptionclass Exception;
+#if !defined(SWIG_STD_EXCEPTIONS_AS_CLASSES)
+ %typemap(throws,noblock=1) Exception {
+ SWIG_exception_fail(Code, $1.what());
+ }
+ %ignore Exception;
+ struct Exception {
+ };
+#endif
+%enddef
+
+namespace std {
+ %std_exception_map(bad_cast, SWIG_TypeError);
+ %std_exception_map(bad_exception, SWIG_SystemError);
+ %std_exception_map(domain_error, SWIG_ValueError);
+ %std_exception_map(exception, SWIG_SystemError);
+ %std_exception_map(invalid_argument, SWIG_ValueError);
+ %std_exception_map(length_error, SWIG_IndexError);
+ %std_exception_map(logic_error, SWIG_RuntimeError);
+ %std_exception_map(out_of_range, SWIG_IndexError);
+ %std_exception_map(overflow_error, SWIG_OverflowError);
+ %std_exception_map(range_error, SWIG_OverflowError);
+ %std_exception_map(runtime_error, SWIG_RuntimeError);
+ %std_exception_map(underflow_error, SWIG_OverflowError);
+}
+
+%include <std/std_except.i>
diff --git a/contrib/tools/swig/Lib/typemaps/std_string.swg b/contrib/tools/swig/Lib/typemaps/std_string.swg
new file mode 100644
index 00000000000..5b57beab560
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/std_string.swg
@@ -0,0 +1,25 @@
+//
+// String
+//
+
+
+#ifndef SWIG_STD_BASIC_STRING
+#define SWIG_STD_STRING
+
+%include <typemaps/std_strings.swg>
+
+%fragment("<string>");
+
+namespace std
+{
+ %naturalvar string;
+ class string;
+}
+
+%typemaps_std_string(std::string, char, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, %checkcode(STDSTRING));
+
+#else
+
+%include <std/std_string.i>
+
+#endif
diff --git a/contrib/tools/swig/Lib/typemaps/std_string_view.swg b/contrib/tools/swig/Lib/typemaps/std_string_view.swg
new file mode 100644
index 00000000000..24f57c6c007
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/std_string_view.swg
@@ -0,0 +1,16 @@
+//
+// string_view
+//
+
+
+%include <typemaps/std_strings.swg>
+
+%fragment("<string_view>");
+
+namespace std
+{
+ %naturalvar string_view;
+ class string_view;
+}
+
+%typemaps_std_string_view(std::string_view, char, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize, %checkcode(STRINGVIEW));
diff --git a/contrib/tools/swig/Lib/typemaps/std_strings.swg b/contrib/tools/swig/Lib/typemaps/std_strings.swg
new file mode 100644
index 00000000000..28ef5e48d55
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/std_strings.swg
@@ -0,0 +1,99 @@
+
+/* defining the String asptr/from methods */
+
+%define %std_string_asptr(String, Char, SWIG_AsCharPtrAndSize, Frag)
+%fragment(SWIG_AsPtr_frag(String),"header",fragment=Frag) {
+SWIGINTERN int
+SWIG_AsPtr_dec(String)(SWIG_Object obj, String **val)
+{
+ Char* buf = 0 ; size_t size = 0; int alloc = SWIG_OLDOBJ;
+ if (SWIG_IsOK((SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc)))) {
+ if (buf) {
+ if (val) *val = new String(buf, size - 1);
+ if (alloc == SWIG_NEWOBJ) %delete_array(buf);
+ return SWIG_NEWOBJ;
+ } else {
+ if (val) *val = 0;
+ return SWIG_OLDOBJ;
+ }
+ } else {
+ %error_clear;
+ static swig_type_info *descriptor = SWIG_TypeQuery(#String " *");
+ if (descriptor) {
+ String *vptr;
+ int res = SWIG_ConvertPtr(obj, (void**)&vptr, descriptor, 0);
+ if (SWIG_IsOK(res) && val) *val = vptr;
+ return res;
+ }
+ }
+ return SWIG_ERROR;
+}
+}
+%enddef
+
+%define %std_string_from(String, SWIG_FromCharPtrAndSize, Frag)
+%fragment(SWIG_From_frag(String),"header",fragment=Frag) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From_dec(String)(const String& s)
+{
+ return SWIG_FromCharPtrAndSize(s.data(), s.size());
+}
+}
+%enddef
+
+%define %std_string_view_from(String, SWIG_FromCharPtrAndSize, Frag)
+%fragment(SWIG_From_frag(String),"header",fragment=Frag) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From_dec(String)(const String& s)
+{
+ return SWIG_FromCharPtrAndSize(s.data() ? s.data() : "", s.size());
+}
+}
+%enddef
+
+%define %std_string_asval(String)
+%fragment(SWIG_AsVal_frag(String),"header", fragment=SWIG_AsPtr_frag(String)) {
+SWIGINTERN int
+SWIG_AsVal_dec(String)(SWIG_Object obj, String *val)
+{
+ String* v = (String *) 0;
+ int res = SWIG_AsPtr(String)(obj, &v);
+ if (!SWIG_IsOK(res)) return res;
+ if (v) {
+ if (val) *val = *v;
+ if (SWIG_IsNewObj(res)) {
+ %delete(v);
+ res = SWIG_DelNewMask(res);
+ }
+ return res;
+ }
+ return SWIG_ERROR;
+}
+}
+%enddef
+
+
+%define %typemaps_std_string(String, Char, AsPtrMethod, FromMethod, CheckCode)
+
+%std_string_asptr(String, Char, AsPtrMethod, #AsPtrMethod)
+%std_string_asval(String)
+%std_string_from(String, FromMethod, #FromMethod)
+
+%typemaps_asptrfromn(%arg(CheckCode), String);
+
+%enddef
+
+
+/* An empty string_view returns NULL from data() but SWIG_FromCharPtrAndSize()
+ * implementations treat that as invalid and return None/Null/undef or similar
+ * in the target language so we can't just use %typemaps_std_string.
+ */
+%define %typemaps_std_string_view(String, Char, AsPtrMethod, FromMethod, CheckCode)
+
+%std_string_asptr(String, Char, AsPtrMethod, #AsPtrMethod)
+%std_string_asval(String)
+%std_string_view_from(String, FromMethod, #FromMethod)
+
+%typemaps_asptrfromn(%arg(CheckCode), String);
+
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/std_wstring.swg b/contrib/tools/swig/Lib/typemaps/std_wstring.swg
new file mode 100644
index 00000000000..4a2830bb929
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/std_wstring.swg
@@ -0,0 +1,26 @@
+%include <typemaps/wstring.swg>
+
+#ifndef SWIG_STD_BASIC_STRING
+#define SWIG_STD_WSTRING
+
+%include <typemaps/std_strings.swg>
+
+%{
+#include <cwchar>
+%}
+%fragment("<string>");
+
+namespace std
+{
+ %naturalvar wstring;
+ class wstring;
+}
+
+%typemaps_std_string(std::wstring, wchar_t, SWIG_AsWCharPtrAndSize, SWIG_FromWCharPtrAndSize, %checkcode(STDUNISTRING));
+
+
+#else
+
+%include <std/std_wstring.i>
+
+#endif
diff --git a/contrib/tools/swig/Lib/typemaps/string.swg b/contrib/tools/swig/Lib/typemaps/string.swg
new file mode 100644
index 00000000000..59548d8e269
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/string.swg
@@ -0,0 +1,34 @@
+%ensure_fragment(SWIG_AsCharPtrAndSize)
+%ensure_fragment(SWIG_FromCharPtrAndSize)
+
+%types(char *);
+
+%fragment("SWIG_pchar_descriptor","header") {
+SWIGINTERN swig_type_info*
+SWIG_pchar_descriptor(void)
+{
+ static swig_type_info* info = 0;
+ if (!info) {
+ info = SWIG_TypeQuery("_p_char");
+ }
+ return info;
+}
+}
+
+%fragment("SWIG_strnlen","header",fragment="SWIG_FromCharPtrAndSize") {
+SWIGINTERN size_t
+SWIG_strnlen(const char* s, size_t maxlen)
+{
+ const char *p;
+ for (p = s; maxlen-- && *p; p++)
+ ;
+ return p - s;
+}
+}
+
+%include <typemaps/strings.swg>
+%typemaps_string(%checkcode(STRING), %checkcode(CHAR),
+ SWIGWARN_TYPEMAP_CHARLEAK_MSG,
+ char, Char, SWIG_AsCharPtrAndSize, SWIG_FromCharPtrAndSize,
+ strlen, SWIG_strnlen,
+ "<limits.h>", CHAR_MIN, CHAR_MAX)
diff --git a/contrib/tools/swig/Lib/typemaps/strings.swg b/contrib/tools/swig/Lib/typemaps/strings.swg
new file mode 100644
index 00000000000..339d4a676aa
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/strings.swg
@@ -0,0 +1,649 @@
+//
+// Use the macro SWIG_PRESERVE_CARRAY_SIZE if you prefer to preserve
+// the size of char arrays, ie
+// ------------------------------------------
+// C Side => Language Side
+// ------------------------------------------
+// char name[5] = "hola" => 'hola\0'
+//
+// the default behaviour is
+//
+// char name[5] = "hola" => 'hola'
+//
+//
+//#define SWIG_PRESERVE_CARRAY_SIZE
+
+/* ------------------------------------------------------------
+ * String typemaps for type Char (char or wchar_t)
+ * ------------------------------------------------------------ */
+
+%define %_typemap_string(StringCode,
+ Char,
+ WarningLeakMsg,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ SWIG_AsCharPtr,
+ SWIG_FromCharPtr,
+ SWIG_AsCharArray,
+ SWIG_NewCopyCharArray,
+ SWIG_DeleteCharArray)
+
+/* in */
+
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtr)
+ Char * (int res, Char *buf = 0, int alloc = 0),
+ const Char * (int res, Char *buf = 0, int alloc = 0) {
+ res = SWIG_AsCharPtr($input, &buf, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $1 = %reinterpret_cast(buf, $1_ltype);
+}
+%typemap(freearg,noblock=1,match="in") Char *, const Char * {
+ if (alloc$argnum == SWIG_NEWOBJ) SWIG_DeleteCharArray(buf$argnum);
+}
+
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtr) Char const*& (int res, Char *buf = 0, int alloc = 0) {
+ res = SWIG_AsCharPtr($input, &buf, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $1 = &buf;
+}
+%typemap(freearg, noblock=1,match="in") Char const*& {
+ if (alloc$argnum == SWIG_NEWOBJ) SWIG_DeleteCharArray(buf$argnum);
+}
+
+/* out */
+
+%typemap(out,noblock=1,fragment=#SWIG_FromCharPtr) Char *, const Char * {
+ %set_output(SWIG_FromCharPtr((const Char *)$1));
+}
+
+
+%typemap(out,noblock=1,fragment=#SWIG_FromCharPtr) Char const*& {
+ %set_output(SWIG_FromCharPtr(*$1));
+}
+
+%typemap(newfree,noblock=1) Char * {
+ SWIG_DeleteCharArray($1);
+}
+
+/* varin */
+
+%typemap(varin,fragment=#SWIG_AsCharPtrAndSize) Char * {
+ Char *cptr = 0; size_t csize = 0; int alloc = SWIG_NEWOBJ;
+ int res = SWIG_AsCharPtrAndSize($input, &cptr, &csize, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res,"$type","$name");
+ }
+ SWIG_DeleteCharArray($1);
+ if (alloc == SWIG_NEWOBJ) {
+ $1 = cptr;
+ } else {
+ $1 = csize ? ($1_type)SWIG_NewCopyCharArray(cptr, csize, Char) : 0;
+ }
+}
+
+%typemap(varin,fragment=#SWIG_AsCharPtrAndSize,warning=WarningLeakMsg) const Char * {
+ Char *cptr = 0; size_t csize = 0; int alloc = SWIG_NEWOBJ;
+ int res = SWIG_AsCharPtrAndSize($input, &cptr, &csize, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ if (alloc == SWIG_NEWOBJ) {
+ $1 = cptr;
+ } else {
+ $1 = csize ? ($1_type)SWIG_NewCopyCharArray(cptr, csize, Char) : 0;
+ }
+}
+
+/* varout */
+
+%typemap(varout,noblock=1,fragment=#SWIG_FromCharPtr) Char *, const Char * {
+ %set_varoutput(SWIG_FromCharPtr($1));
+}
+
+/* memberin */
+
+%typemap(memberin,noblock=1) Char * {
+ SWIG_DeleteCharArray($1);
+ if ($input) {
+ size_t size = SWIG_CharPtrLen(%reinterpret_cast($input, const Char *)) + 1;
+ $1 = ($1_type)SWIG_NewCopyCharArray(%reinterpret_cast($input, const Char *), size, Char);
+ } else {
+ $1 = 0;
+ }
+}
+
+%typemap(memberin,noblock=1,warning=WarningLeakMsg) const Char * {
+ if ($input) {
+ size_t size = SWIG_CharPtrLen(%reinterpret_cast(%reinterpret_cast($input, const Char *), const Char *)) + 1;
+ $1 = ($1_type)SWIG_NewCopyCharArray($input, size, Char);
+ } else {
+ $1 = 0;
+ }
+}
+
+/* globalin */
+
+%typemap(globalin,noblock=1) Char * {
+ SWIG_DeleteCharArray($1);
+ if ($input) {
+ size_t size = SWIG_CharPtrLen(%reinterpret_cast(%reinterpret_cast($input, const Char *), const Char *)) + 1;
+ $1 = ($1_type)SWIG_NewCopyCharArray($input, size, Char);
+ } else {
+ $1 = 0;
+ }
+}
+
+%typemap(globalin,noblock=1,warning=WarningLeakMsg) const Char * {
+ if ($input) {
+ size_t size = SWIG_CharPtrLen($input) + 1;
+ $1 = ($1_type)SWIG_NewCopyCharArray($input, size, Char);
+ } else {
+ $1 = 0;
+ }
+}
+
+/* constant */
+
+%typemap(constcode,noblock=1,fragment=#SWIG_FromCharPtr)
+ Char *, Char const*, Char * const, Char const* const {
+ %set_constant("$symname", SWIG_FromCharPtr($value));
+}
+
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+
+%typemap(directorin,noblock=1,fragment=#SWIG_FromCharPtr)
+ Char *, Char const*, Char *const, Char const *const,
+ Char const *&, Char *const &, Char const *const & {
+ $input = SWIG_FromCharPtr((const Char *)$1);
+}
+
+
+/* directorout */
+
+%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) Char * (int res, Char *buf = 0, int alloc = SWIG_NEWOBJ) {
+ res = SWIG_AsCharPtr($input, &buf, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %dirout_fail(res, "$type");
+ }
+ if (alloc == SWIG_NEWOBJ) {
+ swig_acquire_ownership_array(buf);
+ }
+ $result = %reinterpret_cast(buf, $1_ltype);
+}
+%typemap(directorfree,noblock=1) Char *
+{
+ if (director) {
+ director->swig_release_ownership(%as_voidptr($input));
+ }
+}
+
+
+%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) Char *const& (int res, Char *buf = 0, int alloc = SWIG_NEWOBJ), Char const*const& (int res, Char *buf = 0, int alloc = SWIG_NEWOBJ) {
+ res = SWIG_AsCharPtr($input, &buf, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %dirout_fail(res, "$type");
+ }
+ static $*1_ltype tmp = buf;
+ $result = &tmp;
+ if (alloc == SWIG_NEWOBJ) {
+ swig_acquire_ownership_array(buf);
+ }
+}
+%typemap(directorfree,noblock=1)
+ Char * const&, Char const* const& {
+ if (director) {
+ director->swig_release_ownership(%as_voidptr(*$input));
+ }
+}
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
+/* typecheck */
+
+%typemap(typecheck,noblock=1,precedence=StringCode,
+ fragment=#SWIG_AsCharPtr) Char *, const Char *, Char const*& {
+ int res = SWIG_AsCharPtr($input, 0, 0);
+ $1 = SWIG_CheckState(res);
+}
+
+
+/* throws */
+
+%typemap(throws,noblock=1,fragment=#SWIG_FromCharPtr) Char * {
+ %raise(SWIG_FromCharPtr($1), "$type", 0);
+}
+
+
+/* ------------------------------------------------------------
+ * Unknown size const Character array Char[ANY] handling
+ * ------------------------------------------------------------ */
+
+%apply Char * { Char [] };
+%apply const Char * { const Char [] };
+
+%typemap(varin,noblock=1,warning="462:Unable to set variable of type Char []") Char []
+{
+ %variable_fail(SWIG_AttributeError, "$type", "read-only $name");
+}
+
+
+/* ------------------------------------------------------------
+ * Fixed size Character array Char[ANY] handling
+ * ------------------------------------------------------------ */
+
+/* memberin and globalin typemaps */
+
+%typemap(memberin,noblock=1) Char [ANY]
+{
+ if ($input) memcpy($1,$input,$1_dim0*sizeof(Char));
+ else memset($1,0,$1_dim0*sizeof(Char));
+}
+
+%typemap(globalin,noblock=1) Char [ANY]
+{
+ if ($input) memcpy($1,$input,$1_dim0*sizeof(Char));
+ else memset($1,0,$1_dim0*sizeof(Char));
+}
+
+/* in */
+
+%typemap(in,noblock=1,fragment=#SWIG_AsCharArray)
+ Char [ANY] (Char temp[$1_dim0], int res),
+ const Char [ANY](Char temp[$1_dim0], int res)
+{
+ res = SWIG_AsCharArray($input, temp, $1_dim0);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $1 = %reinterpret_cast(temp, $1_ltype);
+}
+%typemap(freearg) Char [ANY], const Char [ANY] ""
+
+%typemap(in,noblock=1,fragment=#SWIG_AsCharArray) const Char (&)[ANY] (Char temp[$1_dim0], int res)
+{
+ res = SWIG_AsCharArray($input, temp, $1_dim0);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $1 = &temp;
+}
+%typemap(freearg) const Char (&)[ANY] ""
+
+%typemap(out,fragment=#SWIG_FromCharPtrAndSize,fragment=#SWIG_CharBufLen)
+ Char [ANY], const Char[ANY]
+{
+%#ifndef SWIG_PRESERVE_CARRAY_SIZE
+ size_t size = SWIG_CharBufLen($1, $1_dim0);
+%#else
+ size_t size = $1_dim0;
+%#endif
+ %set_output(SWIG_FromCharPtrAndSize($1, size));
+}
+
+/* varin */
+
+%typemap(varin,fragment=#SWIG_AsCharArray) Char [ANY]
+{
+ int res = SWIG_AsCharArray($input, $1, $1_dim0);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+}
+
+/* varout */
+
+%typemap(varout,fragment=#SWIG_CharBufLen)
+ Char [ANY], const Char [ANY] {
+%#ifndef SWIG_PRESERVE_CARRAY_SIZE
+ size_t size = SWIG_CharBufLen($1, $1_dim0);
+%#else
+ size_t size = $1_dim0;
+%#endif
+ %set_varoutput(SWIG_FromCharPtrAndSize($1, size));
+}
+
+/* constant */
+
+%typemap(constcode,fragment=#SWIG_CharBufLen)
+ Char [ANY], const Char [ANY]
+{
+%#ifndef SWIG_PRESERVE_CARRAY_SIZE
+ size_t size = SWIG_CharBufLen($1, $1_dim0);
+%#else
+ size_t size = $value_dim0;
+%#endif
+ %set_constant("$symname", SWIG_FromCharPtrAndSize($value,size));
+}
+
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+%typemap(directorin,fragment=#SWIG_CharBufLen)
+ Char [ANY], const Char [ANY]
+{
+%#ifndef SWIG_PRESERVE_CARRAY_SIZE
+ size_t size = SWIG_CharBufLen($1, $1_dim0);
+%#else
+ size_t size = $1_dim0;
+%#endif
+ $input = SWIG_FromCharPtrAndSize($1, size);
+}
+
+/* directorout */
+
+%typemap(directorout,noblock=1,fragment=#SWIG_AsCharArray)
+ Char [ANY] (Char temp[$result_dim0]),
+ const Char [ANY] (Char temp[$result_dim0], int res)
+{
+ res = SWIG_AsCharArray($input, temp, $result_dim0);
+ if (!SWIG_IsOK(res)) {
+ %dirout_fail(res, "$type");
+ }
+ $result = temp;
+}
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
+/* typecheck */
+
+%typemap(typecheck,noblock=1,precedence=StringCode,
+ fragment=#SWIG_AsCharArray)
+ Char [ANY], const Char[ANY] {
+ int res = SWIG_AsCharArray($input, (Char *)0, $1_dim0);
+ $1 = SWIG_CheckState(res);
+}
+
+
+/* throws */
+
+%typemap(throws,fragment=#SWIG_CharBufLen)
+ Char [ANY], const Char[ANY]
+{
+%#ifndef SWIG_PRESERVE_CARRAY_SIZE
+ size_t size = SWIG_CharBufLen($1, $1_dim0);
+%#else
+ size_t size = $1_dim0;
+%#endif
+ %raise(SWIG_FromCharPtrAndSize($1, size), "$type", 0);
+}
+
+/* -------------------------------------------------------------------
+ * --- Really fix size Char arrays, including '\0'chars at the end ---
+ * ------------------------------------------------------------------- */
+
+%typemap(varout,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
+ Char FIXSIZE[ANY], const Char FIXSIZE[ANY]
+{
+ %set_varoutput(SWIG_FromCharPtrAndSize($1, $1_dim0));
+}
+
+%typemap(out,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
+ Char FIXSIZE[ANY], const Char FIXSIZE[ANY]
+{
+ %set_output(SWIG_FromCharPtrAndSize($1, $1_dim0));
+}
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+%typemap(directorin,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
+ Char FIXSIZE[ANY], const Char FIXSIZE[ANY]
+{
+ $input = SWIG_FromCharPtrAndSize($1, $1_dim0);
+}
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
+%typemap(throws,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
+ Char FIXSIZE[ANY], const Char FIXSIZE[ANY] {
+ %raise(SWIG_FromCharPtrAndSize($1, $1_dim0), "$type", 0);
+}
+
+/* ------------------------------------------------------------
+ * --- String & length ---
+ * ------------------------------------------------------------ */
+
+/* Here len doesn't include the '0' terminator */
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
+ (Char *STRING, size_t LENGTH) (int res, Char *buf = 0, size_t size = 0, int alloc = 0)
+{
+ res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $1 = %reinterpret_cast(buf, $1_ltype);
+ $2 = %numeric_cast(size - 1, $2_ltype);
+}
+%typemap(freearg,noblock=1,match="in") (Char *STRING, size_t LENGTH) {
+ if (alloc$argnum == SWIG_NEWOBJ) SWIG_DeleteCharArray(buf$argnum);
+}
+%typemap(directorin,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
+ (Char *STRING, size_t LENGTH)
+{
+ if ($1 && $2 > 0) {
+ $input = SWIG_FromCharPtrAndSize((const char*)$1, (size_t)$2);
+ } else {
+ $input = SWIG_FromCharPtrAndSize("", 0);
+ }
+}
+
+%typemap(in) (const Char *STRING, size_t LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(freearg) (const Char *STRING, size_t LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(directorin) (const Char *STRING, size_t LENGTH) = (Char *STRING, size_t LENGTH);
+
+/* old 'int' form */
+%typemap(in) (Char *STRING, int LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(freearg) (Char *STRING, int LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(directorin) (Char *STRING, int LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(in) (const Char *STRING, int LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(freearg) (const Char *STRING, int LENGTH) = (Char *STRING, size_t LENGTH);
+%typemap(directorin) (const Char *STRING, int LENGTH) = (Char *STRING, size_t LENGTH);
+
+/* reverse order typemap */
+
+%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
+ (size_t LENGTH, Char *STRING) (int res, Char *buf = 0, size_t size = 0, int alloc = 0)
+{
+ res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+ $2 = %reinterpret_cast(buf, $2_ltype);
+ $1 = %numeric_cast(size - 1, $1_ltype);
+}
+%typemap(freearg,noblock=1,match="in") (size_t LENGTH, Char *STRING) {
+ if (alloc$argnum == SWIG_NEWOBJ) SWIG_DeleteCharArray(buf$argnum);
+}
+%typemap(directorin,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
+ (size_t LENGTH, Char *STRING)
+{
+ if ($2 && $1 > 0) {
+ $input = SWIG_FromCharPtrAndSize((const char*)$2, (size_t)$1);
+ } else {
+ $input = SWIG_FromCharPtrAndSize("", 0);
+ }
+}
+
+%typemap(in) (size_t LENGTH, const Char *STRING) = (Char *STRING, size_t LENGTH);
+%typemap(freearg) (size_t LENGTH, const Char *STRING) = (Char *STRING, size_t LENGTH);
+%typemap(directorin) (size_t LENGTH, const Char *STRING) = (Char *STRING, size_t LENGTH);
+
+/* old 'int' form */
+%typemap(in) (int LENGTH, Char *STRING) = (size_t LENGTH, Char *STRING);
+%typemap(freearg) (int LENGTH, Char *STRING) = (size_t LENGTH, Char *STRING);
+%typemap(directorin) (int LENGTH, Char *STRING) = (size_t LENGTH, Char *STRING);
+%typemap(in) (int LENGTH, const Char *STRING) = (size_t LENGTH, Char *STRING);
+%typemap(freearg) (int LENGTH, const Char *STRING) = (size_t LENGTH, Char *STRING);
+%typemap(directorin) (int LENGTH, const Char *STRING) = (size_t LENGTH, Char *STRING);
+
+%enddef
+
+/* ------------------------------------------------------------
+ * --- String fragment methods ---
+ * ------------------------------------------------------------ */
+
+#ifndef %_typemap2_string
+%define %_typemap2_string(StringCode, CharCode,
+ WarningLeakMsg,
+ Char, CharName,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ SWIG_NewCopyCharArray,
+ SWIG_DeleteCharArray,
+ FragLimits, CHAR_MIN, CHAR_MAX)
+
+%fragment("SWIG_From"#CharName"Ptr","header",fragment=#SWIG_FromCharPtrAndSize) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From##CharName##Ptr(const Char *cptr)
+{
+ return SWIG_FromCharPtrAndSize(cptr, (cptr ? SWIG_CharPtrLen(cptr) : 0));
+}
+}
+
+%fragment("SWIG_From"#CharName"Array","header",fragment=#SWIG_FromCharPtrAndSize) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From##CharName##Array(const Char *cptr, size_t size)
+{
+ return SWIG_FromCharPtrAndSize(cptr, size);
+}
+}
+
+%fragment("SWIG_As" #CharName "Ptr","header",fragment=#SWIG_AsCharPtrAndSize) {
+%define_as(SWIG_As##CharName##Ptr(obj, val, alloc), SWIG_AsCharPtrAndSize(obj, val, NULL, alloc))
+}
+
+%fragment("SWIG_As" #CharName "Array","header",fragment=#SWIG_AsCharPtrAndSize) {
+SWIGINTERN int
+SWIG_As##CharName##Array(SWIG_Object obj, Char *val, size_t size)
+{
+ Char* cptr = 0; size_t csize = 0; int alloc = SWIG_OLDOBJ;
+ int res = SWIG_AsCharPtrAndSize(obj, &cptr, &csize, &alloc);
+ if (SWIG_IsOK(res)) {
+ /* special case of single char conversion when we don't need space for NUL */
+ if (size == 1 && csize == 2 && cptr && !cptr[1]) --csize;
+ if (csize <= size) {
+ if (val) {
+ if (csize) memcpy(val, cptr, csize*sizeof(Char));
+ if (csize < size) memset(val + csize, 0, (size - csize)*sizeof(Char));
+ }
+ if (alloc == SWIG_NEWOBJ) {
+ SWIG_DeleteCharArray(cptr);
+ res = SWIG_DelNewMask(res);
+ }
+ return res;
+ }
+ if (alloc == SWIG_NEWOBJ) SWIG_DeleteCharArray(cptr);
+ }
+ return SWIG_TypeError;
+}
+}
+
+/* Char */
+
+%fragment(SWIG_From_frag(Char),"header",fragment=#SWIG_FromCharPtrAndSize) {
+SWIGINTERNINLINE SWIG_Object
+SWIG_From_dec(Char)(Char c)
+{
+ return SWIG_FromCharPtrAndSize(&c,1);
+}
+}
+
+%fragment(SWIG_AsVal_frag(Char),"header",
+ fragment="SWIG_As"#CharName"Array",
+ fragment=FragLimits,
+ fragment=SWIG_AsVal_frag(long)) {
+SWIGINTERN int
+SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val)
+{
+ int res = SWIG_As##CharName##Array(obj, val, 1);
+ if (!SWIG_IsOK(res)) {
+ long v;
+ res = SWIG_AddCast(SWIG_AsVal(long)(obj, &v));
+ if (SWIG_IsOK(res)) {
+ if ((CHAR_MIN <= v) && (v <= CHAR_MAX)) {
+ if (val) *val = %numeric_cast(v, Char);
+ } else {
+ res = SWIG_OverflowError;
+ }
+ }
+ }
+ return res;
+}
+}
+
+%_typemap_string(StringCode,
+ Char,
+ WarningLeakMsg,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ SWIG_As##CharName##Ptr,
+ SWIG_From##CharName##Ptr,
+ SWIG_As##CharName##Array,
+ SWIG_NewCopyCharArray,
+ SWIG_DeleteCharArray)
+
+%enddef
+#endif
+
+/* ------------------------------------------------------------
+ * String typemaps and fragments, with default allocators
+ * ------------------------------------------------------------ */
+
+%define %typemaps_string(StringCode, CharCode,
+ WarningLeakMsg,
+ Char, CharName,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ FragLimits, CHAR_MIN, CHAR_MAX)
+%_typemap2_string(StringCode, CharCode,
+ WarningLeakMsg,
+ Char, CharName,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ %new_copy_array,
+ %delete_array,
+ FragLimits, CHAR_MIN, CHAR_MAX)
+%enddef
+
+/* ------------------------------------------------------------
+ * String typemaps and fragments, with custom allocators
+ * ------------------------------------------------------------ */
+
+%define %typemaps_string_alloc(StringCode, CharCode,
+ WarningLeakMsg,
+ Char, CharName,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ SWIG_NewCopyCharArray,
+ SWIG_DeleteCharArray,
+ FragLimits, CHAR_MIN, CHAR_MAX)
+%_typemap2_string(StringCode, CharCode,
+ WarningLeakMsg,
+ Char, CharName,
+ SWIG_AsCharPtrAndSize,
+ SWIG_FromCharPtrAndSize,
+ SWIG_CharPtrLen,
+ SWIG_CharBufLen,
+ SWIG_NewCopyCharArray,
+ SWIG_DeleteCharArray,
+ FragLimits, CHAR_MIN, CHAR_MAX)
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/swigmacros.swg b/contrib/tools/swig/Lib/typemaps/swigmacros.swg
new file mode 100644
index 00000000000..b772eb04b3e
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/swigmacros.swg
@@ -0,0 +1,228 @@
+/* -----------------------------------------------------------------------------
+ * SWIG API. Portion only visible from SWIG
+ * ----------------------------------------------------------------------------- */
+/*
+ This file implements the internal macros of the 'SWIG API', which
+ are useful to implement all the SWIG target languages.
+
+ Basic preprocessor macros:
+ --------------------------
+
+ %arg(Arg) Safe argument wrap
+ %str(Arg) Stringify the argument
+ %begin_block Begin an execution block
+ %end_block End an execution block
+ %block(Block) Execute Block as an execution block
+ %define_as(Def, Val) Define 'Def' as 'Val', expanding Def and Val first
+ %ifcplusplus(V1, V2) if C++ Mode; then V1; else V2; fi
+
+
+ Casting Operations:
+ -------------------
+
+ SWIG provides the following casting macros, which implement the
+ corresponding C++ casting operations:
+
+ %const_cast(a, Type) const_cast<Type >(a)
+ %static_cast(a, Type) static_cast<Type >(a)
+ %reinterpret_cast(a, Type) reinterpret_cast<Type >(a)
+ %numeric_cast(a, Type) static_cast<Type >(a)
+ %as_voidptr(a) const_cast<void *>(static_cast<const void *>(a))
+ %as_voidptrptr(a) reinterpret_cast<void **>(a)
+
+ or their C unsafe versions. In C++ we use the safe version unless
+ SWIG_NO_CPLUSPLUS_CAST is defined
+
+
+ Memory allocation:
+ ------------------
+
+ These allocation/freeing macros are safe to use in C or C++ and
+ dispatch the proper new/delete/delete[] or free/malloc calls as
+ needed.
+
+ %new_instance(Type) Allocate a new instance of given Type
+ %new_copy(value,Type) Allocate and initialize a new instance with 'value'
+ %new_array(size,Type) Allocate a new array with given size and Type and zero initialize
+ %new_copy_array(cptr,size,Type) Allocate and initialize a new array from 'cptr'
+ %delete(cptr) Delete an instance
+ %delete_array(cptr) Delete an array
+
+
+ Auxiliary loop macros:
+ ----------------------
+
+ %formacro(Macro, Args...) or %formacro_1(Macro, Args...)
+ for i in Args
+ do
+ Macro($i)
+ done
+
+ %formacro_2(Macro2, Args...)
+ for i,j in Args
+ do
+ Macro2($i, $j)
+ done
+
+
+ Flags and conditional macros:
+ -----------------------------
+
+ %mark_flag(flag)
+ flag := True
+
+ %evalif(flag,expr)
+ if flag; then
+ expr
+ fi
+
+ %evalif_2(flag1 flag2,expr)
+ if flag1 and flag2; then
+ expr
+ fi
+
+
+*/
+/* -----------------------------------------------------------------------------
+ * Basic preprocessor macros
+ * ----------------------------------------------------------------------------- */
+
+#define %arg(Arg...) Arg
+#define %str(Arg) `Arg`
+#ifndef %begin_block
+# define %begin_block do {
+#endif
+#ifndef %end_block
+# define %end_block } while(0)
+#endif
+#define %block(Block...) %begin_block Block; %end_block
+
+/* define a new macro */
+%define %define_as(Def, Val...)%#define Def Val %enddef
+
+/* include C++ or else value */
+%define %ifcplusplus(cppval, nocppval)
+#ifdef __cplusplus
+cppval
+#else
+nocppval
+#endif
+%enddef
+
+/* -----------------------------------------------------------------------------
+ * Casting operators
+ * ----------------------------------------------------------------------------- */
+
+#if defined(__cplusplus) && !defined(SWIG_NO_CPLUSPLUS_CAST)
+# define %const_cast(a,Type...) const_cast< Type >(a)
+# define %static_cast(a,Type...) static_cast< Type >(a)
+# define %reinterpret_cast(a,Type...) reinterpret_cast< Type >(a)
+# define %numeric_cast(a,Type...) static_cast< Type >(a)
+#else /* C case */
+# define %const_cast(a,Type...) (Type)(a)
+# define %static_cast(a,Type...) (Type)(a)
+# define %reinterpret_cast(a,Type...) (Type)(a)
+# define %numeric_cast(a,Type...) (Type)(a)
+#endif /* __cplusplus */
+
+
+#define %as_voidptr(a) SWIG_as_voidptr(a)
+#define %as_voidptrptr(a) SWIG_as_voidptrptr(a)
+
+%insert("header") {
+%define_as(SWIG_as_voidptr(a), %const_cast(%static_cast(a,const void *), void *))
+%define_as(SWIG_as_voidptrptr(a), ((void)%as_voidptr(*a),%reinterpret_cast(a, void**)))
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Allocating/freeing elements
+ * ----------------------------------------------------------------------------- */
+
+#if defined(__cplusplus)
+# define %new_instance(Type...) (new Type())
+# define %new_copy(val,Type...) (new Type(%static_cast(val, const Type&)))
+# define %new_array(size,Type...) (new Type[size]())
+# define %new_copy_array(ptr,size,Type...) %reinterpret_cast(memcpy(new Type[size], ptr, sizeof(Type)*(size)), Type*)
+# define %delete(cptr) delete cptr
+# define %delete_array(cptr) delete[] cptr
+#else /* C case */
+# define %new_instance(Type...) (Type *)calloc(1,sizeof(Type))
+# define %new_copy(val,Type...) (Type *)memcpy(%new_instance(Type),&val,sizeof(Type))
+# define %new_array(size,Type...) (Type *)calloc(size, sizeof(Type))
+# define %new_copy_array(ptr,size,Type...) (Type *)memcpy(malloc((size)*sizeof(Type)), ptr, sizeof(Type)*(size))
+# define %delete(cptr) free((char*)cptr)
+# define %delete_array(cptr) free((char*)cptr)
+#endif /* __cplusplus */
+
+/* -----------------------------------------------------------------------------
+ * SWIG names and mangling
+ * ----------------------------------------------------------------------------- */
+
+#define %mangle(Type...) #@Type
+#define %descriptor(Type...) SWIGTYPE_ ## #@Type
+#define %string_name(Name) "SWIG_" %str(Name)
+#define %symbol_name(Name, Type...) SWIG_ ## Name ## _ #@Type
+#define %checkcode(Code) SWIG_TYPECHECK_ ## Code
+
+
+/* -----------------------------------------------------------------------------
+ * Auxiliary loop macros
+ * ----------------------------------------------------------------------------- */
+
+
+/* for loop for macro with one argument */
+%define %_formacro_1(macro, arg1,...)macro(arg1)
+#if #__VA_ARGS__ != "__fordone__"
+%_formacro_1(macro, __VA_ARGS__)
+#endif
+%enddef
+
+/* for loop for macro with one argument */
+%define %formacro_1(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
+%define %formacro(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
+
+/* for loop for macro with two arguments */
+%define %_formacro_2(macro, arg1, arg2, ...)macro(arg1, arg2)
+#if #__VA_ARGS__ != "__fordone__"
+%_formacro_2(macro, __VA_ARGS__)
+#endif
+%enddef
+
+/* for loop for macro with two arguments */
+%define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef
+
+/* -----------------------------------------------------------------------------
+ * SWIG flags
+ * ----------------------------------------------------------------------------- */
+
+/*
+ mark a flag, ie, define a macro name but ignore it in
+ the interface.
+
+ the flag can be later used with %evalif
+*/
+
+%define %mark_flag(x) %define x 1 %enddef %enddef
+
+
+/*
+ %evalif and %evalif_2 are use to evaluate or process
+ an expression if the given predicate is 'true' (1).
+*/
+%define %_evalif(_x,_expr)
+#if _x == 1
+_expr
+#endif
+%enddef
+
+%define %_evalif_2(_x,_y,_expr)
+#if _x == 1 && _y == 1
+_expr
+#endif
+%enddef
+
+%define %evalif(_x,_expr...) %_evalif(%arg(_x),%arg(_expr)) %enddef
+
+%define %evalif_2(_x,_y,_expr...) %_evalif_2(%arg(_x),%arg(_y),%arg(_expr)) %enddef
+
diff --git a/contrib/tools/swig/Lib/typemaps/swigmove.swg b/contrib/tools/swig/Lib/typemaps/swigmove.swg
new file mode 100644
index 00000000000..656e1410bc8
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/swigmove.swg
@@ -0,0 +1,21 @@
+/* -----------------------------------------------------------------------------
+ * swigmove.swg
+ *
+ * Input typemaps library for implementing full move semantics when passing
+ * parameters by value.
+ * ----------------------------------------------------------------------------- */
+
+%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "$1_type", $symname, $argnum);
+ } else {
+ %argument_fail(res, "$1_type", $symname, $argnum);
+ }
+ }
+ if (!argp) { %argument_nullref("$1_type", $symname, $argnum); }
+ SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp);
+}
+
+%typemap(typecheck) SWIGTYPE MOVE = SWIGTYPE;
diff --git a/contrib/tools/swig/Lib/typemaps/swigobject.swg b/contrib/tools/swig/Lib/typemaps/swigobject.swg
new file mode 100644
index 00000000000..26c6ba8edf0
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/swigobject.swg
@@ -0,0 +1,37 @@
+/* ------------------------------------------------------------
+ * Language Object * - Just pass straight through unmodified
+ * ------------------------------------------------------------ */
+
+%typemap(in) SWIG_Object "$1 = $input;"
+
+%typemap(in,noblock=1) SWIG_Object const & ($*ltype temp)
+{
+ temp = %static_cast($input, $*ltype);
+ $1 = &temp;
+}
+
+%typemap(out,noblock=1) SWIG_Object {
+ %set_output($1);
+}
+
+%typemap(out,noblock=1) SWIG_Object const & {
+ %set_output(*$1);
+}
+
+%typecheck(SWIG_TYPECHECK_SWIGOBJECT) SWIG_Object "$1 = ($input != 0);";
+
+%typemap(throws,noblock=1) SWIG_Object {
+ %raise($1, "$type", 0);
+}
+
+%typemap(constcode,noblock=1) SWIG_Object {
+ %set_constant("$symname", $value);
+}
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+%typemap(directorin) SWIG_Object "$input = $1;"
+%typemap(directorout) SWIG_Object "$result = $input;"
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
diff --git a/contrib/tools/swig/Lib/typemaps/swigtype.swg b/contrib/tools/swig/Lib/typemaps/swigtype.swg
new file mode 100644
index 00000000000..ba8ce3c1f8f
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/swigtype.swg
@@ -0,0 +1,698 @@
+/* -----------------------------------------------------------------------------
+ * --- Input arguments ---
+ * ----------------------------------------------------------------------------- */
+/* Pointers and arrays */
+%typemap(in, noblock=1) SWIGTYPE *(void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ $1 = %reinterpret_cast(argp, $ltype);
+}
+%typemap(freearg) SWIGTYPE * ""
+
+%typemap(in, noblock=1) SWIGTYPE [] (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp,$descriptor, $disown | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ $1 = %reinterpret_cast(argp, $ltype);
+}
+%typemap(freearg) SWIGTYPE [] ""
+
+
+%typemap(in, noblock=1) SWIGTYPE *const& (void *argp = 0, int res = 0, $*1_ltype temp) {
+ res = SWIG_ConvertPtr($input, &argp, $*descriptor, $disown | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$*ltype", $symname, $argnum);
+ }
+ temp = %reinterpret_cast(argp, $*ltype);
+ $1 = %reinterpret_cast(&temp, $1_ltype);
+}
+%typemap(freearg) SWIGTYPE *const& ""
+
+
+/* Reference */
+%typemap(in, noblock=1) SWIGTYPE & (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (!argp) { %argument_nullref("$type", $symname, $argnum); }
+ $1 = %reinterpret_cast(argp, $ltype);
+}
+%typemap(freearg) SWIGTYPE & ""
+
+#if defined(__cplusplus) && defined(%implicitconv_flag)
+%typemap(in,noblock=1,implicitconv=1) const SWIGTYPE & (void *argp = 0, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags | %implicitconv_flag);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (!argp) { %argument_nullref("$type", $symname, $argnum); }
+ $1 = %reinterpret_cast(argp, $ltype);
+}
+%typemap(freearg,noblock=1,match="in",implicitconv=1) const SWIGTYPE &
+{
+ if (SWIG_IsNewObj(res$argnum)) %delete($1);
+}
+#endif
+
+/* Rvalue reference */
+%typemap(in, noblock=1, fragment="<memory>") SWIGTYPE && (void *argp = 0, int res = 0, std::unique_ptr<$*1_ltype> rvrdeleter) {
+ res = SWIG_ConvertPtr($input, &argp, $descriptor, SWIG_POINTER_RELEASE | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
+ %releasenotowned_fail(res, "$type", $symname, $argnum);
+ } else {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ }
+ if (!argp) { %argument_nullref("$type", $symname, $argnum); }
+ $1 = %reinterpret_cast(argp, $ltype);
+ rvrdeleter.reset($1);
+}
+%typemap(freearg) SWIGTYPE && ""
+
+/* By value */
+#if defined(__cplusplus) && defined(%implicitconv_flag)
+%typemap(in,implicitconv=1) SWIGTYPE (void *argp, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $&descriptor, %convertptr_flags | %implicitconv_flag);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (!argp) {
+ %argument_nullref("$type", $symname, $argnum);
+ } else {
+ $&ltype temp = %reinterpret_cast(argp, $&ltype);
+ $1 = *temp;
+ if (SWIG_IsNewObj(res)) %delete(temp);
+ }
+}
+#else
+%typemap(in) SWIGTYPE (void *argp, int res = 0) {
+ res = SWIG_ConvertPtr($input, &argp, $&descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+ if (!argp) {
+ %argument_nullref("$type", $symname, $argnum);
+ } else {
+ $1 = *(%reinterpret_cast(argp, $&ltype));
+ }
+}
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * --- Output arguments ---
+ * ----------------------------------------------------------------------------- */
+
+/* Pointers, references */
+%typemap(out,noblock=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE[] {
+ %set_output(SWIG_NewPointerObj(%as_voidptr($1), $descriptor, $owner | %newpointer_flags));
+}
+
+%typemap(out, noblock=1) SWIGTYPE *const& {
+ %set_output(SWIG_NewPointerObj(%as_voidptr(*$1), $*descriptor, $owner | %newpointer_flags));
+}
+
+/* Return by value */
+#ifdef __cplusplus
+%typemap(out, noblock=1) SWIGTYPE {
+ %set_output(SWIG_NewPointerObj((new $1_ltype($1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags));
+}
+#else
+%typemap(out, noblock=1) SWIGTYPE {
+ %set_output(SWIG_NewPointerObj(%new_copy($1, $1_ltype), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags));
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * --- Variable input ---
+ * ----------------------------------------------------------------------------- */
+
+/* memberin/globalin/varin, for fix arrays. */
+
+%typemap(memberin) SWIGTYPE [ANY] {
+ if ($input) {
+ size_t ii = 0;
+ for (; ii < (size_t)$1_dim0; ++ii) *($1_basetype *)&$1[ii] = *(($1_basetype *)$input + ii);
+ } else {
+ %variable_nullref("$type","$name");
+ }
+}
+
+%typemap(globalin) SWIGTYPE [ANY] {
+ if ($input) {
+ size_t ii = 0;
+ for (; ii < (size_t)$1_dim0; ++ii) *($1_basetype *)&$1[ii] = *(($1_basetype *)$input + ii);
+ } else {
+ %variable_nullref("$type","$name");
+ }
+}
+
+%typemap(varin) SWIGTYPE [ANY] {
+ $basetype *inp = 0;
+ int res = SWIG_ConvertPtr($input, %as_voidptrptr(&inp), $descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ } else if (inp) {
+ size_t ii = 0;
+ for (; ii < (size_t)$1_dim0; ++ii) *($1_basetype *)&$1[ii] = *(($1_basetype *)inp + ii);
+ } else {
+ %variable_nullref("$type", "$name");
+ }
+}
+
+
+/* memberin/globalin/varin, for fix double arrays. */
+
+%typemap(memberin) SWIGTYPE [ANY][ANY] {
+ if ($input) {
+ size_t ii = 0;
+ for (; ii < (size_t)$1_dim0; ++ii) {
+ size_t jj = 0;
+ for (; jj < (size_t)$1_dim1; ++jj) $1[ii][jj] = $input[ii][jj];
+ }
+ } else {
+ %variable_nullref("$type","$name");
+ }
+}
+
+%typemap(globalin) SWIGTYPE [ANY][ANY] {
+ if ($input) {
+ size_t ii = 0;
+ for (; ii < (size_t)$1_dim0; ++ii) {
+ size_t jj = 0;
+ for (; jj < (size_t)$1_dim1; ++jj) $1[ii][jj] = $input[ii][jj];
+ }
+ } else {
+ %variable_nullref("$type","$name");
+ }
+}
+
+%typemap(varin) SWIGTYPE [ANY][ANY] {
+ $basetype (*inp)[$1_dim1] = 0;
+ int res = SWIG_ConvertPtr($input, %as_voidptrptr(&inp), $descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ } else if (inp) {
+ size_t ii = 0;
+ for (; ii < (size_t)$1_dim0; ++ii) {
+ size_t jj = 0;
+ for (; jj < (size_t)$1_dim1; ++jj) $1[ii][jj] = inp[ii][jj];
+ }
+ } else {
+ %variable_nullref("$type", "$name");
+ }
+}
+
+/* Pointers, references, and variable size arrays */
+
+%typemap(varin,warning=SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) SWIGTYPE * {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ $1 = %reinterpret_cast(argp, $ltype);
+}
+
+%typemap(varin,noblock=1,warning="462:Unable to set dimensionless array variable") SWIGTYPE []
+{
+ %variable_fail(SWIG_AttributeError, "$type", "read-only $name");
+}
+
+%typemap(varin,warning=SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) SWIGTYPE & {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ if (!argp) {
+ %variable_nullref("$type", "$name");
+ }
+ $1 = *(%reinterpret_cast(argp, $ltype));
+}
+
+%typemap(varin,warning=SWIGWARN_TYPEMAP_SWIGTYPELEAK_MSG) SWIGTYPE && {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ if (!argp) {
+ %variable_nullref("$type", "$name");
+ }
+ $1 = *(%reinterpret_cast(argp, $ltype));
+}
+
+#if defined(__cplusplus) && defined(%implicitconv_flag)
+%typemap(varin,implicitconv=1) SWIGTYPE {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $&descriptor, %convertptr_flags | %implicitconv_flag);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ if (!argp) {
+ %variable_nullref("$type", "$name");
+ } else {
+ $&type temp;
+ temp = %reinterpret_cast(argp, $&type);
+ $1 = *temp;
+ if (SWIG_IsNewObj(res)) %delete(temp);
+ }
+}
+#else
+%typemap(varin) SWIGTYPE {
+ void *argp = 0;
+ int res = SWIG_ConvertPtr($input, &argp, $&descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ if (!argp) {
+ %variable_nullref("$type", "$name");
+ } else {
+ $1 = *(%reinterpret_cast(argp, $&type));
+ }
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * --- Variable output ---
+ * ----------------------------------------------------------------------------- */
+
+/* Pointers and arrays */
+%typemap(varout, noblock=1) SWIGTYPE * {
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags));
+}
+
+%typemap(varout, noblock=1) SWIGTYPE [] {
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags));
+}
+
+/* References */
+%typemap(varout, noblock=1) SWIGTYPE & {
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(&$1), $descriptor, %newpointer_flags));
+}
+
+%typemap(varout, noblock=1) SWIGTYPE && {
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(&$1), $descriptor, %newpointer_flags));
+}
+
+/* Value */
+%typemap(varout, noblock=1) SWIGTYPE {
+ %set_varoutput(SWIG_NewPointerObj(%as_voidptr(&$1), $&descriptor, %newpointer_flags));
+}
+
+/* ------------------------------------------------------------
+ * --- Typechecking rules ---
+ * ------------------------------------------------------------ */
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE * {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor, 0);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE *const& {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $*descriptor, 0);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE & {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE && {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL);
+ $1 = SWIG_CheckState(res);
+}
+
+#if defined(__cplusplus) && defined(%implicitconv_flag)
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1,implicitconv=1) const SWIGTYPE & {
+ int res = SWIG_ConvertPtr($input, 0, $descriptor, SWIG_POINTER_NO_NULL | %implicitconv_flag);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1,implicitconv=1) const SWIGTYPE && {
+ int res = SWIG_ConvertPtr($input, 0, $descriptor, SWIG_POINTER_NO_NULL | %implicitconv_flag);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1,implicitconv=1) SWIGTYPE {
+ int res = SWIG_ConvertPtr($input, 0, $&descriptor, SWIG_POINTER_NO_NULL | %implicitconv_flag);
+ $1 = SWIG_CheckState(res);
+}
+#else
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) const SWIGTYPE & {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) const SWIGTYPE && {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $descriptor, SWIG_POINTER_NO_NULL);
+ $1 = SWIG_CheckState(res);
+}
+
+%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE {
+ void *vptr = 0;
+ int res = SWIG_ConvertPtr($input, &vptr, $&descriptor, SWIG_POINTER_NO_NULL);
+ $1 = SWIG_CheckState(res);
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * --- Director typemaps --- *
+ * ----------------------------------------------------------------------------- */
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+
+%typemap(directorin,noblock=1) SWIGTYPE {
+ $input = SWIG_NewPointerObj((new $1_ltype(SWIG_STD_MOVE($1))), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags);
+}
+
+%typemap(directorin,noblock=1) SWIGTYPE * {
+ $input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags);
+}
+
+%typemap(directorin,noblock=1) SWIGTYPE *const& {
+ $input = SWIG_NewPointerObj(%as_voidptr($1), $*descriptor, %newpointer_flags);
+}
+
+%typemap(directorin,noblock=1) SWIGTYPE & {
+ $input = SWIG_NewPointerObj(%as_voidptr(&$1), $descriptor, %newpointer_flags);
+}
+
+%typemap(directorin,noblock=1) SWIGTYPE && {
+ $input = SWIG_NewPointerObj(%as_voidptr(&$1_name), $descriptor, %newpointer_flags);
+}
+
+/* directorout */
+
+#if defined(__cplusplus) && defined(%implicitconv_flag)
+%typemap(directorout,noblock=1,implicitconv=1) SWIGTYPE (void * swig_argp, int swig_res = 0) {
+ swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags | %implicitconv_flag);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+ $result = *(%reinterpret_cast(swig_argp, $&ltype));
+ if (SWIG_IsNewObj(swig_res)) %delete(%reinterpret_cast(swig_argp, $&ltype));
+}
+#else
+%typemap(directorout,noblock=1) SWIGTYPE (void * swig_argp, int swig_res = 0) {
+ swig_res = SWIG_ConvertPtr($input,&swig_argp,$&descriptor, %convertptr_flags);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+ $result = *(%reinterpret_cast(swig_argp, $&ltype));
+}
+#endif
+
+%typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG)
+ SWIGTYPE *(void *swig_argp, int swig_res, swig_owntype own) {
+ swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+ $result = %reinterpret_cast(swig_argp, $ltype);
+ swig_acquire_ownership_obj(%as_voidptr($result), own /* & TODO: SWIG_POINTER_OWN */);
+}
+%typemap(directorfree,noblock=1,match="directorout") SWIGTYPE * {
+ if (director) {
+ SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input)));
+ }
+}
+
+%typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG)
+ SWIGTYPE *const&(void *swig_argp, int swig_res, swig_owntype own) {
+ swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $*descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+ $1_ltype swig_temp = new $*1_ltype(($*1_ltype)swig_argp);
+ swig_acquire_ownership(swig_temp);
+ $result = swig_temp;
+}
+%typemap(directorfree,noblock=1,match="directorout") SWIGTYPE *const& {
+ if (director) {
+ SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr(*$input)));
+ }
+}
+
+%typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG)
+ SWIGTYPE &(void *swig_argp, int swig_res, swig_owntype own) {
+ swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+ if (!swig_argp) { %dirout_nullref("$type"); }
+ $result = %reinterpret_cast(swig_argp, $ltype);
+ swig_acquire_ownership_obj(%as_voidptr($result), own /* & TODO: SWIG_POINTER_OWN */);
+}
+%typemap(directorfree,noblock=1,match="directorout") SWIGTYPE & {
+ if (director) {
+ SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input)));
+ }
+}
+
+%typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG)
+ SWIGTYPE &&(void *swig_argp, int swig_res, swig_owntype own) {
+ swig_res = SWIG_ConvertPtrAndOwn($input, &swig_argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+ if (!swig_argp) { %dirout_nullref("$type"); }
+ $result = %reinterpret_cast(swig_argp, $ltype);
+ swig_acquire_ownership_obj(%as_voidptr($result), own /* & TODO: SWIG_POINTER_OWN */);
+}
+%typemap(directorfree,noblock=1,match="directorout") SWIGTYPE && {
+ if (director) {
+ SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input)));
+ }
+}
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
+
+/* ------------------------------------------------------------
+ * --- Constants ---
+ * ------------------------------------------------------------ */
+
+%typemap(constcode,noblock=1) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] {
+ %set_constant("$symname", SWIG_NewPointerObj(%as_voidptr($value),$descriptor,%newpointer_flags));
+}
+
+%typemap(constcode,noblock=1) SWIGTYPE {
+ %set_constant("$symname", SWIG_NewPointerObj(%as_voidptr(&$value),$&descriptor,%newpointer_flags));
+}
+
+/* ------------------------------------------------------------
+ * --- Exception handling ---
+ * ------------------------------------------------------------ */
+
+%typemap(throws,noblock=1) SWIGTYPE {
+ %raise(SWIG_NewPointerObj(%new_copy($1, $1_ltype),$&descriptor,SWIG_POINTER_OWN), "$type", $&descriptor);
+}
+
+%typemap(throws,noblock=1) SWIGTYPE * {
+ %raise(SWIG_NewPointerObj(%as_voidptr($1),$descriptor,0), "$type", $descriptor);
+}
+
+%typemap(throws,noblock=1) SWIGTYPE [ANY] {
+ %raise(SWIG_NewPointerObj(%as_voidptr($1),$descriptor,0), "$type", $descriptor);
+}
+
+%typemap(throws,noblock=1) SWIGTYPE & {
+ %raise(SWIG_NewPointerObj(%as_voidptr(&$1),$descriptor,0), "$type", $descriptor);
+}
+
+%typemap(throws,noblock=1) SWIGTYPE && {
+ %raise(SWIG_NewPointerObj(%as_voidptr(&$1),$descriptor,0), "$type", $descriptor);
+}
+
+%typemap(throws,noblock=1) (...) {
+ SWIG_exception_fail(SWIG_RuntimeError,"unknown exception");
+}
+
+/* ------------------------------------------------------------
+ * --- CLASS::* typemaps ---
+ * ------------------------------------------------------------ */
+
+%typemap(in) SWIGTYPE (CLASS::*) {
+ int res = SWIG_ConvertMember($input, %as_voidptr(&$1), sizeof($1),$descriptor);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+}
+
+%typemap(out,noblock=1) SWIGTYPE (CLASS::*) {
+ %set_output(SWIG_NewMemberObj(%as_voidptr(&$1), sizeof($1), $descriptor));
+}
+
+%typemap(varin) SWIGTYPE (CLASS::*) {
+ int res = SWIG_ConvertMember($input,%as_voidptr(&$1), sizeof($1), $descriptor);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+}
+
+%typemap(varout,noblock=1) SWIGTYPE (CLASS::*) {
+ %set_varoutput(SWIG_NewMemberObj(%as_voidptr(&$1), sizeof($1), $descriptor));
+}
+
+%typemap(constcode,noblock=1) SWIGTYPE (CLASS::*) {
+ %set_constant("$symname", SWIG_NewMemberObj(%as_voidptr(&$value), sizeof($value), $descriptor));
+}
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+
+%typemap(directorin,noblock=1) SWIGTYPE (CLASS::*) {
+ $input = SWIG_NewMemberObj(%as_voidptr(&$1), sizeof($1), $descriptor);
+}
+
+/* directorout */
+
+%typemap(directorout) SWIGTYPE (CLASS::*) {
+ int swig_res = SWIG_ConvertMember($input,%as_voidptr(&$result), sizeof($result), $descriptor);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+}
+#endif
+
+%apply SWIGTYPE (CLASS::*) { SWIGTYPE (CLASS::*const) }
+%apply SWIGTYPE & { SWIGTYPE (CLASS::*const&) }
+
+/* ------------------------------------------------------------
+ * --- function ptr typemaps ---
+ * ------------------------------------------------------------ */
+
+/*
+ ISO C++ doesn't allow direct casting of a function ptr to a object
+ ptr. So, maybe the ptr sizes are not the same, and we need to take
+ some providences.
+ */
+%typemap(in) SWIGTYPE ((*)(ANY)) {
+ int res = SWIG_ConvertFunctionPtr($input, (void**)(&$1), $descriptor);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type",$symname, $argnum);
+ }
+}
+
+%typecheck(SWIG_TYPECHECK_POINTER,noblock=1) SWIGTYPE ((*)(ANY)) {
+ void *ptr = 0;
+ int res = SWIG_ConvertFunctionPtr($input, &ptr, $descriptor);
+ $1 = SWIG_CheckState(res);
+}
+
+
+%typemap(out, noblock=1) SWIGTYPE ((*)(ANY)) {
+ %set_output(SWIG_NewFunctionPtrObj((void *)($1), $descriptor));
+}
+
+%typemap(varin) SWIGTYPE ((*)(ANY)) {
+ int res = SWIG_ConvertFunctionPtr($input, (void**)(&$1), $descriptor);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+}
+
+%typemap(varout,noblock=1) SWIGTYPE ((*)(ANY)) {
+ %set_varoutput(SWIG_NewFunctionPtrObj((void *)($1), $descriptor));
+}
+
+%typemap(constcode, noblock=1) SWIGTYPE ((*)(ANY)){
+ %set_constant("$symname", SWIG_NewFunctionPtrObj((void *)$value, $descriptor));
+}
+%typemap(constcode) SWIGTYPE ((* const)(ANY)) = SWIGTYPE ((*)(ANY));
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+
+%typemap(directorin,noblock=1) SWIGTYPE ((*)(ANY)) {
+ $input = SWIG_NewFunctionPtrObj((void*)($1), $descriptor);
+}
+
+/* directorout */
+
+%typemap(directorout) SWIGTYPE ((*)(ANY)) {
+ int swig_res = SWIG_ConvertFunctionPtr($input,(void**)(&$result),$descriptor);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res,"$type");
+ }
+}
+#endif
+
+%apply SWIGTYPE ((*)(ANY)) { SWIGTYPE ((* const)(ANY)) }
+
+%apply SWIGTYPE * { SWIGTYPE *const }
+
+/* ------------------------------------------------------------
+ * --- Special typemaps ---
+ * ------------------------------------------------------------ */
+
+/* DISOWN typemap */
+
+%typemap(in, noblock=1) SWIGTYPE *DISOWN (int res = 0) {
+ res = SWIG_ConvertPtr($input, %as_voidptrptr(&$1), $descriptor, SWIG_POINTER_DISOWN | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res,"$type", $symname, $argnum);
+ }
+}
+
+%typemap(varin) SWIGTYPE *DISOWN {
+ void *temp = 0;
+ int res = SWIG_ConvertPtr($input, &temp, $descriptor, SWIG_POINTER_DISOWN | %convertptr_flags);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ $1 = ($ltype) temp;
+}
+
+/* DYNAMIC typemap */
+
+%typemap(out,noblock=1) SWIGTYPE *DYNAMIC, SWIGTYPE &DYNAMIC {
+ %set_output(SWIG_NewPointerObj(%as_voidptr($1), SWIG_TypeDynamicCast($descriptor, %as_voidptrptr(&$1)), $owner | %newpointer_flags));
+}
+
+/* INSTANCE typemap */
+
+#ifdef __cplusplus
+%typemap(out,noblock=1) SWIGTYPE INSTANCE {
+ %set_output(SWIG_NewInstanceObj((new $1_ltype($1)), $&1_descriptor, SWIG_POINTER_OWN | %newinstance_flags));
+}
+#else
+%typemap(out,noblock=1) SWIGTYPE INSTANCE {
+ %set_output(SWIG_NewInstanceObj(%new_copy($1, $1_ltype), $&1_descriptor, SWIG_POINTER_OWN | %newinstance_flags));
+}
+#endif
+
+%typemap(out,noblock=1) SWIGTYPE *INSTANCE, SWIGTYPE &INSTANCE, SWIGTYPE INSTANCE[] {
+ %set_output(SWIG_NewInstanceObj(%as_voidptr($1), $1_descriptor, $owner | %newinstance_flags));
+}
+
+%typemap(varout,noblock=1) SWIGTYPE *INSTANCE, SWIGTYPE INSTANCE[] {
+ %set_varoutput(SWIG_NewInstanceObj(%as_voidptr($1), $1_descriptor, %newinstance_flags));
+}
+
+%typemap(varout,noblock=1) SWIGTYPE &INSTANCE {
+ %set_varoutput(SWIG_NewInstanceObj(%as_voidptr($1), $1_descriptor, %newinstance_flags));
+}
+
+%typemap(varout,noblock=1) SWIGTYPE INSTANCE {
+ %set_varoutput(SWIG_NewInstanceObj(%as_voidptr(&$1), $&1_descriptor, %newinstance_flags));
+}
+
diff --git a/contrib/tools/swig/Lib/typemaps/swigtypemaps.swg b/contrib/tools/swig/Lib/typemaps/swigtypemaps.swg
new file mode 100644
index 00000000000..0c95c2f986f
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/swigtypemaps.swg
@@ -0,0 +1,174 @@
+/* -----------------------------------------------------------------------------
+ * swigtypemaps.swg
+ *
+ * Unified Typemap Library frontend
+ * ----------------------------------------------------------------------------- */
+
+/*
+ This file provides the frontend to the Unified Typemap Library.
+
+ When using this library in a SWIG target language, you need to
+ define a minimum set of fragments, specialize a couple of macros,
+ and then include this file.
+
+ Typically you will create a 'mytypemaps.swg' file in each target
+ language, where you will have the following sections:
+
+ === mytypemaps.swg ===
+
+ // Fragment section
+ %include <typemaps/fragments.swg>
+ <include target language fragments>
+
+ // Unified typemap section
+ <specialized the typemap library macros>
+ %include <typemaps/swigtypemaps.swg>
+
+ // Local typemap section
+ <add/replace extra target language typemaps>
+
+ === mytypemaps.swg ===
+
+ While we add more docs, please take a look at the following cases
+ to see how you specialized the unified typemap library for a new
+ target language:
+
+ Lib/python/pytypemaps.swg
+ Lib/tcl/tcltypemaps.swg
+ Lib/ruby/rubytypemaps.swg
+ Lib/perl5/perltypemaps.swg
+
+*/
+
+#define SWIGUTL SWIGUTL
+
+/* -----------------------------------------------------------------------------
+ * Language specialization section.
+ *
+ * Tune these macros for each language as needed.
+ * ----------------------------------------------------------------------------- */
+
+/*
+ The SWIG target language object must be provided.
+ For example in python you define:
+
+ #define SWIG_Object PyObject *
+*/
+
+#if !defined(SWIG_Object)
+#error "SWIG_Object must be defined as the SWIG target language object"
+#endif
+
+/*==== flags for new/convert methods ====*/
+
+
+#ifndef %convertptr_flags
+%define %convertptr_flags 0 %enddef
+#endif
+
+#ifndef %newpointer_flags
+%define %newpointer_flags 0 %enddef
+#endif
+
+#ifndef %newinstance_flags
+%define %newinstance_flags 0 %enddef
+#endif
+
+/*==== set output ====*/
+
+#ifndef %set_output
+/* simple set output operation */
+#define %set_output(obj) $result = obj
+#endif
+
+/*==== set variable output ====*/
+
+#ifndef %set_varoutput
+/* simple set varoutput operation */
+#define %set_varoutput(obj) $result = obj
+#endif
+
+/*==== append output ====*/
+
+#ifndef %append_output
+#if defined(SWIG_AppendOutput)
+/* simple append operation */
+#define %append_output(obj) $result = SWIG_AppendOutput($result,obj)
+#else
+#error "Language must define SWIG_AppendOutput or %append_output"
+#endif
+#endif
+
+/*==== set constant ====*/
+
+#ifndef %set_constant
+#if defined(SWIG_SetConstant)
+/* simple set constant operation */
+#define %set_constant(name,value) SWIG_SetConstant(name,value)
+#else
+#error "Language must define SWIG_SetConstant or %set_constant"
+#endif
+#endif
+
+/*==== raise an exception ====*/
+
+#ifndef %raise
+#if defined(SWIG_Raise)
+/* simple raise operation */
+#define %raise(obj, type, desc) SWIG_Raise(obj, type, desc); SWIG_fail
+#else
+#error "Language must define SWIG_Raise or %raise"
+#endif
+#endif
+
+/*==== clear errors ====*/
+
+#ifndef %error_clear
+#define %error_clear
+#endif
+
+/*==== director output exception ====*/
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+#ifndef SWIG_DirOutFail
+#define SWIG_DirOutFail(code, msg) Swig::DirectorTypeMismatchException::raise(SWIG_ErrorType(code), msg)
+#endif
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * Language independent definitions
+ * ----------------------------------------------------------------------------- */
+
+#define %error_block(Block...) %block(Block)
+#define %default_code(code) SWIG_ArgError(code)
+#define %argument_fail(code, type, name, argn) SWIG_exception_fail(%default_code(code), %argfail_fmt(type, name, argn))
+#define %argument_nullref(type, name, argn) SWIG_exception_fail(SWIG_NullReferenceError, %argnullref_fmt(type, name, argn))
+#define %variable_fail(code, type, name) SWIG_exception_fail(%default_code(code), %varfail_fmt(type, name))
+#define %variable_nullref(type, name) SWIG_exception_fail(SWIG_NullReferenceError, %varnullref_fmt(type, name))
+#define %releasenotowned_fail(code, type, name, argn) SWIG_exception_fail(%default_code(code), %releasenotownedfail_fmt(type, name, argn))
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+#define %dirout_fail(code, type) SWIG_DirOutFail(%default_code(code), %outfail_fmt(type))
+#define %dirout_nullref(type) SWIG_DirOutFail(SWIG_NullReferenceError, %outnullref_fmt(type))
+#endif
+
+/* -----------------------------------------------------------------------------
+ * All the typemaps
+ * ----------------------------------------------------------------------------- */
+
+
+%include <typemaps/fragments.swg>
+%include <typemaps/exception.swg>
+%include <typemaps/swigtype.swg>
+%include <typemaps/void.swg>
+%include <typemaps/swigobject.swg>
+%include <typemaps/valtypes.swg>
+%include <typemaps/ptrtypes.swg>
+%include <typemaps/inoutlist.swg>
+%include <typemaps/primtypes.swg>
+%include <typemaps/string.swg>
+%include <typemaps/misctypes.swg>
+%include <typemaps/enumint.swg>
+
+
diff --git a/contrib/tools/swig/Lib/typemaps/typemaps.swg b/contrib/tools/swig/Lib/typemaps/typemaps.swg
new file mode 100644
index 00000000000..7d013b045d9
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/typemaps.swg
@@ -0,0 +1,153 @@
+/* -----------------------------------------------------------------------------
+ * typemaps.swg
+ *
+ * Tcl Pointer handling
+ *
+ * These mappings provide support for input/output arguments and common
+ * uses for C/C++ pointers.
+ * ----------------------------------------------------------------------------- */
+
+// INPUT typemaps.
+// These remap a C pointer to be an "INPUT" value which is passed by value
+// instead of reference.
+
+/*
+The following methods can be applied to turn a pointer into a simple
+"input" value. That is, instead of passing a pointer to an object,
+you would use a real value instead.
+
+ int *INPUT
+ short *INPUT
+ long *INPUT
+ long long *INPUT
+ unsigned int *INPUT
+ unsigned short *INPUT
+ unsigned long *INPUT
+ unsigned long long *INPUT
+ unsigned char *INPUT
+ bool *INPUT
+ float *INPUT
+ double *INPUT
+
+To use these, suppose you had a C function like this :
+
+ double fadd(double *a, double *b) {
+ return *a+*b;
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double fadd(double *INPUT, double *INPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INPUT { double *a, double *b };
+ double fadd(double *a, double *b);
+
+*/
+
+// OUTPUT typemaps. These typemaps are used for parameters that
+// are output only. The output value is appended to the result as
+// a list element.
+
+/*
+The following methods can be applied to turn a pointer into an "output"
+value. When calling a function, no input value would be given for
+a parameter, but an output value would be returned. In the case of
+multiple output values, they are returned in the form of a Tcl tuple.
+
+ int *OUTPUT
+ short *OUTPUT
+ long *OUTPUT
+ long long *OUTPUT
+ unsigned int *OUTPUT
+ unsigned short *OUTPUT
+ unsigned long *OUTPUT
+ unsigned long long *OUTPUT
+ unsigned char *OUTPUT
+ bool *OUTPUT
+ float *OUTPUT
+ double *OUTPUT
+
+For example, suppose you were trying to wrap the modf() function in the
+C math library which splits x into integral and fractional parts (and
+returns the integer part in one of its parameters).K:
+
+ double modf(double x, double *ip);
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ double modf(double x, double *OUTPUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *OUTPUT { double *ip };
+ double modf(double x, double *ip);
+
+The Tcl output of the function would be a tuple containing both
+output values.
+
+*/
+
+// INOUT
+// Mappings for an argument that is both an input and output
+// parameter
+
+/*
+The following methods can be applied to make a function parameter both
+an input and output value. This combines the behavior of both the
+"INPUT" and "OUTPUT" methods described earlier. Output values are
+returned in the form of a Tcl tuple.
+
+ int *INOUT
+ short *INOUT
+ long *INOUT
+ long long *INOUT
+ unsigned int *INOUT
+ unsigned short *INOUT
+ unsigned long *INOUT
+ unsigned long long *INOUT
+ unsigned char *INOUT
+ bool *INOUT
+ float *INOUT
+ double *INOUT
+
+For example, suppose you were trying to wrap the following function :
+
+ void neg(double *x) {
+ *x = -(*x);
+ }
+
+You could wrap it with SWIG as follows :
+
+ %include <typemaps.i>
+ void neg(double *INOUT);
+
+or you can use the %apply directive :
+
+ %include <typemaps.i>
+ %apply double *INOUT { double *x };
+ void neg(double *x);
+
+Unlike C, this mapping does not directly modify the input value (since
+this makes no sense in Tcl). Rather, the modified input value shows
+up as the return value of the function. Thus, to apply this function
+to a Tcl variable you might do this :
+
+ x = neg(x)
+
+*/
+
+
+#if defined(SWIG_INOUT_NODEF)
+
+%apply_checkctypes(%typemaps_inoutn)
+
+%apply size_t& { std::size_t& };
+%apply ptrdiff_t& { std::ptrdiff_t& };
+
+#endif
diff --git a/contrib/tools/swig/Lib/typemaps/valtypes.swg b/contrib/tools/swig/Lib/typemaps/valtypes.swg
new file mode 100644
index 00000000000..7623ff049b0
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/valtypes.swg
@@ -0,0 +1,216 @@
+/*---------------------------------------------------------------------
+ * Value typemaps (Type, const Type&) for value types, such as
+ * fundamental types (int, double), that define the AsVal/From
+ * methods.
+ *
+ * To apply them, just use one of the following macros:
+ *
+ * %typemaps_from(FromMeth, FromFrag, Type)
+ * %typemaps_asval(CheckCode, AsValMeth, AsValFrag, Type)
+ * %typemaps_asvalfrom(CheckCode, AsValMeth, FromMeth, AsValFrag, FromFrag, Type)
+ *
+ * or the simpler and normalize form:
+ *
+ * %typemaps_asvalfromn(CheckCode, Type)
+ *
+ * Also, you can use the individual typemap definitions:
+ *
+ * %value_in_typemap(asval_meth,frag,Type)
+ * %value_varin_typemap(asval_meth,frag,Type)
+ * %value_typecheck_typemap(checkcode,asval_meth,frag,Type)
+ * %value_directorout_typemap(asval_meth,frag,Type)
+ *
+ * %value_out_typemap(from_meth,frag,Type)
+ * %value_varout_typemap(from_meth,frag,Type)
+ * %value_constcode_typemap(from_meth,frag,Type)
+ * %value_directorin_typemap(from_meth,frag,Type)
+ * %value_throws_typemap(from_meth,frag,Type)
+ *
+ *---------------------------------------------------------------------*/
+
+/* in */
+
+%define %value_in_typemap(asval_meth,frag,Type...)
+ %typemap(in,noblock=1,fragment=frag) Type (Type val, int ecode = 0) {
+ ecode = asval_meth($input, &val);
+ if (!SWIG_IsOK(ecode)) {
+ %argument_fail(ecode, "$ltype", $symname, $argnum);
+ }
+ $1 = %static_cast(val,$ltype);
+ }
+ %typemap(freearg) Type ""
+ %typemap(in,noblock=1,fragment=frag) const Type & ($*ltype temp, Type val, int ecode = 0) {
+ ecode = asval_meth($input, &val);
+ if (!SWIG_IsOK(ecode)) {
+ %argument_fail(ecode, "$*ltype", $symname, $argnum);
+ }
+ temp = %static_cast(val, $*ltype);
+ $1 = &temp;
+ }
+ %typemap(freearg) const Type& ""
+%enddef
+
+/* out */
+
+%define %value_out_typemap(from_meth,frag,Type...)
+ %typemap(out,noblock=1,fragment=frag) Type, const Type {
+ %set_output(from_meth(%static_cast($1,Type)));
+ }
+ %typemap(out,noblock=1,fragment=frag) const Type& {
+ %set_output(from_meth(%static_cast(*$1,Type)));
+ }
+%enddef
+
+/* varin */
+
+%define %value_varin_typemap(asval_meth,frag,Type...)
+ %typemap(varin,fragment=frag) Type {
+ Type val;
+ int res = asval_meth($input, &val);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ $1 = %static_cast(val,$ltype);
+ }
+%enddef
+
+/* varout */
+
+%define %value_varout_typemap(from_meth,frag,Type...)
+ %typemap(varout,noblock=1,fragment=frag) Type, const Type& {
+ %set_varoutput(from_meth(%static_cast($1,Type)));
+ }
+%enddef
+
+/* constant installation code */
+
+%define %value_constcode_typemap(from_meth,frag,Type...)
+ %typemap(constcode,noblock=1,fragment=frag) Type {
+ %set_constant("$symname", from_meth(%static_cast($value,Type)));
+ }
+%enddef
+
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+
+%define %value_directorin_typemap(from_meth,frag,Type...)
+ %typemap(directorin,noblock=1,fragment=frag) Type *DIRECTORIN {
+ $input = from_meth(%static_cast(*$1,Type));
+ }
+ %typemap(directorin,noblock=1,fragment=frag) Type, const Type& {
+ $input = from_meth(%static_cast($1,Type));
+ }
+%enddef
+
+/* directorout */
+
+%define %value_directorout_typemap(asval_meth,frag,Type...)
+ %typemap(directorargout,noblock=1,fragment=frag) Type *DIRECTOROUT(Type swig_val, int swig_res) {
+ swig_res = asval_meth($result, &swig_val);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res, "$type");
+ }
+ *$1 = swig_val;
+ }
+ %typemap(directorout,noblock=1,fragment=frag) Type {
+ Type swig_val;
+ int swig_res = asval_meth($input, &swig_val);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res, "$type");
+ }
+ $result = %static_cast(swig_val,$type);
+ }
+ %typemap(directorout,noblock=1,fragment=frag,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) const Type& {
+ Type swig_val;
+ int swig_res = asval_meth($input, &swig_val);
+ if (!SWIG_IsOK(swig_res)) {
+ %dirout_fail(swig_res, "$type");
+ }
+ $basetype *temp = new $basetype(($basetype)swig_val);
+ swig_acquire_ownership(temp);
+ $result = temp;
+ }
+ %typemap(directorfree,noblock=1) const Type & {
+ if (director) {
+ director->swig_release_ownership(%as_voidptr($input));
+ }
+ }
+ %typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type
+%enddef
+
+#else
+
+#define %value_directorin_typemap(from_meth,frag,Type...)
+#define %value_directorout_typemap(asval_meth,frag,Type...)
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
+
+/* throws */
+
+%define %value_throws_typemap(from_meth,frag,Type...)
+ %typemap(throws,noblock=1,fragment=frag) Type {
+ %raise(from_meth(%static_cast($1,Type)), "$type", 0);
+ }
+%enddef
+
+/* typecheck */
+
+%define %value_typecheck_typemap(check,asval_meth,frag,Type...)
+ %typemap(typecheck,precedence=check,fragment=frag) Type, const Type& {
+ int res = asval_meth($input, NULL);
+ $1 = SWIG_CheckState(res);
+ }
+%enddef
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with AsVal methods
+ *---------------------------------------------------------------------*/
+%define %typemaps_asval(CheckCode, AsValMeth, AsValFrag, Type...)
+ %value_in_typemap(%arg(AsValMeth), %arg(AsValFrag), Type);
+ %value_varin_typemap(%arg(AsValMeth), %arg(AsValFrag), Type);
+ %value_directorout_typemap(%arg(AsValMeth), %arg(AsValFrag), Type);
+ %value_typecheck_typemap(%arg(CheckCode), %arg(AsValMeth), %arg(AsValFrag), Type);
+ %value_input_typemap(%arg(CheckCode), %arg(AsValMeth), %arg(AsValFrag), Type);
+%enddef
+
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with from method
+ *---------------------------------------------------------------------*/
+
+%define %typemaps_from(FromMeth, FromFrag, Type...)
+ %value_out_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_varout_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_constcode_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_directorin_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_throws_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_output_typemap(%arg(FromMeth), %arg(FromFrag), Type);
+%enddef
+
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with asval/from method
+ *---------------------------------------------------------------------*/
+
+%define %typemaps_asvalfrom(CheckCode, AsValMeth, FromMeth,
+ AsValFrag, FromFrag, Type...)
+ %typemaps_asval(%arg(CheckCode), %arg(AsValMeth), %arg(AsValFrag), Type);
+ %typemaps_from(%arg(FromMeth), %arg(FromFrag), Type);
+ %value_inout_typemap(Type);
+%enddef
+
+
+/*---------------------------------------------------------------------
+ * typemap definition for types with for 'normalized' asval/from methods
+ *---------------------------------------------------------------------*/
+%define %typemaps_asvalfromn(CheckCode, Type...)
+ %typemaps_asvalfrom(%arg(CheckCode),
+ SWIG_AsVal(Type),
+ SWIG_From(Type),
+ %arg(SWIG_AsVal_frag(Type)),
+ %arg(SWIG_From_frag(Type)),
+ Type);
+%enddef
diff --git a/contrib/tools/swig/Lib/typemaps/void.swg b/contrib/tools/swig/Lib/typemaps/void.swg
new file mode 100644
index 00000000000..795992bf480
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/void.swg
@@ -0,0 +1,84 @@
+/* ------------------------------------------------------------
+ * Void * - Accepts any kind of pointer
+ * ------------------------------------------------------------ */
+
+/* in */
+
+%typemap(in,noblock=1) void * (int res) {
+ res = SWIG_ConvertPtr($input,%as_voidptrptr(&$1), 0, $disown);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "$type", $symname, $argnum);
+ }
+}
+%typemap(freearg) void * ""
+
+%typemap(in,noblock=1) void * const& ($*ltype temp = 0, int res) {
+ res = SWIG_ConvertPtr($input, %as_voidptrptr(&temp), 0, $disown);
+ if (!SWIG_IsOK(res)) {
+ %argument_fail(res, "Stype", $symname, $argnum);
+ }
+ $1 = &temp;
+}
+%typemap(freearg) void * const& ""
+
+
+/* out */
+
+#if defined(VOID_Object)
+%typemap(out,noblock=1) void { $result = VOID_Object; }
+#else
+%typemap(out,noblock=1) void {}
+#endif
+
+/* varin */
+
+%typemap(varin) void * {
+ void *temp = 0;
+ int res = SWIG_ConvertPtr($input, &temp, 0, SWIG_POINTER_DISOWN);
+ if (!SWIG_IsOK(res)) {
+ %variable_fail(res, "$type", "$name");
+ }
+ $1 = ($1_ltype) temp;
+}
+
+/* typecheck */
+
+%typecheck(SWIG_TYPECHECK_VOIDPTR, noblock=1) void *
+{
+ void *ptr = 0;
+ int res = SWIG_ConvertPtr($input, &ptr, 0, 0);
+ $1 = SWIG_CheckState(res);
+}
+
+#if defined(SWIG_DIRECTOR_TYPEMAPS)
+
+/* directorin */
+
+%typemap(directorin,noblock=1) void *, void const*, void *const, void const *const,
+ void const *&, void *const &, void const *const & {
+ $input = SWIG_NewPointerObj(%as_voidptr($1), $descriptor, %newpointer_flags);
+}
+
+/* directorout */
+
+%typemap(directorout,noblock=1) void * (void *argp, int res) {
+ res = SWIG_ConvertPtr($input, &argp, 0, 0);
+ if (!SWIG_IsOK(res)) {
+ %dirout_fail(res,"$type");
+ }
+ $result = %reinterpret_cast(argp, $ltype);
+}
+
+%typemap(directorout,noblock=1,warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) void * const& (void *argp, int res) {
+ res = SWIG_ConvertPtr($input, &argp, 0, $disown);
+ if (!SWIG_IsOK(res)) {
+ %dirout_fail(res,"$type");
+ }
+ static $*ltype temp = %reinterpret_cast(argp, $*ltype);
+ $result = &temp;
+}
+
+
+
+#endif /* SWIG_DIRECTOR_TYPEMAPS */
+
diff --git a/contrib/tools/swig/Lib/typemaps/wstring.swg b/contrib/tools/swig/Lib/typemaps/wstring.swg
new file mode 100644
index 00000000000..25d2f77e682
--- /dev/null
+++ b/contrib/tools/swig/Lib/typemaps/wstring.swg
@@ -0,0 +1,36 @@
+%ensure_fragment(SWIG_AsWCharPtrAndSize)
+%ensure_fragment(SWIG_FromWCharPtrAndSize)
+
+
+%types(wchar_t *);
+
+%fragment("SWIG_pwchar_descriptor","header") {
+SWIGINTERN swig_type_info*
+SWIG_pwchar_descriptor()
+{
+ static swig_type_info *info = 0;
+ if (!info) {
+ info = SWIG_TypeQuery("_p_wchar_t");
+ }
+ return info;
+}
+}
+
+%fragment("SWIG_wcsnlen","header",fragment="SWIG_FromWCharPtrAndSize") {
+SWIGINTERN size_t
+SWIG_wcsnlen(const wchar_t* s, size_t maxlen)
+{
+ const wchar_t *p;
+ for (p = s; maxlen-- && *p; p++)
+ ;
+ return p - s;
+}
+}
+
+%include <typemaps/strings.swg>
+%typemaps_string(%checkcode(UNISTRING), %checkcode(UNICHAR),
+ SWIGWARN_TYPEMAP_WCHARLEAK_MSG,
+ wchar_t, WChar, SWIG_AsWCharPtrAndSize, SWIG_FromWCharPtrAndSize,
+ wcslen, SWIG_wcsnlen,
+ "<wchar.h>", WCHAR_MIN, WCHAR_MAX)
+
diff --git a/contrib/tools/swig/Lib/unique_ptr.swg b/contrib/tools/swig/Lib/unique_ptr.swg
new file mode 100644
index 00000000000..a3503831413
--- /dev/null
+++ b/contrib/tools/swig/Lib/unique_ptr.swg
@@ -0,0 +1,22 @@
+/* -----------------------------------------------------------------------------
+ * unique_ptr.swg
+ *
+ * Common std::unique_ptr support.
+ * Not for direct inclusion.
+ * ----------------------------------------------------------------------------- */
+
+
+%fragment("SwigNoDeleteUniquePtr", "header", fragment="<memory>") {
+namespace swig {
+ template<typename T>
+ struct NoDeleteUniquePtr {
+ std::unique_ptr<T> uptr;
+ NoDeleteUniquePtr(T *p = 0) : uptr(p) {}
+ ~NoDeleteUniquePtr() {uptr.release();}
+ };
+}
+}
+
+namespace std {
+ template <class T> class unique_ptr {};
+}
diff --git a/contrib/tools/swig/Lib/wchar.i b/contrib/tools/swig/Lib/wchar.i
new file mode 100644
index 00000000000..14de346346d
--- /dev/null
+++ b/contrib/tools/swig/Lib/wchar.i
@@ -0,0 +1,11 @@
+/* -----------------------------------------------------------------------------
+ * wchar.i
+ * ----------------------------------------------------------------------------- */
+
+/*
+ wchar_t not supported, unless otherwise specified in the target language.
+*/
+
+#if defined(SWIG_WCHAR)
+#undef SWIG_WCHAR
+#endif
diff --git a/contrib/tools/swig/Lib/windows.i b/contrib/tools/swig/Lib/windows.i
new file mode 100644
index 00000000000..3e4626196b8
--- /dev/null
+++ b/contrib/tools/swig/Lib/windows.i
@@ -0,0 +1,152 @@
+/* -----------------------------------------------------------------------------
+ * windows.i
+ *
+ * SWIG library file to support types found in windows.h as well as Microsoft
+ * integral type extensions. The types are set for 32 bit Windows.
+ * ----------------------------------------------------------------------------- */
+
+// Support for non ISO (Windows) integral types
+%apply unsigned char { unsigned __int8 };
+%apply const unsigned char& { const unsigned __int8& };
+
+%apply signed char { __int8 };
+%apply const signed char& { const __int8& };
+
+%apply unsigned short { unsigned __int16 };
+%apply const unsigned short& { const unsigned __int16& };
+
+%apply short { __int16 };
+%apply const short& { const __int16& };
+
+%apply unsigned int { unsigned __int32 };
+%apply const unsigned int& { const unsigned __int32& };
+
+%apply int { __int32 };
+%apply const int& { const __int32& };
+
+%apply unsigned long long { unsigned __int64 };
+%apply const unsigned long long& { const unsigned __int64& };
+
+%apply long long { __int64 };
+%apply const long long& { const __int64& };
+
+
+// Workaround Microsoft calling conventions
+#define __cdecl
+#define __fastcall
+#define __far
+#define __forceinline
+#define __fortran
+#define __inline
+#define __pascal
+#define __stdcall
+#define __syscall
+#define _cdecl
+#define _fastcall
+#define _inline
+#define _pascal
+#define _stdcall
+#define WINAPI
+#define __declspec(WINDOWS_EXTENDED_ATTRIBUTE)
+
+#define __w64
+
+// Types from windef.h
+typedef unsigned long ULONG;
+typedef ULONG *PULONG;
+typedef unsigned short USHORT;
+typedef USHORT *PUSHORT;
+typedef unsigned char UCHAR;
+typedef UCHAR *PUCHAR;
+typedef char *PSZ;
+typedef unsigned long DWORD;
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef float FLOAT;
+typedef FLOAT *PFLOAT;
+typedef BOOL *PBOOL;
+typedef BOOL *LPBOOL;
+typedef BYTE *PBYTE;
+typedef BYTE *LPBYTE;
+typedef int *PINT;
+typedef int *LPINT;
+typedef WORD *PWORD;
+typedef WORD *LPWORD;
+typedef long *LPLONG;
+typedef DWORD *PDWORD;
+typedef DWORD *LPDWORD;
+typedef void *LPVOID;
+typedef const void *LPCVOID;
+typedef int INT;
+typedef unsigned int UINT;
+typedef unsigned int *PUINT;
+
+// Types from basetsd.h
+typedef signed char INT8, *PINT8;
+typedef signed short INT16, *PINT16;
+typedef signed int INT32, *PINT32;
+typedef signed __int64 INT64, *PINT64;
+typedef unsigned char UINT8, *PUINT8;
+typedef unsigned short UINT16, *PUINT16;
+typedef unsigned int UINT32, *PUINT32;
+typedef unsigned __int64 UINT64, *PUINT64;
+typedef signed int LONG32, *PLONG32;
+typedef unsigned int ULONG32, *PULONG32;
+typedef unsigned int DWORD32, *PDWORD32;
+typedef __w64 int INT_PTR, *PINT_PTR;
+typedef __w64 unsigned int UINT_PTR, *PUINT_PTR;
+typedef __w64 long LONG_PTR, *PLONG_PTR;
+typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR;
+typedef unsigned short UHALF_PTR, *PUHALF_PTR;
+typedef short HALF_PTR, *PHALF_PTR;
+typedef __w64 long SHANDLE_PTR;
+typedef __w64 unsigned long HANDLE_PTR;
+typedef ULONG_PTR SIZE_T, *PSIZE_T;
+typedef LONG_PTR SSIZE_T, *PSSIZE_T;
+typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
+typedef __int64 LONG64, *PLONG64;
+typedef unsigned __int64 ULONG64, *PULONG64;
+typedef unsigned __int64 DWORD64, *PDWORD64;
+
+// Types from winnt.h
+typedef void *PVOID;
+typedef void *PVOID64;
+#ifndef VOID
+#define VOID void
+#endif
+typedef char CHAR;
+typedef short SHORT;
+typedef long LONG;
+typedef CHAR *PCHAR;
+typedef CHAR *LPCH, *PCH;
+typedef const CHAR *LPCCH, *PCCH;
+typedef CHAR *NPSTR;
+typedef CHAR *LPSTR, *PSTR;
+typedef const CHAR *LPCSTR, *PCSTR;
+typedef char TCHAR, *PTCHAR;
+typedef unsigned char TBYTE , *PTBYTE ;
+typedef LPSTR LPTCH, PTCH;
+typedef LPSTR PTSTR, LPTSTR, PUTSTR, LPUTSTR;
+typedef LPCSTR PCTSTR, LPCTSTR, PCUTSTR, LPCUTSTR;
+typedef SHORT *PSHORT;
+typedef LONG *PLONG;
+typedef void *HANDLE;
+typedef HANDLE *PHANDLE;
+typedef BYTE FCHAR;
+typedef WORD FSHORT;
+typedef DWORD FLONG;
+typedef LONG HRESULT;
+typedef char CCHAR;
+typedef DWORD LCID;
+typedef PDWORD PLCID;
+typedef WORD LANGID;
+typedef __int64 LONGLONG;
+typedef unsigned __int64 ULONGLONG;
+typedef LONGLONG *PLONGLONG;
+typedef ULONGLONG *PULONGLONG;
+typedef ULONGLONG DWORDLONG;
+typedef DWORDLONG *PDWORDLONG;
+typedef BYTE BOOLEAN;
+typedef BOOLEAN *PBOOLEAN;
+
diff --git a/contrib/tools/swig/README b/contrib/tools/swig/README
new file mode 100644
index 00000000000..e499e7605e6
--- /dev/null
+++ b/contrib/tools/swig/README
@@ -0,0 +1,139 @@
+SWIG (Simplified Wrapper and Interface Generator)
+
+Tagline: SWIG is a compiler that integrates C and C++ with languages
+ including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua,
+ Octave, R, Scheme (Guile, MzScheme/Racket), Scilab, Ocaml.
+ SWIG can also export its parse tree into XML.
+
+SWIG reads annotated C/C++ header files and creates wrapper code (glue
+code) in order to make the corresponding C/C++ libraries available to
+the listed languages, or to extend C/C++ programs with a scripting
+language.
+
+Up-to-date SWIG related information can be found at
+
+ https://www.swig.org
+
+A SWIG FAQ and other hints can be found on the SWIG Wiki:
+
+ https://github.com/swig/swig/wiki
+
+License
+=======
+Please see the LICENSE file for details of the SWIG license. For
+further insight into the license including the license of SWIG's
+output code, please visit
+
+ https://www.swig.org/legal.html
+
+Release Notes
+=============
+Please see the CHANGES.current file for a detailed list of bug fixes and
+new features for the current release. The CHANGES file contains bug fixes
+and new features for older versions. A summary of changes in each release
+can be found in the RELEASENOTES file.
+
+Documentation
+=============
+The Doc/Manual directory contains the most recent set of updated
+documentation for this release. The documentation is available in
+three different formats, each of which contains identical content.
+These format are, pdf (Doc/Manual/SWIGDocumentation.pdf), single
+page html (Doc/Manual/SWIGDocumentation.html) or multiple page html
+(other files in Doc/Manual). Please select your chosen format and
+copy/install to wherever takes your fancy.
+
+There is some technical developer documentation available in the
+Doc/Devel subdirectory. This is not necessarily up-to-date, but it
+has some information on SWIG internals.
+
+Documentation is also online at https://www.swig.org/doc.html.
+
+Backwards Compatibility
+=======================
+The developers strive their best to preserve backwards compatibility
+between releases, but this is not always possible as the overriding
+aim is to provide the best wrapping experience. Where backwards
+compatibility is known to be broken, it is clearly marked as an
+incompatibility in the CHANGES and CHANGES.current files.
+
+See the documentation for details of the SWIG_VERSION preprocessor
+symbol if you have backward compatibility issues and need to use more
+than one version of SWIG.
+
+Installation
+============
+Please read the Doc/Manual/Preface.html#Preface_installation for
+full installation instructions for Windows, Unix and Mac OS X
+using the release tarball/zip file. The INSTALL file has generic
+build and installation instructions for Unix users.
+Users wishing to build and install code from Github should
+visit https://swig.org/svn.html to obtain the more detailed
+instructions required for building code obtained from Github - extra
+steps are required compared to building from the release tarball.
+
+Testing
+=======
+The typical 'make -k check' can be performed on Unix operating systems.
+Please read Doc/Manual/Preface.html#Preface_testing for details.
+
+Examples
+========
+The Examples directory contains a variety of examples of using SWIG
+and it has some browsable documentation. Simply point your browser to
+the file "Example/index.html".
+
+The Examples directory also includes Visual C++ project 6 (.dsp) files for
+building some of the examples on Windows. Later versions of Visual Studio
+will convert these old style project files into a current solution file.
+
+Known Issues
+============
+There are minor known bugs, details of which are in the bug tracker, see
+https://www.swig.org/bugs.html.
+
+Troubleshooting
+===============
+In order to operate correctly, SWIG relies upon a set of library
+files. If after building SWIG, you get error messages like this,
+
+ $ swig foo.i
+ :1. Unable to find 'swig.swg'
+ :3. Unable to find 'tcl8.swg'
+
+it means that SWIG has either been incorrectly configured or
+installed. To fix this:
+
+ 1. Make sure you remembered to do a 'make install' and that
+ the installation actually worked. Make sure you have
+ write permission on the install directory.
+
+ 2. If that doesn't work, type 'swig -swiglib' to find out
+ where SWIG thinks its library is located.
+
+ 3. If the location is not where you expect, perhaps
+ you supplied a bad option to configure. Use
+ ./configure --prefix=pathname to set the SWIG install
+ location. Also, make sure you don't include a shell
+ escape character such as ~ when you specify the path.
+
+ 4. The SWIG library can be changed by setting the SWIG_LIB
+ environment variable. However, you really shouldn't
+ have to do this.
+
+If you are having other troubles, you might look at the SWIG Wiki at
+https://github.com/swig/swig/wiki.
+
+Participate!
+============
+Please report any errors and submit patches (if possible)! We only
+have access to a limited variety of hardware (Linux, Solaris, OS-X,
+and Windows). All contributions help.
+
+If you would like to join the SWIG development team or contribute a
+language module to the distribution, please contact the swig-devel
+mailing list, details at https://www.swig.org/mail.html.
+
+
+ -- The SWIG Maintainers
+
diff --git a/contrib/tools/swig/RELEASENOTES b/contrib/tools/swig/RELEASENOTES
new file mode 100644
index 00000000000..324334a1dc7
--- /dev/null
+++ b/contrib/tools/swig/RELEASENOTES
@@ -0,0 +1,555 @@
+This file contains a brief overview of the changes made in each release.
+A detailed description of changes are available in the CHANGES.current
+and CHANGES files.
+
+Release Notes
+=============
+Detailed release notes are available with the release and are also
+published on the SWIG web site at https://swig.org/release.html.
+
+SWIG-4.3.1 summary:
+- Small number of regression fixes for Python and Java.
+- Corner case operator precedence bug fix affecting type deduction.
+- Octave 10 compilation errors fix.
+
+SWIG-4.3.0 summary:
+- Add experimental support for C as a target language.
+- MzScheme/Racket is deprecated and planned for removal in SWIG-4.4.
+- The distributed Windows binary is now a 64-bit executable.
+- Add some missing use of move semantics for performance improvements.
+- Enhanced handling of namespaces when using the nspace feature.
+- STL wrapper enhancements for std::unique_ptr, std::string_view,
+ std::filesystem.
+- Various enum and enum class wrapping improvements.
+- Other C++ handling improvements around templates, friends, C++11
+ trailing return types and C++17 fold expressions.
+- Many parser improvements for both C and C++, especially expressions.
+- Improvements to handling of string and character literals.
+- Minor preprocessor fixes.
+- Python: Stricter stable ABI conformance, add support for python-3.13.
+- C#: Add support for converting Doxygen comments into XML C# comments.
+- Various other target language specific enhancements and updates for
+ Java, Javascript, Lua, MzScheme, Ocaml, Octave, Perl, Python, R, Ruby.
+
+SWIG-4.2.1 summary:
+- Tcl 9.0 support.
+- Octave 9.0 support.
+- Improvements wrapping friend functions.
+- Variadic templated functions within a template support.
+- Type deduction enhancements.
+- Stability and regression fixes.
+
+SWIG-4.2.0 summary:
+- Various template wrapping improvements: template template parameters,
+ variadic templates, partially specialized templates, const template
+ parameters and improved error checking instantiating templates.
+- Improved decltype() support for expressions.
+- C++14 auto without trailing return type and C++11 auto variables.
+- Numerous C++ using declarations improvements.
+- Numerous fixes for constructors, destructors and assignment operators:
+ implicit, default and deleted and related non-assignable variable
+ wrappers.
+- STL: std::array and std::map improvements, std::string_view support
+ added.
+- Various C preprocessor improvements.
+- Various issues fixed to do with architecture specific long type.
+- Various Doxygen improvements.
+- D1/Tango support removed. D2/Phobos is now the supported D version
+ and SWIG now generates code which works with recent D2 releases.
+- New Javascript generator targeting Node.js binary stable ABI Node-API.
+- Octave 8.1 support added.
+- PHP7 support removed, PHP8 is now the supported PHP version.
+- Python STL container wrappers now use the Python Iterator Protocol.
+- Python stable ABI support added.
+- Python 3.12 support added.
+- Ruby 3.2 and 3.3 support.
+- Scilab 2023.* support added.
+- Various minor enhancements for C#, Go, Guile, Javascript, Lua, Ocaml,
+ Perl, PHP, R, Racket, Ruby, Scilab and Tcl.
+- A number of deprecated features have been removed.
+
+SWIG-4.1.1 summary:
+- Couple of stability fixes.
+- Stability fix in ccache-swig when calculating hashes of inputs.
+- Some template handling improvements.
+- R - minor fixes plus deprecation for rtypecheck typemaps being optional.
+
+SWIG-4.1.0 summary:
+- Add Javascript Node v12-v18 support, remove support prior to v6.
+- Octave 6.0 to 6.4 support added.
+- Add PHP 8 support.
+- PHP wrapping is now done entirely via PHP's C API - no more .php wrapper.
+- Perl 5.8.0 is now the oldest version SWIG supports.
+- Python 3.3 is now the oldest Python 3 version SWIG supports.
+- Python 3.9-3.11 support added.
+- Various memory leak fixes in Python generated code.
+- Scilab 5.5-6.1 support improved.
+- Many improvements for each and every target language.
+- Various preprocessor expression handling improvements.
+- Improved C99, C++11, C++14, C++17 support. Start adding C++20 standard.
+- Make SWIG much more move semantics friendly.
+- Add C++ std::unique_ptr support.
+- Few minor C++ template handling improvements.
+- Various C++ using declaration fixes.
+- Few fixes for handling Doxygen comments.
+- GitHub Actions is now used instead of Travis CI for continuous integration.
+- Add building SWIG using CMake as a secondary build system.
+- Update optional SWIG build dependency for regex support from PCRE to PCRE2.
+
+SWIG-4.0.2 summary:
+- A few fixes around doxygen comment handling.
+- Ruby 2.7 support added.
+- Various minor improvements to C#, D, Java, OCaml, Octave, Python,
+ R, Ruby.
+- Considerable performance improvement running SWIG on large
+ interface files.
+
+SWIG-4.0.1 summary:
+- SWIG now cleans up on error by removing all generated files.
+- Add Python 3.8 support.
+- Python Sphinx compatibility added for Doxygen comments.
+- Some minor regressions introduced in 4.0.0 were fixed.
+- Fix some C++17 compatibility problems in Python and Ruby generated
+ code.
+- Minor improvements/fixes for C#, Java, Javascript, Lua, MzScheme,
+ Ocaml, Octave and Python.
+
+SWIG-4.0.0 summary:
+- Support for Doxygen documentation comments which are parsed and
+ converted into JavaDoc or PyDoc comments.
+- STL wrappers improved for C#, Java and Ruby.
+- C++11 STL containers added for Java, Python and Ruby.
+- Improved support for parsing C++11 and C++14 code.
+- Various fixes for shared_ptr.
+- Various C preprocessor corner case fixes.
+- Corner case fixes for member function pointers.
+- Python module overhaul by simplifying the generated code and turning
+ most optimizations on by default.
+- %template improvements wrt scoping to align with C++ explicit
+ template instantiations.
+- Added support for a command-line options file (sometimes called a
+ response file).
+- Numerous enhancements and fixes for all supported target languages.
+- SWIG now classifies the status of target languages into either
+ 'Experimental' or 'Supported' to indicate the expected maturity
+ level.
+- Support for CFFI, Allegrocl, Chicken, CLISP, S-EXP, UFFI, Pike,
+ Modula3 has been removed.
+- Octave 4.4-5.1 support added.
+- PHP5 support removed, PHP7 is now the supported PHP version.
+- Minimum Python version required is now 2.7, 3.2-3.7 are the only
+ other versions supported.
+- Added support for Javascript NodeJS versions 2-10.
+- OCaml support is much improved and updated, minimum OCaml version
+ required is now 3.12.0.
+
+SWIG-3.0.12 summary:
+- Add support for Octave-4.2.
+- Enhance %extend to support template functions.
+- Language specific enhancements and fixes for C#, D, Guile, Java, PHP7.
+
+SWIG-3.0.11 summary:
+- PHP 7 support added.
+- C++11 alias templates and type aliasing support added.
+- Minor fixes and enhancements for C# Go Guile Java Javascript Octave
+ PHP Python R Ruby Scilab XML.
+
+SWIG-3.0.10 summary:
+- Regression fixes for smart pointers and importing Python modules.
+
+SWIG-3.0.9 summary:
+- Add support for Python's implicit namespace packages.
+- Fixes to support Go 1.6.
+- C++11 std::array support added for Java.
+- Improved C++ multiple inheritance support for Java/C# wrappers.
+- Various other minor fixes and improvements for C#, D, Go, Java,
+ Javascript, Lua, Python, R, Ruby, Scilab.
+
+SWIG-3.0.8 summary:
+- pdf documentation enhancements.
+- Various Python 3.5 issues fixed.
+- std::array support added for Ruby and Python.
+- shared_ptr support added for Ruby.
+- Minor improvements for CFFI, Go, Java, Perl, Python, Ruby.
+
+SWIG-3.0.7 summary:
+- Add support for Octave-4.0.0.
+- Remove potential Android security exploit in generated Java classes.
+- Minor new features and bug fixes.
+
+SWIG-3.0.6 summary:
+- Stability and regression fixes.
+- Fixed parsing of C++ corner cases.
+- Language improvements and bug fixes for C#, Go, Java, Lua, Python, R.
+
+SWIG-3.0.5 summary:
+- Added support for Scilab.
+- Important Python regression fix when wrapping C++ default arguments.
+- Minor improvements for C#, Go, Octave, PHP and Python.
+
+SWIG-3.0.4 summary:
+- Python regression fix when wrapping C++ default arguments.
+- Improved error messages.
+
+SWIG-3.0.3 summary:
+- Add support for C++11 strongly typed enumerations.
+- Numerous bug fixes and minor enhancements for C#, D, Go, Java,
+ Javascript, PHP, Perl and Python wrappers.
+
+SWIG-3.0.2 summary:
+- Bug fix during install and a couple of other minor changes.
+
+SWIG-3.0.1 summary:
+- Javascript module added. This supports JavascriptCore (Safari/Webkit),
+ v8 (Chromium) and node.js currently.
+- A few notable regressions introduced in 3.0.0 have been fixed - in
+ Lua, nested classes and parsing of operator <<.
+- The usual round of bug fixes and minor improvements for:
+ C#, GCJ, Go, Java, Lua, PHP and Python.
+
+SWIG-3.0.0 summary:
+- This is a major new release focusing primarily on C++ improvements.
+- C++11 support added. Please see documentation for details of supported
+ features: https://www.swig.org/Doc3.0/CPlusPlus11.html
+- Nested class support added. This has been taken full advantage of in
+ Java and C#. Other languages can use the nested classes, but require
+ further work for a more natural integration into the target language.
+ We urge folk knowledgeable in the other target languages to step
+ forward and help with this effort.
+- Lua: improved metatables and support for %nspace.
+- Go 1.3 support added.
+- Python import improvements including relative imports.
+- Python 3.3 support completed.
+- Perl director support added.
+- C# .NET 2 support is now the minimum. Generated using statements are
+ replaced by fully qualified names.
+- Bug fixes and improvements to the following languages:
+ C#, Go, Guile, Java, Lua, Perl, PHP, Python, Octave, R, Ruby, Tcl
+- Various other bug fixes and improvements affecting all languages.
+- Note that this release contains some backwards incompatible changes
+ in some languages.
+- Full detailed release notes are in the changes file.
+
+SWIG-2.0.12 summary:
+- This is a maintenance release backporting some fixes from the pending
+ 3.0.0 release.
+- Octave 3.8 support added.
+- C++11 support for new versions of erase/insert in the STL containers.
+- Compilation fixes on some systems for the generated Lua, PHP, Python
+ and R wrappers.
+
+SWIG-2.0.11 summary:
+- Minor bug fixes and enhancements mostly in Python, but also
+ C#, Lua, Ocaml, Octave, Perl, PHP, Python, R, Ruby, Tcl.
+
+SWIG-2.0.10 summary:
+- Ruby 1.9 support is now complete.
+- Add support for Guile 2.0 and Guile 1.6 support (GH interface) has
+ been dropped.
+- Various small language neutral improvements and fixes.
+- Various bug fixes and minor improvements specific to C#, CFFI, D,
+ Java, Octave, PHP, Python,
+- Minor bug fix in ccache-swig.
+- Development has moved to Github with Travis continuous integration
+ testing - patches using https://github.com/swig/swig are welcome.
+
+SWIG-2.0.9 summary:
+- Improved typemap matching.
+- Ruby 1.9 support is much improved.
+- Various bug fixes and minor improvements in C#, CFFI, Go, Java,
+ Modula3, Octave, Perl, Python, R, Ruby, Tcl and in ccache-swig.
+
+SWIG-2.0.8 summary:
+- Fix a couple of regressions introduced in 2.0.5 and 2.0.7.
+- Improved using declarations and using directives support.
+- Minor fixes/enhancements for C#, Java, Octave, Perl and Python.
+
+SWIG-2.0.7 summary:
+- Important regression fixes since 2.0.5 for typemaps in general and
+ in Python.
+- Fixes and enhancements for Go, Java, Octave and PHP.
+
+SWIG-2.0.6 summary:
+- Regression fix for Python STL wrappers on some systems.
+
+SWIG-2.0.5 summary:
+- Official Android support added including documentation and examples.
+- Improvements involving templates:
+ 1) Various fixes with templates and typedef types.
+ 2) Some template lookup problems fixed.
+ 3) Templated type fixes to use correct typemaps.
+- Autodoc documentation generation improvements.
+- Python STL container wrappers improvements including addition of
+ stepped slicing.
+- Approximately 70 fixes and minor enhancements for the following
+ target languages: AllegroCL, C#, D, Go, Java, Lua, Ocaml, Octave,
+ Perl, PHP, Python, R, Ruby, Tcl, Xml.
+
+SWIG-2.0.4 summary:
+- This is mainly a Python oriented release including support for Python
+ built-in types for superior performance with the new -builtin option.
+ The -builtin option is especially suitable for performance-critical
+ libraries and applications that call wrapped methods repeatedly.
+ See the python-specific chapter of the SWIG manual for more info.
+- Python 3.2 support has also been added and various Python bugs have
+ been fixed.
+- Octave 3.4 support has also been added.
+- There are also the usual minor generic improvements, as well as bug
+ fixes and enhancements for D, Guile, Lua, Octave, Perl and Tcl.
+
+SWIG-2.0.3 summary:
+- A bug fix release including a couple of fixes for regressions in the
+ 2.0 series.
+
+SWIG-2.0.2 summary:
+- Support for the D language has been added.
+- Various bug fixes and minor enhancements.
+- Bug fixes particular to the Clisp, C#, Go, MzScheme, Ocaml, PHP, R,
+ Ruby target languages.
+
+SWIG-2.0.1 summary:
+- Support for the Go language has been added.
+- New regular expression (regex) encoder for renaming symbols based on
+ the Perl Compatible Regular Expressions (PCRE) library.
+- Numerous fixes in reporting file and line numbers in error and warning
+ messages.
+- Various bug fixes and improvements in the C#, Lua, Perl, PHP, Ruby
+ and Python language modules.
+
+SWIG-2.0.0 summary:
+- License changes, see LICENSE file and https://www.swig.org/legal.html.
+- Much better nested class/struct support.
+- Much improved template partial specialization and explicit
+ specialization handling.
+- Namespace support improved with the 'nspace' feature where namespaces
+ can be automatically translated into Java packages or C# namespaces.
+- Improved typemap and symbol table debugging.
+- Numerous subtle typemap matching rule changes when using the default
+ (SWIGTYPE) type. These now work much like C++ class template partial
+ specialization matching.
+- Other small enhancements for typemaps. Typemap fragments are also now
+ official and documented.
+- Warning and error display refinements.
+- Wrapping of shared_ptr is improved and documented now.
+- Numerous C++ unary scope operator (::) fixes.
+- Better support for boolean expressions.
+- Various bug fixes and improvements in the Allegrocl, C#, Java, Lua,
+ Octave, PHP, Python, R, Ruby and XML modules.
+
+SWIG-1.3.40 summary:
+- SWIG now supports directors for PHP.
+- PHP support improved in general.
+- Octave 3.2 support added.
+- Various bug fixes/enhancements for Allegrocl, C#, Java, Octave, Perl,
+ Python, Ruby and Tcl.
+- Other generic fixes and minor new features.
+
+SWIG-1.3.39 summary:
+- Some new small feature enhancements.
+- Improved C# std::vector wrappers.
+- Bug fixes: mainly Python, but also Perl, MzScheme, CFFI, Allegrocl
+ and Ruby
+
+SWIG-1.3.38 summary:
+- Output directory regression fix and other minor bug fixes
+
+SWIG-1.3.37 summary:
+- Python 3 support added
+- SWIG now ships with a version of ccache that can be used with SWIG.
+ This enables the files generated by SWIG to be cached so that repeated
+ use of SWIG on unchanged input files speeds up builds quite considerably.
+- PHP 4 support removed and PHP support improved in general
+- Improved C# array support
+- Numerous Allegro CL improvements
+- Bug fixes/enhancements for Python, PHP, Java, C#, Chicken, Allegro CL,
+ CFFI, Ruby, Tcl, Perl, R, Lua.
+- Other minor generic bug fixes and enhancements
+
+SWIG-1.3.36 summary:
+- Enhancement to directors to wrap all protected members
+- Optimisation feature for objects returned by value
+- A few bugs fixes in the PHP, Java, Ruby, R, C#, Python, Lua and
+ Perl modules
+- Other minor generic bug fixes
+
+SWIG-1.3.35 summary:
+- Octave language module added
+- Bug fixes in Python, Lua, Java, C#, Perl modules
+- A few other generic bugs and runtime assertions fixed
+
+SWIG-1.3.34 summary:
+- shared_ptr support for Python
+- Support for latest R - version 2.6
+- Various minor improvements/bug fixes for R, Lua, Python, Java, C#
+- A few other generic bug fixes, mainly for templates and using statements
+
+SWIG-1.3.33 summary:
+- Fix regression for Perl where C++ wrappers would not compile
+- Fix regression parsing macros
+
+SWIG-1.3.32 summary:
+- shared_ptr support for Java and C#
+- Enhanced STL support for Ruby
+- Windows support for R
+- Fixed long-standing memory leak in PHP Module
+- Numerous fixes and minor enhancements for Allegrocl, C#, cffi, Chicken, Guile,
+ Java, Lua, Ocaml, Perl, PHP, Python, Ruby, Tcl.
+- Improved warning support
+
+SWIG-1.3.31 summary:
+- Python modern classes regression fix
+
+SWIG-1.3.30 summary:
+- Python-2.5 support
+- New language module: R
+- Director support added for C#
+- Numerous director fixes and improvements
+- Improved mingw/msys support
+- Better constants support in Guile and chicken modules
+- Support for generating PHP5 class wrappers
+- Important Java premature garbage collection fix
+- Minor improvements/fixes in cffi, php, allegrocl, perl, chicken, lua, ruby,
+ ocaml, python, java, c# and guile language modules
+- Many many other bug fixes
+
+SWIG-1.3.29 summary:
+- Numerous important bug fixes
+- Few minor new features
+- Some performance improvements in generated code for Python
+
+SWIG-1.3.28 summary:
+- More powerful renaming (%rename) capability.
+- More user friendly warning handling.
+- Add finer control for default constructors and destructors. We discourage
+ the use of the 'nodefault' option, which disables both constructors and
+ destructors, leading to possible memory leaks. Use instead 'nodefaultctor'
+ and/or 'nodefaultdtor'.
+- Automatic copy constructor wrapper generation via the 'copyctor' option/feature.
+- Better handling of Windows extensions and types.
+- Better runtime error reporting.
+- Add the %catches directive to catch and dispatch exceptions.
+- Add the %naturalvar directive for more 'natural' variable wrapping.
+- Better default handling of std::string variables using the %naturalvar directive.
+- Add the %allowexcept and %exceptionvar directives to handle exceptions when
+ accessing a variable.
+- Add the %delobject directive to mark methods that act like destructors.
+- Add the -fastdispatch option to enable smaller and faster overload dispatch
+ mechanism.
+- Template support for %rename, %feature and %typemap improved.
+- Add/doc more debug options, such as -dump_module, -debug_typemaps, etc.
+- Unified typemap library (UTL) potentially providing core typemaps for all
+ scripting languages based on the recently evolving Python typemaps.
+- New language module: Common Lisp with CFFI.
+- Python, Ruby, Perl and Tcl use the new UTL, many old reported and hidden
+ errors with typemaps are now fixed.
+- Initial Java support for languages using the UTL via GCJ, you can now use
+ Java libraries in your favorite script language using gcj + swig.
+- Tcl support for std::wstring.
+- PHP4 module update, many error fixes and actively maintained again.
+- Allegrocl support for C++, also enhanced C support.
+- Ruby support for bang methods.
+- Ruby support for user classes as native exceptions.
+- Perl improved dispatching in overloaded functions via the new cast and rank
+ mechanism.
+- Perl improved backward compatibility, 5.004 and later tested and working.
+- Python improved backward compatibility, 1.5.2 and later tested and working.
+- Python can use the same cast/rank mechanism via the -castmode option.
+- Python implicit conversion mechanism similar to C++, via the %implicitconv
+ directive (replaces and improves the implicit.i library).
+- Python threading support added.
+- Python STL support improved, iterators are supported and STL containers can
+ use now the native PyObject type.
+- Python many performance options and improvements, try the -O option to test
+ all of them. Python runtime benchmarks show up to 20 times better performance
+ compared to 1.3.27 and older versions.
+- Python support for 'multi-inheritance' on the python side.
+- Python simplified proxy classes, now swig doesn't need to generate the
+ additional 'ClassPtr' classes.
+- Python extended support for smart pointers.
+- Python better support for static member variables.
+- Python backward compatibility improved, many projects that used to work
+ only with swig-1.3.21 to swig-1.3.24 are working again with swig-1.3.28
+- Python test-suite is now 'valgrinded' before release, and swig also
+ reports memory leaks due to missing destructors.
+- Minor bug fixes and improvements to the Lua, Ruby, Java, C#, Python, Guile,
+ Chicken, Tcl and Perl modules.
+
+SWIG-1.3.27 summary:
+- Fix bug in anonymous typedef structures which was leading to strange behaviour
+
+SWIG-1.3.26 summary:
+- New language modules: Lua, CLISP and Common Lisp with UFFI.
+- Big overhaul to the PHP module.
+- Change to the way 'extern' is handled.
+- Minor bug fixes specific to C#, Java, Modula3, Ocaml, Allegro CL,
+ XML, Lisp s-expressions, Tcl, Ruby and Python modules.
+- Other minor improvements and bug fixes.
+
+SWIG-1.3.25 summary:
+- Improved runtime type system. Speed of module loading improved in
+ modules with lots of types. SWIG_RUNTIME_VERSION has been increased
+ from 1 to 2, but the API is exactly the same; only internal changes
+ were made.
+- The languages that use the runtime type system now support external
+ access to the runtime type system.
+- Various improvements with typemaps and template handling.
+- Fewer warnings in generated code.
+- Improved colour documentation.
+- Many C# module improvements (exception handling, prevention of early
+ garbage collection, C# attributes support added, more flexible type
+ marshalling/asymmetric types.)
+- Minor improvements and bug fixes specific to the C#, Java, TCL, Guile,
+ Chicken, MzScheme, Perl, Php, Python, Ruby and Ocaml modules).
+- Various other bug fixes and memory leak fixes.
+
+SWIG-1.3.24 summary:
+- Improved enum handling
+- More runtime library options
+- More bugs fixes for templates and template default arguments, directors
+ and other areas.
+- Better smart pointer support, including data members, static members
+ and %extend.
+
+SWIG-1.3.23 summary:
+- Improved support for callbacks
+- Python docstring support and better error handling
+- C++ default argument support for Java and C# added.
+- Improved c++ default argument support for the scripting languages plus
+ option to use original (compact) default arguments.
+- %feature and %ignore/%rename bug fixes and mods - they might need default
+ arguments specified to maintain compatible behaviour when using the new
+ default arguments wrapping.
+- Runtime library changes: Runtime code can now exist in more than one module
+ and so need not be compiled into just one module
+- Further improved support for templates and namespaces
+- Overloaded templated function support added
+- More powerful default typemaps (mixed default typemaps)
+- Some important %extend and director code bug fixes
+- Guile now defaults to using SCM API. The old interface can be obtained by
+ the -gh option.
+- Various minor improvements and bug fixes for C#, Chicken, Guile, Java,
+ MzScheme, Perl, Python and Ruby
+- Improved dependencies generation for constructing Makefiles.
+
+SWIG-1.3.22 summary:
+- Improved exception handling and translation of C errors or C++
+ exceptions into target language exceptions.
+- Improved enum support, mapping to built-in Java 1.5 enums and C#
+ enums or the typesafe enum pattern for these two languages.
+- Python - much better STL support and support for std::wstring,
+ wchar_t and FILE *.
+- Initial support for Modula3 and Allegro CL.
+- 64 bit TCL support.
+- Java and C#'s proxy classes are now nearly 100% generated from
+ typemaps and/or features for finer control on the generated code.
+- SWIG runtime library support deprecation.
+- Improved documentation. SWIG now additionally provides documentation
+ in the form of a single HTML page as well as a pdf document.
+- Enhanced C++ friend declaration support.
+- Better support for reference counted classes.
+- Various %fragment improvements.
+- RPM fixes.
+- Various minor improvements and bug fixes for C#, Chicken, Guile, Java,
+ MzScheme, Perl, Php, Python, Ruby and XML.
+
+
diff --git a/contrib/tools/swig/Source/CParse/cparse.h b/contrib/tools/swig/Source/CParse/cparse.h
new file mode 100644
index 00000000000..0084e5e843a
--- /dev/null
+++ b/contrib/tools/swig/Source/CParse/cparse.h
@@ -0,0 +1,83 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * cparse.h
+ *
+ * SWIG parser module.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_CPARSE_H
+#define SWIG_CPARSE_H
+
+#include "swig.h"
+#include "swigwarn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* cscanner.c */
+ extern String *cparse_file;
+ extern int cparse_line;
+ extern int cparse_cplusplus;
+ extern int cparse_cplusplusout;
+ extern int cparse_start_line;
+ extern String *cparse_unknown_directive;
+ extern int scan_doxygen_comments;
+
+ extern void Swig_cparse_cplusplus(int);
+ extern void Swig_cparse_cplusplusout(int);
+ extern void scanner_file(File *);
+ extern void scanner_next_token(int);
+ extern int skip_balanced(int startchar, int endchar);
+ extern String *get_raw_text_balanced(int startchar, int endchar);
+ extern void skip_decl(void);
+ extern void scanner_last_id(int);
+ extern void scanner_clear_rename(void);
+ extern void scanner_set_location(String *file, int line);
+ extern void scanner_set_main_input_file(String *file);
+ extern String *scanner_get_main_input_file(void);
+ extern void Swig_cparse_follow_locators(int);
+ extern void scanner_start_inline(String *, int);
+ extern String *scanner_ccode;
+ extern int yylex(void);
+
+/* parser.y */
+ extern SwigType *Swig_cparse_type(String *);
+ extern Node *Swig_cparse(File *);
+ extern Hash *Swig_cparse_features(void);
+ extern void SWIG_cparse_set_compact_default_args(int defargs);
+ extern int SWIG_cparse_template_reduce(int treduce);
+
+/* util.c */
+ extern void Swig_cparse_replace_descriptor(String *s);
+ extern SwigType *Swig_cparse_smartptr(Node *n);
+ extern void cparse_normalize_void(Node *);
+ extern Parm *Swig_cparse_parm(String *s);
+ extern ParmList *Swig_cparse_parms(String *s, Node *file_line_node);
+ extern Node *Swig_cparse_new_node(const_String_or_char_ptr tag);
+
+/* templ.c */
+ extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
+ extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope);
+ extern void Swig_cparse_debug_templates(int);
+ extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary, Node *templ);
+ extern ParmList *Swig_cparse_template_partialargs_expand(ParmList *partially_specialized_parms, Node *primary, ParmList *templateparms);
+
+#ifdef __cplusplus
+}
+#endif
+#define SWIG_WARN_NODE_BEGIN(Node) \
+ { \
+ String *wrnfilter = Node ? Getattr(Node,"feature:warnfilter") : 0; \
+ if (wrnfilter) Swig_warnfilter(wrnfilter,1)
+#define SWIG_WARN_NODE_END(Node) \
+ if (wrnfilter) Swig_warnfilter(wrnfilter,0); \
+ }
+
+#endif
diff --git a/contrib/tools/swig/Source/CParse/cscanner.c b/contrib/tools/swig/Source/CParse/cscanner.c
new file mode 100644
index 00000000000..5d0cee04475
--- /dev/null
+++ b/contrib/tools/swig/Source/CParse/cscanner.c
@@ -0,0 +1,1105 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * scanner.c
+ *
+ * SWIG tokenizer. This file is a wrapper around the generic C scanner
+ * found in Swig/scanner.c. Extra logic is added both to accommodate the
+ * bison-based grammar and certain peculiarities of C++ parsing (e.g.,
+ * operator overloading, typedef resolution, etc.). This code also splits
+ * C identifiers up into keywords and SWIG directives.
+ * ----------------------------------------------------------------------------- */
+
+#include "cparse.h"
+#include "parser.h"
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+/* Scanner object */
+static Scanner *scan = 0;
+
+/* Global string containing C code. Used by the parser to grab code blocks */
+String *scanner_ccode = 0;
+
+/* The main file being parsed */
+static String *main_input_file = 0;
+
+/* Error reporting/location information */
+int cparse_line = 1;
+String *cparse_file = 0;
+int cparse_start_line = 0;
+
+/* C++ mode */
+int cparse_cplusplus = 0;
+
+/* Generate C++ compatible code when wrapping C code */
+int cparse_cplusplusout = 0;
+
+/* To allow better error reporting */
+String *cparse_unknown_directive = 0;
+
+// Default-initialised instances of token types to avoid uninitialised fields.
+// The compiler will initialise all fields to zero or NULL for us.
+
+static const struct Define default_dtype;
+
+/* Private vars */
+static int scan_init = 0;
+static int num_brace = 0;
+static int last_id = 0;
+static int rename_active = 0;
+
+/* Doxygen comments scanning */
+int scan_doxygen_comments = 0;
+
+static int isStructuralDoxygen(String *s) {
+ static const char* const structuralTags[] = {
+ "addtogroup",
+ "callgraph",
+ "callergraph",
+ "category",
+ "def",
+ "defgroup",
+ "dir",
+ "example",
+ "file",
+ "headerfile",
+ "internal",
+ "mainpage",
+ "name",
+ "nosubgrouping",
+ "overload",
+ "package",
+ "page",
+ "protocol",
+ "relates",
+ "relatesalso",
+ "showinitializer",
+ "weakgroup",
+ };
+
+ unsigned n;
+ char *slashPointer = Strchr(s, '\\');
+ char *atPointer = Strchr(s,'@');
+ if (slashPointer == NULL && atPointer == NULL)
+ return 0;
+ else if(slashPointer == NULL)
+ slashPointer = atPointer;
+
+ slashPointer++; /* skip backslash or at sign */
+
+ for (n = 0; n < sizeof(structuralTags)/sizeof(structuralTags[0]); n++) {
+ const size_t len = strlen(structuralTags[n]);
+ if (strncmp(slashPointer, structuralTags[n], len) == 0) {
+ /* Take care to avoid false positives with prefixes of other tags. */
+ if (slashPointer[len] == '\0' || isspace((int)slashPointer[len]))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_cplusplus()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_cparse_cplusplus(int v) {
+ cparse_cplusplus = v;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_cplusplusout()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_cparse_cplusplusout(int v) {
+ cparse_cplusplusout = v;
+}
+
+/* ----------------------------------------------------------------------------
+ * scanner_init()
+ *
+ * Initialize buffers
+ * ------------------------------------------------------------------------- */
+
+static void scanner_init(void) {
+ scan = NewScanner();
+ Scanner_idstart(scan,"%");
+ scan_init = 1;
+ scanner_ccode = NewStringEmpty();
+}
+
+/* ----------------------------------------------------------------------------
+ * scanner_file(DOHFile *f)
+ *
+ * Start reading from new file
+ * ------------------------------------------------------------------------- */
+void scanner_file(DOHFile * f) {
+ if (!scan_init) scanner_init();
+ Scanner_clear(scan);
+ Scanner_push(scan,f);
+}
+
+/* ----------------------------------------------------------------------------
+ * scanner_start_inline(String *text, int line)
+ *
+ * Take a chunk of text and recursively feed it back into the scanner. Used
+ * by the %inline directive.
+ * ------------------------------------------------------------------------- */
+
+void scanner_start_inline(String *text, int line) {
+ String *stext = Copy(text);
+
+ Seek(stext,0,SEEK_SET);
+ Setfile(stext,cparse_file);
+ Setline(stext,line);
+ Scanner_push(scan,stext);
+ Delete(stext);
+}
+
+/* -----------------------------------------------------------------------------
+ * skip_balanced()
+ *
+ * Skips a piece of code enclosed in begin/end symbols such as '{...}' or
+ * (...). Ignores symbols inside comments or strings.
+ *
+ * Returns 0 if successfully skipped, -1 if EOF found first.
+ * ----------------------------------------------------------------------------- */
+
+int skip_balanced(int startchar, int endchar) {
+ int start_line = Scanner_line(scan);
+ Clear(scanner_ccode);
+
+ if (Scanner_skip_balanced(scan,startchar,endchar) < 0) {
+ Swig_error(cparse_file, start_line, "Missing '%c'. Reached end of input.\n", endchar);
+ return -1;
+ }
+
+ cparse_line = Scanner_line(scan);
+ cparse_file = Scanner_file(scan);
+
+ Append(scanner_ccode, Scanner_text(scan));
+ if (endchar == '}')
+ num_brace--;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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)
+ *
+ * This tries to skip over an entire declaration. For example
+ *
+ * friend ostream& operator<<(ostream&, const char *s);
+ *
+ * or
+ * friend ostream& operator<<(ostream&, const char *s) { }
+ *
+ * ------------------------------------------------------------------------- */
+
+void skip_decl(void) {
+ int tok;
+ int done = 0;
+ int start_line = Scanner_line(scan);
+
+ while (!done) {
+ tok = Scanner_token(scan);
+ if (tok == 0) {
+ if (!Swig_error_count()) {
+ Swig_error(cparse_file, start_line, "Missing semicolon (';'). Reached end of input.\n");
+ }
+ return;
+ }
+ if (tok == SWIG_TOKEN_LBRACE) {
+ if (Scanner_skip_balanced(scan,'{','}') < 0) {
+ Swig_error(cparse_file, start_line, "Missing closing brace ('}'). Reached end of input.\n");
+ }
+ break;
+ }
+ if (tok == SWIG_TOKEN_SEMI) {
+ done = 1;
+ }
+ }
+ cparse_file = Scanner_file(scan);
+ cparse_line = Scanner_line(scan);
+}
+
+/* ----------------------------------------------------------------------------
+ * int yylook()
+ *
+ * Lexical scanner.
+ * ------------------------------------------------------------------------- */
+
+static int yylook(void) {
+
+ int tok = 0;
+
+ while (1) {
+ if ((tok = Scanner_token(scan)) == 0)
+ return 0;
+ if (tok == SWIG_TOKEN_ERROR)
+ return 0;
+ cparse_start_line = Scanner_start_line(scan);
+ cparse_line = Scanner_line(scan);
+ cparse_file = Scanner_file(scan);
+
+ switch(tok) {
+ case SWIG_TOKEN_ID:
+ return ID;
+ case SWIG_TOKEN_LPAREN:
+ return LPAREN;
+ case SWIG_TOKEN_RPAREN:
+ return RPAREN;
+ case SWIG_TOKEN_SEMI:
+ return SEMI;
+ case SWIG_TOKEN_COMMA:
+ return COMMA;
+ case SWIG_TOKEN_STAR:
+ return STAR;
+ case SWIG_TOKEN_RBRACE:
+ num_brace--;
+ if (num_brace < 0) {
+ Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous closing brace ('}')\n");
+ num_brace = 0;
+ } else {
+ return RBRACE;
+ }
+ break;
+ case SWIG_TOKEN_LBRACE:
+ num_brace++;
+ return LBRACE;
+ case SWIG_TOKEN_EQUAL:
+ return EQUAL;
+ case SWIG_TOKEN_EQUALTO:
+ return EQUALTO;
+ case SWIG_TOKEN_PLUS:
+ return PLUS;
+ case SWIG_TOKEN_MINUS:
+ return MINUS;
+ case SWIG_TOKEN_SLASH:
+ return SLASH;
+ case SWIG_TOKEN_AND:
+ return AND;
+ case SWIG_TOKEN_LAND:
+ return LAND;
+ case SWIG_TOKEN_OR:
+ return OR;
+ case SWIG_TOKEN_LOR:
+ return LOR;
+ case SWIG_TOKEN_XOR:
+ return XOR;
+ case SWIG_TOKEN_NOT:
+ return NOT;
+ case SWIG_TOKEN_LNOT:
+ return LNOT;
+ case SWIG_TOKEN_NOTEQUAL:
+ return NOTEQUALTO;
+ case SWIG_TOKEN_LBRACKET:
+ return LBRACKET;
+ case SWIG_TOKEN_RBRACKET:
+ return RBRACKET;
+ case SWIG_TOKEN_QUESTION:
+ return QUESTIONMARK;
+ case SWIG_TOKEN_LESSTHAN:
+ return LESSTHAN;
+ case SWIG_TOKEN_LTEQUAL:
+ return LESSTHANOREQUALTO;
+ case SWIG_TOKEN_LSHIFT:
+ return LSHIFT;
+ case SWIG_TOKEN_GREATERTHAN:
+ return GREATERTHAN;
+ case SWIG_TOKEN_GTEQUAL:
+ return GREATERTHANOREQUALTO;
+ case SWIG_TOKEN_RSHIFT:
+ return RSHIFT;
+ case SWIG_TOKEN_ARROW:
+ return ARROW;
+ case SWIG_TOKEN_PERIOD:
+ return PERIOD;
+ case SWIG_TOKEN_PERCENT:
+ return MODULO;
+ case SWIG_TOKEN_COLON:
+ return COLON;
+ case SWIG_TOKEN_DCOLONSTAR:
+ return DSTAR;
+ case SWIG_TOKEN_LTEQUALGT:
+ return LESSEQUALGREATER;
+
+ case SWIG_TOKEN_DCOLON:
+ {
+ int nexttok = Scanner_token(scan);
+ if (nexttok == SWIG_TOKEN_STAR) {
+ return DSTAR;
+ } else if (nexttok == SWIG_TOKEN_NOT) {
+ return DCNOT;
+ } else {
+ Scanner_pushtoken(scan,nexttok,Scanner_text(scan));
+ if (!last_id) {
+ scanner_next_token(DCOLON);
+ return NONID;
+ } else {
+ return DCOLON;
+ }
+ }
+ }
+ break;
+
+ case SWIG_TOKEN_ELLIPSIS:
+ return ELLIPSIS;
+
+ case SWIG_TOKEN_LLBRACKET:
+ do {
+ tok = Scanner_token(scan);
+ } while ((tok != SWIG_TOKEN_RRBRACKET) && (tok > 0));
+ if (tok <= 0) {
+ Swig_error(cparse_file, cparse_line, "Unbalanced double brackets, missing closing (']]'). Reached end of input.\n");
+ }
+ break;
+
+ case SWIG_TOKEN_RRBRACKET:
+ /* Turn an unmatched ]] back into two ] - e.g. `a[a[0]]` */
+ scanner_next_token(RBRACKET);
+ return RBRACKET;
+
+ /* Look for multi-character sequences */
+
+ case SWIG_TOKEN_RSTRING:
+ yylval.type = NewString(Scanner_text(scan));
+ return TYPE_RAW;
+
+ case SWIG_TOKEN_STRING:
+ yylval.str = NewString(Scanner_text(scan));
+ return STRING;
+
+ case SWIG_TOKEN_WSTRING:
+ yylval.str = NewString(Scanner_text(scan));
+ return WSTRING;
+
+ case SWIG_TOKEN_CHAR:
+ yylval.str = NewString(Scanner_text(scan));
+ if (Len(yylval.str) == 0) {
+ Swig_error(cparse_file, cparse_line, "Empty character constant\n");
+ }
+ return CHARCONST;
+
+ case SWIG_TOKEN_WCHAR:
+ yylval.str = NewString(Scanner_text(scan));
+ if (Len(yylval.str) == 0) {
+ Swig_error(cparse_file, cparse_line, "Empty character constant\n");
+ }
+ return WCHARCONST;
+
+ /* Numbers */
+
+ case SWIG_TOKEN_INT:
+ return NUM_INT;
+
+ case SWIG_TOKEN_UINT:
+ return NUM_UNSIGNED;
+
+ case SWIG_TOKEN_LONG:
+ return NUM_LONG;
+
+ case SWIG_TOKEN_ULONG:
+ return NUM_ULONG;
+
+ case SWIG_TOKEN_LONGLONG:
+ return NUM_LONGLONG;
+
+ case SWIG_TOKEN_ULONGLONG:
+ return NUM_ULONGLONG;
+
+ case SWIG_TOKEN_DOUBLE:
+ return NUM_DOUBLE;
+
+ case SWIG_TOKEN_FLOAT:
+ return NUM_FLOAT;
+
+ case SWIG_TOKEN_LONGDOUBLE:
+ return NUM_LONGDOUBLE;
+
+ case SWIG_TOKEN_BOOL:
+ return NUM_BOOL;
+
+ case SWIG_TOKEN_POUND:
+ Scanner_skip_line(scan);
+ yylval.id = Swig_copy_string(Char(Scanner_text(scan)));
+ return POUND;
+
+ case SWIG_TOKEN_CODEBLOCK:
+ yylval.str = NewString(Scanner_text(scan));
+ return HBLOCK;
+
+ case SWIG_TOKEN_COMMENT:
+ {
+ typedef enum {
+ DOX_COMMENT_PRE = -1,
+ DOX_COMMENT_NONE,
+ DOX_COMMENT_POST
+ } comment_kind_t;
+ comment_kind_t existing_comment = DOX_COMMENT_NONE;
+
+ /* Concatenate or skip all consecutive comments at once. */
+ do {
+ String *cmt = Scanner_text(scan);
+ String *cmt_modified = 0;
+ char *loc = Char(cmt);
+ if ((strncmp(loc, "/*@SWIG", 7) == 0) && (loc[Len(cmt)-3] == '@')) {
+ Scanner_locator(scan, cmt);
+ }
+ if (scan_doxygen_comments) { /* else just skip this node, to avoid crashes in parser module*/
+
+ int slashStyle = 0; /* Flag for "///" style doxygen comments */
+ if (strncmp(loc, "///", 3) == 0) {
+ slashStyle = 1;
+ if (Len(cmt) == 3) {
+ /* Modify to make length=4 to ensure that the empty comment does
+ get processed to preserve the newlines in the original comments. */
+ cmt_modified = NewStringf("%s ", cmt);
+ cmt = cmt_modified;
+ loc = Char(cmt);
+ }
+ }
+
+ /* Check for all possible Doxygen comment start markers while ignoring
+ comments starting with a row of asterisks or slashes just as
+ Doxygen itself does. Also skip empty comment (slash-star-star-slash),
+ which causes a crash due to begin > end. */
+ if (Len(cmt) > 3 && loc[0] == '/' &&
+ ((loc[1] == '/' && ((loc[2] == '/' && loc[3] != '/') || loc[2] == '!')) ||
+ (loc[1] == '*' && ((loc[2] == '*' && loc[3] != '*' && loc[3] != '/') || loc[2] == '!')))) {
+ comment_kind_t this_comment = loc[3] == '<' ? DOX_COMMENT_POST : DOX_COMMENT_PRE;
+ if (existing_comment != DOX_COMMENT_NONE && this_comment != existing_comment) {
+ /* We can't concatenate together Doxygen pre- and post-comments. */
+ break;
+ }
+
+ if (this_comment == DOX_COMMENT_POST || !isStructuralDoxygen(loc)) {
+ String *str;
+
+ int begin = this_comment == DOX_COMMENT_POST ? 4 : 3;
+ int end = Len(cmt);
+ if (loc[end - 1] == '/' && loc[end - 2] == '*') {
+ end -= 2;
+ }
+
+ str = NewStringWithSize(loc + begin, end - begin);
+
+ if (existing_comment == DOX_COMMENT_NONE) {
+ yylval.str = str;
+ Setline(yylval.str, Scanner_start_line(scan));
+ Setfile(yylval.str, Scanner_file(scan));
+ } else {
+ if (slashStyle) {
+ /* Add a newline to the end of each doxygen "///" comment,
+ since they are processed individually, unlike the
+ slash-star style, which gets processed as a block with
+ newlines included. */
+ Append(yylval.str, "\n");
+ }
+ Append(yylval.str, str);
+ }
+
+ existing_comment = this_comment;
+ }
+ }
+ }
+ do {
+ tok = Scanner_token(scan);
+ } while (tok == SWIG_TOKEN_ENDLINE);
+ Delete(cmt_modified);
+ } while (tok == SWIG_TOKEN_COMMENT);
+
+ Scanner_pushtoken(scan, tok, Scanner_text(scan));
+
+ switch (existing_comment) {
+ case DOX_COMMENT_PRE:
+ return DOXYGENSTRING;
+ case DOX_COMMENT_NONE:
+ break;
+ case DOX_COMMENT_POST:
+ return DOXYGENPOSTSTRING;
+ }
+ }
+ break;
+ case SWIG_TOKEN_ENDLINE:
+ break;
+ case SWIG_TOKEN_BACKSLASH:
+ break;
+ default:
+ Swig_error(cparse_file, cparse_line, "Unexpected token '%s'.\n", Scanner_text(scan));
+ Exit(EXIT_FAILURE);
+ }
+ }
+}
+
+void scanner_set_location(String *file, int line) {
+ Scanner_set_location(scan,file,line-1);
+}
+
+void scanner_last_id(int x) {
+ last_id = x;
+}
+
+void scanner_clear_rename(void) {
+ rename_active = 0;
+}
+
+/* Used to push a fictitious token into the scanner */
+static int next_token = 0;
+void scanner_next_token(int tok) {
+ next_token = tok;
+}
+
+void scanner_set_main_input_file(String *file) {
+ main_input_file = file;
+}
+
+String *scanner_get_main_input_file(void) {
+ return main_input_file;
+}
+
+/* ----------------------------------------------------------------------------
+ * int yylex()
+ *
+ * Gets the lexene and returns tokens.
+ * ------------------------------------------------------------------------- */
+
+int yylex(void) {
+
+ int l;
+ char *yytext;
+
+ if (!scan_init) {
+ scanner_init();
+ }
+
+ Delete(cparse_unknown_directive);
+ cparse_unknown_directive = NULL;
+
+ if (next_token) {
+ l = next_token;
+ next_token = 0;
+ return l;
+ }
+
+ l = yylook();
+
+ /* Swig_diagnostic(cparse_file, cparse_line, ":::%d: '%s'\n", l, Scanner_text(scan)); */
+
+ if (l == NONID) {
+ last_id = 1;
+ } else {
+ last_id = 0;
+ }
+
+ /* We got some sort of non-white space object. We set the start_line
+ variable unless it has already been set */
+
+ if (!cparse_start_line) {
+ cparse_start_line = cparse_line;
+ }
+
+ /* Copy the lexene */
+
+ switch (l) {
+
+ case NUM_INT:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_INT;
+ goto num_common;
+ case NUM_DOUBLE:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_DOUBLE;
+ goto num_common;
+ case NUM_FLOAT:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_FLOAT;
+ goto num_common;
+ case NUM_LONGDOUBLE:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_LONGDOUBLE;
+ goto num_common;
+ case NUM_ULONG:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_ULONG;
+ goto num_common;
+ case NUM_LONG:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_LONG;
+ goto num_common;
+ case NUM_UNSIGNED:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_UINT;
+ goto num_common;
+ case NUM_LONGLONG:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_LONGLONG;
+ goto num_common;
+ case NUM_ULONGLONG:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_ULONGLONG;
+ goto num_common;
+num_common: {
+ yylval.dtype.val = NewString(Scanner_text(scan));
+ const char *c = Char(yylval.dtype.val);
+ if (c[0] == '0') {
+ // Convert to base 10 using strtoull().
+ unsigned long long value;
+ char *e;
+ errno = 0;
+ if (c[1] == 'b' || c[1] == 'B') {
+ /* strtoull() doesn't handle binary literal prefixes so skip the prefix
+ * and specify base 2 explicitly. */
+ value = strtoull(c + 2, &e, 2);
+ } else {
+ value = strtoull(c, &e, 0);
+ }
+ if (errno != ERANGE) {
+ while (*e && strchr("ULul", *e)) ++e;
+ }
+ if (errno != ERANGE && *e == '\0') {
+ yylval.dtype.numval = NewStringf("%llu", value);
+ } else {
+ // Our unsigned long long isn't wide enough or this isn't an integer.
+ }
+ } else {
+ const char *e = c;
+ while (isdigit((unsigned char)*e)) ++e;
+ int len = e - c;
+ while (*e && strchr("ULul", *e)) ++e;
+ if (*e == '\0') {
+ yylval.dtype.numval = NewStringWithSize(c, len);
+ }
+ }
+ return (l);
+ }
+ case NUM_BOOL:
+ yylval.dtype = default_dtype;
+ yylval.dtype.type = T_BOOL;
+ yylval.dtype.val = NewString(Scanner_text(scan));
+ yylval.dtype.numval = NewString(Equal(yylval.dtype.val, "false") ? "0" : "1");
+ return (l);
+
+ case ID:
+ yytext = Char(Scanner_text(scan));
+ if (yytext[0] != '%') {
+ /* Look for keywords now */
+
+ if (strcmp(yytext, "int") == 0) {
+ yylval.type = NewSwigType(T_INT);
+ return (TYPE_INT);
+ }
+ if (strcmp(yytext, "double") == 0) {
+ yylval.type = NewSwigType(T_DOUBLE);
+ return (TYPE_DOUBLE);
+ }
+ if (strcmp(yytext, "void") == 0) {
+ yylval.type = NewSwigType(T_VOID);
+ return (TYPE_VOID);
+ }
+ if (strcmp(yytext, "char") == 0) {
+ yylval.type = NewSwigType(T_CHAR);
+ return (TYPE_CHAR);
+ }
+ if (strcmp(yytext, "wchar_t") == 0) {
+ yylval.type = NewSwigType(T_WCHAR);
+ return (TYPE_WCHAR);
+ }
+ if (strcmp(yytext, "short") == 0) {
+ yylval.type = NewSwigType(T_SHORT);
+ return (TYPE_SHORT);
+ }
+ if (strcmp(yytext, "long") == 0) {
+ yylval.type = NewSwigType(T_LONG);
+ return (TYPE_LONG);
+ }
+ if (strcmp(yytext, "float") == 0) {
+ yylval.type = NewSwigType(T_FLOAT);
+ return (TYPE_FLOAT);
+ }
+ if (strcmp(yytext, "signed") == 0) {
+ yylval.type = NewSwigType(T_INT);
+ return (TYPE_SIGNED);
+ }
+ if (strcmp(yytext, "unsigned") == 0) {
+ yylval.type = NewSwigType(T_UINT);
+ return (TYPE_UNSIGNED);
+ }
+ if (strcmp(yytext, "bool") == 0) {
+ yylval.type = NewSwigType(T_BOOL);
+ return (TYPE_BOOL);
+ }
+
+ /* Non ISO (Windows) C extensions */
+ if (strcmp(yytext, "__int8") == 0) {
+ yylval.type = NewString(yytext);
+ return (TYPE_NON_ISO_INT8);
+ }
+ if (strcmp(yytext, "__int16") == 0) {
+ yylval.type = NewString(yytext);
+ return (TYPE_NON_ISO_INT16);
+ }
+ if (strcmp(yytext, "__int32") == 0) {
+ yylval.type = NewString(yytext);
+ return (TYPE_NON_ISO_INT32);
+ }
+ if (strcmp(yytext, "__int64") == 0) {
+ yylval.type = NewString(yytext);
+ return (TYPE_NON_ISO_INT64);
+ }
+
+ /* C++ keywords */
+ if (cparse_cplusplus) {
+ if (strcmp(yytext, "class") == 0)
+ return (CLASS);
+ if (strcmp(yytext, "private") == 0)
+ return (PRIVATE);
+ if (strcmp(yytext, "public") == 0)
+ return (PUBLIC);
+ if (strcmp(yytext, "protected") == 0)
+ return (PROTECTED);
+ if (strcmp(yytext, "friend") == 0)
+ return (FRIEND);
+ if (strcmp(yytext, "constexpr") == 0)
+ return (CONSTEXPR);
+ if (strcmp(yytext, "thread_local") == 0)
+ return (THREAD_LOCAL);
+ if (strcmp(yytext, "decltype") == 0)
+ return (DECLTYPE);
+ if (strcmp(yytext, "virtual") == 0)
+ return (VIRTUAL);
+ if (strcmp(yytext, "static_assert") == 0)
+ return (STATIC_ASSERT);
+ if (strcmp(yytext, "operator") == 0) {
+ int nexttok;
+ String *s = NewString("operator ");
+
+ /* If we have an operator, we have to collect the operator symbol and attach it to
+ the operator identifier. To do this, we need to scan ahead by several tokens.
+ Cases include:
+
+ (1) If the next token is an operator as determined by Scanner_isoperator(),
+ it means that the operator applies to one of the standard C++ mathematical,
+ assignment, or logical operator symbols (e.g., '+','<=','==','&', etc.)
+ In this case, we merely append the symbol text to the operator string above.
+
+ (2) If the next token is (, we look for ). This is operator ().
+ (3) If the next token is [, we look for ]. This is operator [].
+ (4) If the next token is an identifier. The operator is possibly a conversion operator.
+ (a) Must check for special case new[] and delete[]
+
+ Error handling is somewhat tricky here. We'll try to back out gracefully if we can.
+
+ */
+
+ do {
+ nexttok = Scanner_token(scan);
+ } while (nexttok == SWIG_TOKEN_ENDLINE || nexttok == SWIG_TOKEN_COMMENT);
+
+ if (Scanner_isoperator(nexttok)) {
+ /* One of the standard C/C++ symbolic operators */
+ Append(s,Scanner_text(scan));
+ yylval.str = s;
+ return OPERATOR;
+ } else if (nexttok == SWIG_TOKEN_LPAREN) {
+ /* Function call operator. The next token MUST be a RPAREN */
+ nexttok = Scanner_token(scan);
+ if (nexttok != SWIG_TOKEN_RPAREN) {
+ Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n");
+ } else {
+ Append(s,"()");
+ yylval.str = s;
+ return OPERATOR;
+ }
+ } else if (nexttok == SWIG_TOKEN_LBRACKET) {
+ /* Array access operator. The next token MUST be a RBRACKET */
+ nexttok = Scanner_token(scan);
+ if (nexttok != SWIG_TOKEN_RBRACKET) {
+ Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n");
+ } else {
+ Append(s,"[]");
+ yylval.str = s;
+ return OPERATOR;
+ }
+ } else if (nexttok == SWIG_TOKEN_STRING) {
+ /* Operator "" or user-defined string literal ""_suffix */
+ Append(s,"\"\"");
+ yylval.str = s;
+ return OPERATOR;
+ } else if (nexttok == SWIG_TOKEN_ID) {
+ /* We have an identifier. It could be "new" or "delete",
+ * potentially followed by "[]", or it could be a conversion
+ * operator (it can't be "and_eq" or similar as those are returned
+ * as SWIG_TOKEN_ANDEQUAL, etc by Scanner_token()). To deal with
+ * this we read tokens until we encounter a suitable terminating
+ * token. Some care is needed for formatting. */
+ int needspace = 1;
+ int termtoken = 0;
+ const char *termvalue = 0;
+
+ Append(s,Scanner_text(scan));
+ while (1) {
+
+ nexttok = Scanner_token(scan);
+ if (nexttok <= 0) {
+ Swig_error(Scanner_file(scan),Scanner_line(scan),"Syntax error. Bad operator name.\n");
+ }
+ if (nexttok == SWIG_TOKEN_LPAREN) {
+ termtoken = SWIG_TOKEN_LPAREN;
+ termvalue = "(";
+ break;
+ } else if (nexttok == SWIG_TOKEN_CODEBLOCK) {
+ termtoken = SWIG_TOKEN_CODEBLOCK;
+ termvalue = Char(Scanner_text(scan));
+ break;
+ } else if (nexttok == SWIG_TOKEN_LBRACE) {
+ termtoken = SWIG_TOKEN_LBRACE;
+ termvalue = "{";
+ break;
+ } else if (nexttok == SWIG_TOKEN_SEMI) {
+ termtoken = SWIG_TOKEN_SEMI;
+ termvalue = ";";
+ break;
+ } else if (nexttok == SWIG_TOKEN_STRING) {
+ termtoken = SWIG_TOKEN_STRING;
+ termvalue = Swig_copy_string(Char(Scanner_text(scan)));
+ break;
+ } else if (nexttok == SWIG_TOKEN_ID) {
+ if (needspace) {
+ Append(s," ");
+ }
+ Append(s,Scanner_text(scan));
+ } else if (nexttok == SWIG_TOKEN_ENDLINE) {
+ } else if (nexttok == SWIG_TOKEN_COMMENT) {
+ } else {
+ Append(s,Scanner_text(scan));
+ needspace = 0;
+ }
+ }
+ yylval.str = s;
+ if (!rename_active) {
+ String *cs;
+ char *t = Char(s) + 9;
+ if (!((strcmp(t, "new") == 0)
+ || (strcmp(t, "delete") == 0)
+ || (strcmp(t, "new[]") == 0)
+ || (strcmp(t, "delete[]") == 0)
+ )) {
+ /* retract(strlen(t)); */
+
+ /* The operator is a conversion operator. In order to deal with this, we need to feed the
+ type information back into the parser. For now this is a hack. Needs to be cleaned up later. */
+ cs = NewString(t);
+ if (termtoken) Append(cs,termvalue);
+ Seek(cs,0,SEEK_SET);
+ Setline(cs,cparse_line);
+ Setfile(cs,cparse_file);
+ Scanner_push(scan,cs);
+ Delete(cs);
+ return CONVERSIONOPERATOR;
+ }
+ }
+ if (termtoken)
+ Scanner_pushtoken(scan, termtoken, termvalue);
+ return (OPERATOR);
+ }
+ }
+ if (strcmp(yytext, "throw") == 0)
+ return (THROW);
+ if (strcmp(yytext, "noexcept") == 0)
+ return (NOEXCEPT);
+ if (strcmp(yytext, "try") == 0)
+ return (yylex());
+ if (strcmp(yytext, "catch") == 0)
+ return (CATCH);
+ if (strcmp(yytext, "inline") == 0)
+ return (yylex());
+ if (strcmp(yytext, "mutable") == 0)
+ return (yylex());
+ if (strcmp(yytext, "explicit") == 0)
+ return (EXPLICIT);
+ if (strcmp(yytext, "auto") == 0)
+ return (AUTO);
+ if (strcmp(yytext, "export") == 0)
+ return (yylex());
+ if (strcmp(yytext, "typename") == 0)
+ return (TYPENAME);
+ if (strcmp(yytext, "template") == 0) {
+ yylval.intvalue = cparse_line;
+ return (TEMPLATE);
+ }
+ if (strcmp(yytext, "delete") == 0)
+ return (DELETE_KW);
+ if (strcmp(yytext, "default") == 0)
+ return (DEFAULT);
+ if (strcmp(yytext, "using") == 0)
+ return (USING);
+ if (strcmp(yytext, "namespace") == 0)
+ return (NAMESPACE);
+ if (strcmp(yytext, "alignof") == 0)
+ return (ALIGNOF);
+ if (strcmp(yytext, "override") == 0) {
+ last_id = 1;
+ return (OVERRIDE);
+ }
+ if (strcmp(yytext, "final") == 0) {
+ last_id = 1;
+ return (FINAL);
+ }
+ } else {
+ if (strcmp(yytext, "class") == 0) {
+ Swig_warning(WARN_PARSE_CLASS_KEYWORD, cparse_file, cparse_line, "class keyword used, but not in C++ mode.\n");
+ }
+ if (strcmp(yytext, "_Bool") == 0) {
+ /* C99 boolean type. */
+ yylval.type = NewSwigType(T_BOOL);
+ return (TYPE_BOOL);
+ }
+ if (strcmp(yytext, "_Complex") == 0) {
+ yylval.type = NewSwigType(T_COMPLEX);
+ return (TYPE_COMPLEX);
+ }
+ if (strcmp(yytext, "restrict") == 0)
+ return (yylex());
+ }
+
+ /* Misc keywords */
+
+ if (strcmp(yytext, "extern") == 0)
+ return (EXTERN);
+ if (strcmp(yytext, "const") == 0)
+ return (CONST_QUAL);
+ if (strcmp(yytext, "static") == 0)
+ return (STATIC);
+ if (strcmp(yytext, "struct") == 0)
+ return (STRUCT);
+ if (strcmp(yytext, "union") == 0)
+ return (UNION);
+ if (strcmp(yytext, "enum") == 0)
+ return (ENUM);
+ if (strcmp(yytext, "sizeof") == 0)
+ return (SIZEOF);
+
+ if (strcmp(yytext, "typedef") == 0) {
+ return (TYPEDEF);
+ }
+
+ /* Ignored keywords */
+
+ if (strcmp(yytext, "volatile") == 0)
+ return (VOLATILE);
+ if (strcmp(yytext, "register") == 0)
+ return (REGISTER);
+ if (strcmp(yytext, "inline") == 0)
+ return (yylex());
+
+ } else {
+ /* SWIG directives */
+ String *stext = 0;
+ if (strcmp(yytext, "%module") == 0)
+ return (MODULE);
+ if (strcmp(yytext, "%insert") == 0)
+ return (INSERT);
+ if (strcmp(yytext, "%rename") == 0) {
+ rename_active = 1;
+ return (RENAME);
+ }
+ if (strcmp(yytext, "%namewarn") == 0) {
+ rename_active = 1;
+ return (NAMEWARN);
+ }
+ if (strcmp(yytext, "%includefile") == 0)
+ return (INCLUDE);
+ if (strcmp(yytext, "%beginfile") == 0)
+ return (BEGINFILE);
+ if (strcmp(yytext, "%endoffile") == 0)
+ return (ENDOFFILE);
+ if (strcmp(yytext, "%constant") == 0)
+ return (CONSTANT);
+ if (strcmp(yytext, "%typedef") == 0) {
+ return (TYPEDEF);
+ }
+ if (strcmp(yytext, "%native") == 0)
+ return (NATIVE);
+ if (strcmp(yytext, "%pragma") == 0)
+ return (PRAGMA);
+ if (strcmp(yytext, "%extend") == 0)
+ return (EXTEND);
+ if (strcmp(yytext, "%fragment") == 0)
+ return (FRAGMENT);
+ if (strcmp(yytext, "%inline") == 0)
+ return (INLINE);
+ if (strcmp(yytext, "%typemap") == 0)
+ return (TYPEMAP);
+ if (strcmp(yytext, "%feature") == 0) {
+ /* The rename_active indicates we don't need the information of the
+ * following function's return type. This applied for %rename, so do
+ * %feature.
+ */
+ rename_active = 1;
+ return (FEATURE);
+ }
+ if (strcmp(yytext, "%importfile") == 0)
+ return (IMPORT);
+ if (strcmp(yytext, "%echo") == 0)
+ return (ECHO);
+ if (strcmp(yytext, "%apply") == 0)
+ return (APPLY);
+ if (strcmp(yytext, "%clear") == 0)
+ return (CLEAR);
+ if (strcmp(yytext, "%types") == 0)
+ return (TYPES);
+ if (strcmp(yytext, "%parms") == 0)
+ return (PARMS);
+ if (strcmp(yytext, "%varargs") == 0)
+ return (VARARGS);
+ if (strcmp(yytext, "%template") == 0) {
+ return (SWIGTEMPLATE);
+ }
+ if (strcmp(yytext, "%warn") == 0)
+ return (WARN);
+
+ /* Note down the apparently unknown directive for error reporting - if
+ * we end up reporting a generic syntax error we'll instead report an
+ * error for this as an unknown directive. Then we treat it as MODULO
+ * (`%`) followed by an identifier and if that parses OK then
+ * `cparse_unknown_directive` doesn't get used.
+ *
+ * This allows `a%b` to be handled in expressions without a space after
+ * the operator.
+ */
+ cparse_unknown_directive = NewString(yytext);
+ stext = NewString(yytext + 1);
+ Seek(stext,0,SEEK_SET);
+ Setfile(stext,cparse_file);
+ Setline(stext,cparse_line);
+ Scanner_push(scan,stext);
+ Delete(stext);
+ return (MODULO);
+ }
+
+ yylval.id = Swig_copy_string(yytext);
+ last_id = 1;
+ return (ID);
+ case POUND:
+ return yylex();
+ default:
+ return (l);
+ }
+}
diff --git a/contrib/tools/swig/Source/CParse/parser.y b/contrib/tools/swig/Source/CParse/parser.y
new file mode 100644
index 00000000000..76e2339143c
--- /dev/null
+++ b/contrib/tools/swig/Source/CParse/parser.y
@@ -0,0 +1,7858 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * parser.y
+ *
+ * Bison parser for SWIG. The grammar is a somewhat broken subset of C/C++.
+ * This file is a bit of a mess and probably needs to be rewritten at
+ * some point. Beware.
+ * ----------------------------------------------------------------------------- */
+
+%require "3.5"
+
+/* There are a small number of known shift-reduce conflicts in this file, fail
+ compilation if any more are introduced.
+
+ Please don't increase the number of the conflicts if at all possible. And if
+ you really have no choice but to do it, make sure you clearly document each
+ new conflict in this file.
+ */
+%expect 7
+
+/* Make the internal token numbers the same as the external token numbers
+ * which saves Bison generating a lookup table to map between them, giving
+ * a smaller and faster generated parser.
+ */
+%define api.token.raw
+
+%{
+/* doh.h uses #pragma GCC poison with GCC to prevent direct calls to certain
+ * standard C library functions being introduced, but those cause errors due
+ * to checks like `#if defined YYMALLOC || defined malloc` in the bison
+ * template code. We can't easily arrange to include headers after that
+ * template code, so instead we disable the problematic poisoning for this
+ * file.
+ */
+#define DOH_NO_POISON_MALLOC_FREE
+
+#include "swig.h"
+#include "cparse.h"
+#include "preprocessor.h"
+#include <ctype.h>
+
+#define YYMALLOC Malloc
+#define YYFREE Free
+
+/* -----------------------------------------------------------------------------
+ * Externals
+ * ----------------------------------------------------------------------------- */
+
+int yyparse(void);
+
+/* NEW Variables */
+
+static void *top = 0; /* Top of the generated parse tree */
+static int unnamed = 0; /* Unnamed datatype counter */
+static Hash *classes = 0; /* Hash table of classes */
+static Hash *classes_typedefs = 0; /* Hash table of typedef classes: typedef struct X {...} Y; */
+static Symtab *prev_symtab = 0;
+static Node *current_class = 0;
+String *ModuleName = 0;
+static Node *module_node = 0;
+static String *Classprefix = 0;
+static String *Namespaceprefix = 0;
+static int inclass = 0;
+static Node *currentOuterClass = 0; /* for nested classes */
+static String *last_cpptype = 0;
+static int inherit_list = 0;
+static Parm *template_parameters = 0;
+static int parsing_template_declaration = 0;
+static int extendmode = 0;
+static int compact_default_args = 0;
+static int template_reduce = 0;
+static int cparse_externc = 0;
+int ignore_nested_classes = 0;
+int kwargs_supported = 0;
+
+/* -----------------------------------------------------------------------------
+ * Doxygen Comment Globals
+ * ----------------------------------------------------------------------------- */
+static String *currentDeclComment = NULL; /* Comment of C/C++ declaration. */
+
+/* -----------------------------------------------------------------------------
+ * Assist Functions
+ * ----------------------------------------------------------------------------- */
+
+
+
+/* Called by the parser (yyparse) when an error is found.*/
+static void yyerror (const char *e) {
+ (void)e;
+}
+
+static Node *new_node(const_String_or_char_ptr tag) {
+ Node *n = Swig_cparse_new_node(tag);
+ return n;
+}
+
+/* Copies a node. Does not copy tree links or symbol table data (except for
+ sym:name) */
+
+static Node *copy_node(Node *n) {
+ Node *nn;
+ Iterator k;
+ nn = NewHash();
+ Setfile(nn,Getfile(n));
+ Setline(nn,Getline(n));
+ for (k = First(n); k.key; k = Next(k)) {
+ String *ci;
+ String *key = k.key;
+ char *ckey = Char(key);
+ if ((strcmp(ckey,"nextSibling") == 0) ||
+ (strcmp(ckey,"previousSibling") == 0) ||
+ (strcmp(ckey,"parentNode") == 0) ||
+ (strcmp(ckey,"lastChild") == 0)) {
+ continue;
+ }
+ if (Strncmp(key,"csym:",5) == 0) continue;
+ /* We do copy sym:name. For templates */
+ if ((strcmp(ckey,"sym:name") == 0) ||
+ (strcmp(ckey,"sym:weak") == 0) ||
+ (strcmp(ckey,"sym:typename") == 0)) {
+ String *ci = Copy(k.item);
+ Setattr(nn,key, ci);
+ Delete(ci);
+ continue;
+ }
+ if (strcmp(ckey,"sym:symtab") == 0) {
+ Setattr(nn,"sym:needs_symtab", "1");
+ }
+ /* We don't copy any other symbol table attributes */
+ if (strncmp(ckey,"sym:",4) == 0) {
+ continue;
+ }
+ /* If children. We copy them recursively using this function */
+ if (strcmp(ckey,"firstChild") == 0) {
+ /* Copy children */
+ Node *cn = k.item;
+ while (cn) {
+ Node *copy = copy_node(cn);
+ appendChild(nn,copy);
+ Delete(copy);
+ cn = nextSibling(cn);
+ }
+ continue;
+ }
+ /* We don't copy the symbol table. But we drop an attribute
+ requires_symtab so that functions know it needs to be built */
+
+ if (strcmp(ckey,"symtab") == 0) {
+ /* Node defined a symbol table. */
+ Setattr(nn,"requires_symtab","1");
+ continue;
+ }
+ /* Can't copy nodes */
+ if (strcmp(ckey,"node") == 0) {
+ continue;
+ }
+ if ((strcmp(ckey,"parms") == 0) || (strcmp(ckey,"pattern") == 0) || (strcmp(ckey,"throws") == 0)
+ || (strcmp(ckey,"kwargs") == 0)) {
+ ParmList *pl = CopyParmList(k.item);
+ Setattr(nn,key,pl);
+ Delete(pl);
+ continue;
+ }
+ if (strcmp(ckey,"nested:outer") == 0) { /* don't copy outer classes links, they will be updated later */
+ Setattr(nn, key, k.item);
+ continue;
+ }
+ /* defaultargs will be patched back in later in update_defaultargs() */
+ if (strcmp(ckey,"defaultargs") == 0) {
+ Setattr(nn, "needs_defaultargs", "1");
+ continue;
+ }
+ /* same for abstracts, which contains pointers to the source node children, and so will need to be patch too */
+ if (strcmp(ckey,"abstracts") == 0) {
+ SetFlag(nn, "needs_abstracts");
+ continue;
+ }
+ /* Looks okay. Just copy the data using Copy */
+ ci = Copy(k.item);
+ Setattr(nn, key, ci);
+ Delete(ci);
+ }
+ return nn;
+}
+
+static void set_comment(Node *n, String *comment) {
+ String *name;
+ Parm *p;
+ if (!n || !comment)
+ return;
+
+ if (Getattr(n, "doxygen"))
+ Append(Getattr(n, "doxygen"), comment);
+ else {
+ Setattr(n, "doxygen", comment);
+ /* This is the first comment, populate it with @params, if any */
+ p = Getattr(n, "parms");
+ while (p) {
+ if (Getattr(p, "doxygen"))
+ Printv(comment, "\n@param ", Getattr(p, "name"), Getattr(p, "doxygen"), NIL);
+ p=nextSibling(p);
+ }
+ }
+
+ /* Append same comment to every generated overload */
+ name = Getattr(n, "name");
+ if (!name)
+ return;
+ n = nextSibling(n);
+ while (n && Getattr(n, "name") && Strcmp(Getattr(n, "name"), name) == 0) {
+ Setattr(n, "doxygen", comment);
+ n = nextSibling(n);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Variables
+ * ----------------------------------------------------------------------------- */
+
+static int cplus_mode = 0;
+
+/* C++ modes */
+
+#define CPLUS_PUBLIC 1
+#define CPLUS_PRIVATE 2
+#define CPLUS_PROTECTED 3
+
+/* storage classes */
+
+#define SWIG_STORAGE_CLASS_EXTERNC 0x0001
+#define SWIG_STORAGE_CLASS_EXTERNCPP 0x0002
+#define SWIG_STORAGE_CLASS_EXTERN 0x0004
+#define SWIG_STORAGE_CLASS_STATIC 0x0008
+#define SWIG_STORAGE_CLASS_TYPEDEF 0x0010
+#define SWIG_STORAGE_CLASS_VIRTUAL 0x0020
+#define SWIG_STORAGE_CLASS_FRIEND 0x0040
+#define SWIG_STORAGE_CLASS_EXPLICIT 0x0080
+#define SWIG_STORAGE_CLASS_CONSTEXPR 0x0100
+#define SWIG_STORAGE_CLASS_THREAD_LOCAL 0x0200
+
+/* Test if multiple bits are set in x. */
+static int multiple_bits_set(unsigned x) { return (x & (x - 1)) != 0; }
+
+static const char* storage_class_string(int c) {
+ switch (c) {
+ case SWIG_STORAGE_CLASS_EXTERNC:
+ return "extern \"C\"";
+ case SWIG_STORAGE_CLASS_EXTERNCPP:
+ return "extern \"C++\"";
+ case SWIG_STORAGE_CLASS_EXTERN:
+ return "extern";
+ case SWIG_STORAGE_CLASS_STATIC:
+ return "static";
+ case SWIG_STORAGE_CLASS_TYPEDEF:
+ return "typedef";
+ case SWIG_STORAGE_CLASS_VIRTUAL:
+ return "virtual";
+ case SWIG_STORAGE_CLASS_FRIEND:
+ return "friend";
+ case SWIG_STORAGE_CLASS_EXPLICIT:
+ return "explicit";
+ case SWIG_STORAGE_CLASS_CONSTEXPR:
+ return "constexpr";
+ case SWIG_STORAGE_CLASS_THREAD_LOCAL:
+ return "thread_local";
+ }
+ assert(0);
+ return "<unknown>";
+}
+
+/* include types */
+static int import_mode = 0;
+
+void SWIG_cparse_set_compact_default_args(int defargs) {
+ compact_default_args = defargs;
+}
+
+int SWIG_cparse_template_reduce(int treduce) {
+ template_reduce = treduce;
+ return treduce;
+}
+
+/* -----------------------------------------------------------------------------
+ * Assist functions
+ * ----------------------------------------------------------------------------- */
+
+static int promote_type(int t) {
+ if (t <= T_UCHAR || t == T_CHAR || t == T_WCHAR) return T_INT;
+ return t;
+}
+
+/* Perform type-promotion for binary operators */
+static int promote(int t1, int t2) {
+ t1 = promote_type(t1);
+ t2 = promote_type(t2);
+ return t1 > t2 ? t1 : t2;
+}
+
+static String *yyrename = 0;
+
+/* Forward renaming operator */
+
+static String *resolve_create_node_scope(String *cname, int is_class_definition, int *errored);
+
+
+Hash *Swig_cparse_features(void) {
+ static Hash *features_hash = 0;
+ if (!features_hash) features_hash = NewHash();
+ return features_hash;
+}
+
+/* -----------------------------------------------------------------------------
+ * feature_identifier_fix()
+ *
+ * If a template, return template with all template parameters fully resolved.
+ *
+ * This is a copy and modification of typemap_identifier_fix.
+ * ----------------------------------------------------------------------------- */
+
+static String *feature_identifier_fix(String *s) {
+ String *tp = SwigType_istemplate_templateprefix(s);
+ if (tp) {
+ String *ts, *ta, *tq;
+ ts = SwigType_templatesuffix(s);
+ ta = SwigType_templateargs(s);
+ tq = Swig_symbol_type_qualify(ta,0);
+ Append(tp,tq);
+ Append(tp,ts);
+ Delete(ts);
+ Delete(ta);
+ Delete(tq);
+ return tp;
+ } else {
+ return NewString(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;
+
+
+
+static String *make_name(Node *n, String *name,SwigType *decl) {
+ String *made_name = 0;
+ int destructor = name && (*(Char(name)) == '~');
+
+ if (yyrename) {
+ String *s = NewString(yyrename);
+ Delete(yyrename);
+ yyrename = 0;
+ if (destructor && (*(Char(s)) != '~')) {
+ Insert(s,0,"~");
+ }
+ return s;
+ }
+
+ if (!name) return 0;
+
+ if (parsing_template_declaration)
+ SetFlag(n, "parsing_template_declaration");
+ made_name = Swig_name_make(n, Namespaceprefix, name, decl, add_oldname);
+ Delattr(n, "parsing_template_declaration");
+
+ return made_name;
+}
+
+/* Generate an unnamed identifier */
+static String *make_unnamed(void) {
+ unnamed++;
+ return NewStringf("$unnamed%d$",unnamed);
+}
+
+static int is_operator(String *name) {
+ return Strncmp(name,"operator ", 9) == 0;
+}
+
+/* Add declaration list to symbol table */
+static int add_only_one = 0;
+
+static void add_symbols(Node *n) {
+ String *decl;
+ String *wrn = 0;
+
+ if (inclass && n) {
+ cparse_normalize_void(n);
+ }
+ while (n) {
+ String *symname = 0;
+ String *old_prefix = 0;
+ Symtab *old_scope = 0;
+ int isfriend = inclass && Strstr(Getattr(n, "storage"), "friend") != NULL;
+ int iscdecl = Cmp(nodeType(n),"cdecl") == 0;
+ int only_csymbol = 0;
+
+ if (inclass) {
+ String *name = Getattr(n, "name");
+ if (isfriend) {
+ /* Friends methods in a class are declared in the namespace enclosing the class (outer most class if a nested class) */
+ String *prefix = name ? Swig_scopename_prefix(name) : 0;
+ Node *outer = currentOuterClass;
+ Symtab *namespace_symtab;
+ old_prefix = Namespaceprefix;
+ old_scope = Swig_symbol_current();
+
+ assert(outer);
+ while (Getattr(outer, "nested:outer")) {
+ outer = Getattr(outer, "nested:outer");
+ }
+ namespace_symtab = Getattr(outer, "sym:symtab");
+ if (!namespace_symtab)
+ namespace_symtab = Getattr(outer, "unofficial:symtab");
+ Swig_symbol_setscope(namespace_symtab);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+
+ if (!prefix) {
+ /* To check - this should probably apply to operators too */
+ if (name && !is_operator(name) && Namespaceprefix) {
+ String *friendusing = NewStringf("using namespace %s;", Namespaceprefix);
+ Setattr(n, "friendusing", friendusing);
+ Delete(friendusing);
+ }
+ } else {
+ /* Qualified friend declarations should not be possible as they are ignored in the parse tree */
+ assert(0);
+ }
+ } else if (Equal(nodeType(n), "using")) {
+ String *uname = Getattr(n, "uname");
+ Node *cls = currentOuterClass;
+ String *nprefix = 0;
+ String *nlast = 0;
+ Swig_scopename_split(uname, &nprefix, &nlast);
+ if (Swig_item_in_list(Getattr(cls, "baselist"), nprefix) || Swig_item_in_list(Getattr(cls, "protectedbaselist"), nprefix) || Swig_item_in_list(Getattr(cls, "privatebaselist"), nprefix)) {
+ String *plain_name = SwigType_istemplate(nprefix) ? SwigType_templateprefix(nprefix) : nprefix;
+ if (Equal(nlast, plain_name)) {
+ /* Using declaration looks like it is using a constructor in an immediate base class - change the constructor name for this class.
+ * C++11 requires using declarations for inheriting base constructors to be in the immediate base class.
+ * Note that we don't try and look up the constructor in the base class as the constructor may be an implicit/implied constructor and hence not exist. */
+ Symtab *stab = Swig_symbol_current();
+ String *nname = Getattr(stab, "name");
+ Setattr(n, "name", nname);
+ SetFlag(n, "usingctor");
+ }
+ }
+ } else {
+ /* for member functions, we need to remove the redundant
+ class scope if provided, as in
+
+ struct Foo {
+ int Foo::method(int a);
+ };
+
+ */
+ String *prefix = name ? Swig_scopename_prefix(name) : 0;
+ if (prefix) {
+ if (Classprefix && (Equal(prefix,Classprefix))) {
+ String *base = Swig_scopename_last(name);
+ Setattr(n,"name",base);
+ Delete(base);
+ }
+ Delete(prefix);
+ }
+ }
+ }
+
+ if (!isfriend && (inclass || extendmode)) {
+ Setattr(n,"ismember","1");
+ }
+
+ if (extendmode) {
+ if (!Getattr(n, "template"))
+ SetFlag(n,"isextendmember");
+ }
+
+ if (!isfriend && inclass) {
+ if ((cplus_mode != CPLUS_PUBLIC)) {
+ only_csymbol = 1;
+ if (cplus_mode == CPLUS_PROTECTED) {
+ Setattr(n,"access", "protected");
+ only_csymbol = !Swig_need_protected(n);
+ } else {
+ Setattr(n,"access", "private");
+ /* private are needed only when they are pure virtuals - why? */
+ if ((Cmp(Getattr(n,"storage"),"virtual") == 0) && (Cmp(Getattr(n,"value"),"0") == 0)) {
+ only_csymbol = 0;
+ }
+ if (Cmp(nodeType(n),"destructor") == 0) {
+ /* Needed for "unref" feature */
+ only_csymbol = 0;
+ }
+ }
+ } else {
+ Setattr(n, "access", "public");
+ }
+ } else if (extendmode && !inclass) {
+ Setattr(n, "access", "public");
+ }
+
+ if (Getattr(n,"sym:name")) {
+ n = nextSibling(n);
+ continue;
+ }
+ 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 (storage && (Strstr(storage, "constexpr") || (Strstr(storage, "static") && !SwigType_ismutable(ty)))) {
+ SetFlag(n, "hasconsttype");
+ }
+ Delete(tmp);
+ }
+ if (!type) {
+ Printf(stderr,"notype name %s\n", name);
+ }
+ }
+ }
+ Swig_features_get(Swig_cparse_features(), Namespaceprefix, 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) {
+ if (parsing_template_declaration)
+ SetFlag(n, "parsing_template_declaration");
+ wrn = Swig_name_warning(n, Namespaceprefix, symname,0);
+ Delattr(n, "parsing_template_declaration");
+ }
+ } 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(),Namespaceprefix,name,fun,n);
+
+ symname = make_name(n, name,fun);
+ if (parsing_template_declaration)
+ SetFlag(n, "parsing_template_declaration");
+ wrn = Swig_name_warning(n, Namespaceprefix,symname,fun);
+ Delattr(n, "parsing_template_declaration");
+
+ Delete(fdecl);
+ Delete(fun);
+
+ }
+ if (!symname) {
+ n = nextSibling(n);
+ continue;
+ }
+
+ if (GetFlag(n, "valueignored")) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_PARSE_ASSIGNED_VALUE, Getfile(n), Getline(n), "Value assigned to %s not used due to limited parsing implementation.\n", SwigType_namestr(Getattr(n, "name")));
+ SWIG_WARN_NODE_END(n);
+ }
+
+ if (cparse_cplusplus) {
+ String *value = Getattr(n, "value");
+ if (value && Strcmp(value, "delete") == 0) {
+ /* C++11 deleted definition / deleted function */
+ SetFlag(n,"deleted");
+ SetFlag(n,"feature:ignore");
+ }
+ if (SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) {
+ /* Ignore rvalue ref-qualifiers by default
+ * Use Getattr instead of GetFlag to handle explicit ignore and explicit not ignore */
+ if (!(Getattr(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0)) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED, Getfile(n), Getline(n),
+ "Method with rvalue ref-qualifier %s ignored.\n", Swig_name_decl(n));
+ SWIG_WARN_NODE_END(n);
+ SetFlag(n, "feature:ignore");
+ }
+ }
+ if (Equal(Getattr(n, "type"), "auto")) {
+ /* Ignore functions with an auto return type and no trailing return type
+ * Use Getattr instead of GetFlag to handle explicit ignore and explicit not ignore */
+ if (!(Getattr(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0)) {
+ SWIG_WARN_NODE_BEGIN(n);
+ if (SwigType_isfunction(Getattr(n, "decl")))
+ Swig_warning(WARN_CPP14_AUTO, Getfile(n), Getline(n), "Unable to deduce auto return type for '%s' (ignored).\n", Swig_name_decl(n));
+ else
+ Swig_warning(WARN_CPP11_AUTO, Getfile(n), Getline(n), "Unable to deduce auto type for variable '%s' (ignored).\n", Swig_name_decl(n));
+ SWIG_WARN_NODE_END(n);
+ SetFlag(n, "feature:ignore");
+ }
+ }
+ }
+ if (only_csymbol || GetFlag(n, "feature:ignore") || Strncmp(symname, "$ignore", 7) == 0) {
+ /* Only add to C symbol table and continue */
+ Swig_symbol_add(0, n);
+ if (!only_csymbol && !GetFlag(n, "feature:ignore")) {
+ /* Print the warning attached to $ignore name, if any */
+ char *c = Char(symname) + 7;
+ if (strlen(c)) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0,Getfile(n), Getline(n), "%s\n",c+1);
+ SWIG_WARN_NODE_END(n);
+ }
+ /* If the symbol was ignored via "rename" and is visible, set also feature:ignore*/
+ SetFlag(n, "feature:ignore");
+ }
+ if (!GetFlag(n, "feature:ignore") && Strcmp(symname,"$ignore") == 0) {
+ /* Add feature:ignore if the symbol was explicitly ignored, regardless of visibility */
+ SetFlag(n, "feature:ignore");
+ }
+ } 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 {
+ Swig_symbol_conflict_warn(n, c, symname, inclass);
+ }
+ }
+ }
+ /* restore the class scope if needed */
+ if (isfriend) {
+ Swig_symbol_setscope(old_scope);
+ if (old_prefix) {
+ Delete(Namespaceprefix);
+ Namespaceprefix = old_prefix;
+ }
+ }
+ Delete(symname);
+
+ if (add_only_one) return;
+ n = nextSibling(n);
+ }
+}
+
+
+/* add symbols a parse tree node copy */
+
+static void add_symbols_copy(Node *n) {
+ int emode = 0;
+ while (n) {
+ if (Equal(nodeType(n), "access")) {
+ String *kind = Getattr(n,"kind");
+ if (Strcmp(kind,"public") == 0) {
+ cplus_mode = CPLUS_PUBLIC;
+ } else if (Strcmp(kind,"private") == 0) {
+ cplus_mode = CPLUS_PRIVATE;
+ } else if (Strcmp(kind,"protected") == 0) {
+ cplus_mode = CPLUS_PROTECTED;
+ }
+ n = nextSibling(n);
+ continue;
+ }
+
+ add_oldname = Getattr(n,"sym:name");
+ if ((add_oldname) || (Getattr(n,"sym:needs_symtab"))) {
+ int old_inclass = -1;
+ Node *oldCurrentOuterClass = 0;
+ if (add_oldname) {
+ DohIncref(add_oldname);
+ /* Disable this, it prevents %rename to work with templates */
+ /* If already renamed, we used that name */
+ /*
+ if (Strcmp(add_oldname, Getattr(n,"name")) != 0) {
+ Delete(yyrename);
+ yyrename = Copy(add_oldname);
+ }
+ */
+ }
+ Delattr(n,"sym:needs_symtab");
+ Delattr(n,"sym:name");
+
+ add_only_one = 1;
+ add_symbols(n);
+
+ if (Getattr(n,"partialargs")) {
+ Swig_symbol_cadd(Getattr(n,"partialargs"),n);
+ }
+ add_only_one = 0;
+ if (Equal(nodeType(n), "class")) {
+ /* add_symbols() above sets "sym:symtab", so "unofficial:symtab" is not required */
+ old_inclass = inclass;
+ oldCurrentOuterClass = currentOuterClass;
+ inclass = 1;
+ currentOuterClass = n;
+ if (Strcmp(Getattr(n,"kind"),"class") == 0) {
+ cplus_mode = CPLUS_PRIVATE;
+ } else {
+ cplus_mode = CPLUS_PUBLIC;
+ }
+ }
+ if (Equal(nodeType(n), "extend")) {
+ emode = cplus_mode;
+ cplus_mode = CPLUS_PUBLIC;
+ }
+
+ if (Getattr(n, "requires_symtab")) {
+ Swig_symbol_newscope();
+ Swig_symbol_setscopename(Getattr(n, "name"));
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+
+ add_symbols_copy(firstChild(n));
+
+ if (Equal(nodeType(n), "extend")) {
+ cplus_mode = emode;
+ }
+ if (Getattr(n,"requires_symtab")) {
+ Setattr(n,"symtab", Swig_symbol_popscope());
+ Delattr(n,"requires_symtab");
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+ if (add_oldname) {
+ Delete(add_oldname);
+ add_oldname = 0;
+ }
+ if (Equal(nodeType(n), "class")) {
+ inclass = old_inclass;
+ currentOuterClass = oldCurrentOuterClass;
+ }
+ } else {
+ if (Equal(nodeType(n), "extend")) {
+ emode = cplus_mode;
+ cplus_mode = CPLUS_PUBLIC;
+ }
+ add_symbols_copy(firstChild(n));
+ if (Equal(nodeType(n), "extend")) {
+ cplus_mode = emode;
+ }
+ }
+ n = nextSibling(n);
+ }
+}
+
+/* Add in the "defaultargs" attribute for functions in instantiated templates.
+ * n should be any instantiated template (class or start of linked list of functions). */
+static void update_defaultargs(Node *n) {
+ if (n) {
+ Node *firstdefaultargs = n;
+ update_defaultargs(firstChild(n));
+ n = nextSibling(n);
+ /* recursively loop through nodes of all types, but all we really need are the overloaded functions */
+ while (n) {
+ update_defaultargs(firstChild(n));
+ if (!Getattr(n, "defaultargs")) {
+ if (Getattr(n, "needs_defaultargs")) {
+ Setattr(n, "defaultargs", firstdefaultargs);
+ Delattr(n, "needs_defaultargs");
+ } else {
+ firstdefaultargs = n;
+ }
+ } else {
+ /* Functions added in with %extend (for specialized template classes) will already have default args patched up */
+ assert(Getattr(n, "defaultargs") == firstdefaultargs);
+ }
+ n = nextSibling(n);
+ }
+ }
+}
+
+/* Check a set of declarations to see if any are pure-abstract */
+
+static List *pure_abstracts(Node *n) {
+ List *abstracts = 0;
+ while (n) {
+ if (Cmp(nodeType(n),"cdecl") == 0) {
+ String *decl = Getattr(n,"decl");
+ if (SwigType_isfunction(decl)) {
+ String *init = Getattr(n,"value");
+ if (Cmp(init,"0") == 0) {
+ if (!abstracts) {
+ abstracts = NewList();
+ }
+ Append(abstracts,n);
+ SetFlag(n,"abstract");
+ }
+ }
+ } else if (Cmp(nodeType(n),"destructor") == 0) {
+ if (Cmp(Getattr(n,"value"),"0") == 0) {
+ if (!abstracts) {
+ abstracts = NewList();
+ }
+ Append(abstracts,n);
+ SetFlag(n,"abstract");
+ }
+ }
+ n = nextSibling(n);
+ }
+ return abstracts;
+}
+
+/* Recompute the "abstracts" attribute for the classes in instantiated templates, similarly to update_defaultargs() above. */
+static void update_abstracts(Node *n) {
+ for (; n; n = nextSibling(n)) {
+ Node* const child = firstChild(n);
+ if (!child)
+ continue;
+
+ update_abstracts(child);
+
+ if (Getattr(n, "needs_abstracts")) {
+ Setattr(n, "abstracts", pure_abstracts(child));
+ Delattr(n, "needs_abstracts");
+ }
+ }
+}
+
+/* Make a classname */
+
+static String *make_class_name(String *name) {
+ String *nname = 0;
+ String *prefix;
+ if (Namespaceprefix) {
+ nname= NewStringf("%s::%s", Namespaceprefix, name);
+ } else {
+ nname = NewString(name);
+ }
+ prefix = SwigType_istemplate_templateprefix(nname);
+ if (prefix) {
+ String *args, *qargs;
+ args = SwigType_templateargs(nname);
+ qargs = Swig_symbol_type_qualify(args,0);
+ Append(prefix,qargs);
+ Delete(nname);
+ Delete(args);
+ Delete(qargs);
+ nname = prefix;
+ }
+ return nname;
+}
+
+/* Use typedef name as class name */
+
+static void add_typedef_name(Node *n, Node *declnode, String *oldName, Symtab *cscope, String *scpname) {
+ String *class_rename = 0;
+ SwigType *decl = Getattr(declnode, "decl");
+ if (!decl || !Len(decl)) {
+ String *cname;
+ String *tdscopename;
+ String *class_scope = Swig_symbol_qualifiedscopename(cscope);
+ String *name = Getattr(declnode, "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", decl);
+ Delete(class_scope);
+ Delete(cname);
+ Delete(tdscopename);
+ }
+}
+
+/* If the class name is qualified. We need to create or lookup namespace entries */
+
+static Symtab *set_scope_to_global(void) {
+ Symtab *symtab = Swig_symbol_global_scope();
+ Swig_symbol_setscope(symtab);
+ return symtab;
+}
+
+/* Remove the block braces, { and }, if the 'noblock' attribute is set.
+ * Node *kw can be either a Hash or Parmlist. */
+static String *remove_block(Node *kw, const String *inputcode) {
+ String *modified_code = 0;
+ while (kw) {
+ String *name = Getattr(kw,"name");
+ if (name && (Cmp(name,"noblock") == 0)) {
+ char *cstr = Char(inputcode);
+ int len = Len(inputcode);
+ if (len && cstr[0] == '{') {
+ --len; ++cstr;
+ if (len && cstr[len - 1] == '}') { --len; }
+ /* we now remove the extra spaces */
+ while (len && isspace((int)cstr[0])) { --len; ++cstr; }
+ while (len && isspace((int)cstr[len - 1])) { --len; }
+ modified_code = NewStringWithSize(cstr, len);
+ break;
+ }
+ }
+ kw = nextSibling(kw);
+ }
+ return modified_code;
+}
+
+/*
+#define RESOLVE_DEBUG 1
+*/
+static Node *nscope = 0;
+static Node *nscope_inner = 0;
+
+/* Remove the scope prefix from cname and return the base name without the prefix.
+ * The scopes required for the symbol name are resolved and/or created, if required.
+ * For example AA::BB::CC as input returns CC and creates the namespace AA then inner
+ * namespace BB in the current scope. */
+static String *resolve_create_node_scope(String *cname_in, int is_class_definition, int *errored) {
+ Symtab *gscope = 0;
+ Node *cname_node = 0;
+ String *cname = cname_in;
+ String *last = Swig_scopename_last(cname);
+ nscope = 0;
+ nscope_inner = 0;
+ *errored = 0;
+
+ if (Strncmp(cname, "::", 2) == 0) {
+ if (is_class_definition) {
+ Swig_error(cparse_file, cparse_line, "Using the unary scope operator :: in class definition '%s' is invalid.\n", SwigType_namestr(cname));
+ *errored = 1;
+ return last;
+ }
+ cname = NewString(Char(cname) + 2);
+ }
+ if (is_class_definition) {
+ /* Only lookup symbols which are in scope via a using declaration but not via a using directive.
+ For example find y via 'using x::y' but not y via a 'using namespace x'. */
+ cname_node = Swig_symbol_clookup_no_inherit(cname, 0);
+ if (!cname_node) {
+ Node *full_lookup_node = Swig_symbol_clookup(cname, 0);
+ if (full_lookup_node) {
+ /* This finds a symbol brought into scope via both a using directive and a using declaration. */
+ Node *last_node = Swig_symbol_clookup_no_inherit(last, 0);
+ if (last_node == full_lookup_node)
+ cname_node = last_node;
+ }
+ }
+ } else {
+ /* For %template, the template needs to be in scope via any means. */
+ cname_node = Swig_symbol_clookup(cname, 0);
+ }
+#if RESOLVE_DEBUG
+ if (!cname_node)
+ Printf(stdout, "symbol does not yet exist (%d): [%s]\n", is_class_definition, cname_in);
+ else
+ Printf(stdout, "symbol does exist (%d): [%s]\n", is_class_definition, cname_in);
+#endif
+
+ if (cname_node) {
+ /* The symbol has been defined already or is in another scope.
+ If it is a weak symbol, it needs replacing and if it was brought into the current scope,
+ the scope needs adjusting appropriately for the new symbol.
+ Similarly for defined templates. */
+ Symtab *symtab = Getattr(cname_node, "sym:symtab");
+ Node *sym_weak = Getattr(cname_node, "sym:weak");
+ if ((symtab && sym_weak) || Equal(nodeType(cname_node), "template")) {
+ /* Check if the scope is the current scope */
+ String *current_scopename = Swig_symbol_qualifiedscopename(0);
+ String *found_scopename = Swig_symbol_qualifiedscopename(symtab);
+ if (!current_scopename)
+ current_scopename = NewString("");
+ if (!found_scopename)
+ found_scopename = NewString("");
+
+ {
+ int fail = 1;
+ List *current_scopes = Swig_scopename_tolist(current_scopename);
+ List *found_scopes = Swig_scopename_tolist(found_scopename);
+ Iterator cit = First(current_scopes);
+ Iterator fit = First(found_scopes);
+#if RESOLVE_DEBUG
+Printf(stdout, "comparing current: [%s] found: [%s]\n", current_scopename, found_scopename);
+#endif
+ for (; fit.item && cit.item; fit = Next(fit), cit = Next(cit)) {
+ String *current = cit.item;
+ String *found = fit.item;
+#if RESOLVE_DEBUG
+ Printf(stdout, " looping %s %s\n", current, found);
+#endif
+ if (Strcmp(current, found) != 0)
+ break;
+ }
+
+ if (!cit.item) {
+ String *subscope = NewString("");
+ for (; fit.item; fit = Next(fit)) {
+ if (Len(subscope) > 0)
+ Append(subscope, "::");
+ Append(subscope, fit.item);
+ }
+ if (Len(subscope) > 0)
+ cname = NewStringf("%s::%s", subscope, last);
+ else
+ cname = Copy(last);
+#if RESOLVE_DEBUG
+ Printf(stdout, "subscope to create: [%s] cname: [%s]\n", subscope, cname);
+#endif
+ fail = 0;
+ Delete(subscope);
+ } else {
+ if (is_class_definition) {
+ if (!fit.item) {
+ /* It is valid to define a new class with the same name as one forward declared in a parent scope */
+ fail = 0;
+ } else if (Swig_scopename_check(cname)) {
+ /* Classes defined with scope qualifiers must have a matching forward declaration in matching scope */
+ fail = 1;
+ } else {
+ /* This may let through some invalid cases */
+ fail = 0;
+ }
+#if RESOLVE_DEBUG
+ Printf(stdout, "scope for class definition, fail: %d\n", fail);
+#endif
+ } else {
+#if RESOLVE_DEBUG
+ Printf(stdout, "no matching base scope for template\n");
+#endif
+ fail = 1;
+ }
+ }
+
+ Delete(found_scopes);
+ Delete(current_scopes);
+
+ if (fail) {
+ String *cname_resolved = NewStringf("%s::%s", found_scopename, last);
+ Swig_error(cparse_file, cparse_line, "'%s' resolves to '%s' and was incorrectly instantiated in scope '%s' instead of within scope '%s'.\n",
+ SwigType_namestr(cname_in), SwigType_namestr(cname_resolved), SwigType_namestr(current_scopename), SwigType_namestr(found_scopename));
+ *errored = 1;
+ Delete(cname_resolved);
+ }
+ }
+
+ Delete(current_scopename);
+ Delete(found_scopename);
+ }
+ } else if (!is_class_definition) {
+ /* A template instantiation requires a template to be found in scope */
+ Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", SwigType_namestr(cname_in));
+ *errored = 1;
+ }
+
+ if (*errored)
+ return last;
+
+ if (Swig_scopename_check(cname) && !*errored) {
+ Node *ns;
+ String *prefix = Swig_scopename_prefix(cname);
+ if (Len(prefix) == 0) {
+ String *base = Copy(last);
+ /* Use the global scope, but we need to add a 'global' namespace. */
+ if (!gscope) gscope = set_scope_to_global();
+ /* note that this namespace is not the "unnamed" one,
+ and we don't use Setattr(nscope,"name", ""),
+ because the unnamed namespace is private */
+ nscope = new_node("namespace");
+ Setattr(nscope,"symtab", gscope);;
+ nscope_inner = nscope;
+ Delete(last);
+ return base;
+ }
+ /* Try to locate the scope */
+ ns = Swig_symbol_clookup(prefix,0);
+ if (!ns) {
+ Swig_error(cparse_file, cparse_line, "Undefined scope '%s'\n", SwigType_namestr(prefix));
+ *errored = 1;
+ } else {
+ Symtab *nstab = Getattr(ns,"symtab");
+ if (!nstab) {
+ Swig_error(cparse_file, cparse_line, "'%s' is not defined as a valid scope.\n", SwigType_namestr(prefix));
+ *errored = 1;
+ ns = 0;
+ } else {
+ /* Check if the node scope is the current scope */
+ String *tname = Swig_symbol_qualifiedscopename(0);
+ String *nname = Swig_symbol_qualifiedscopename(nstab);
+ if (tname && (Strcmp(tname,nname) == 0)) {
+ ns = 0;
+ cname = Copy(last);
+ }
+ Delete(tname);
+ Delete(nname);
+ }
+ if (ns) {
+ /* we will try to create a new node using the namespaces we
+ can find in the scope name */
+ List *scopes = Swig_scopename_tolist(prefix);
+ String *sname;
+ Iterator si;
+
+ for (si = First(scopes); si.item; si = Next(si)) {
+ Node *ns1,*ns2;
+ sname = si.item;
+ ns1 = Swig_symbol_clookup(sname,0);
+ assert(ns1);
+ if (Strcmp(nodeType(ns1),"namespace") == 0) {
+ if (Getattr(ns1,"alias")) {
+ ns1 = Getattr(ns1,"namespace");
+ }
+ } else {
+ /* now this last part is a class */
+ si = Next(si);
+ /* or a nested class tree, which is unrolled here */
+ for (; si.item; si = Next(si)) {
+ if (si.item) {
+ Printf(sname,"::%s",si.item);
+ }
+ }
+ /* we get the 'inner' class */
+ nscope_inner = Swig_symbol_clookup(sname,0);
+ /* set the scope to the inner class */
+ Swig_symbol_setscope(Getattr(nscope_inner,"symtab"));
+ /* save the last namespace prefix */
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ /* and return the node name, including the inner class prefix */
+ break;
+ }
+ /* here we just populate the namespace tree as usual */
+ ns2 = new_node("namespace");
+ Setattr(ns2,"name",sname);
+ Setattr(ns2,"symtab", Getattr(ns1,"symtab"));
+ add_symbols(ns2);
+ Swig_symbol_setscope(Getattr(ns1,"symtab"));
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ if (nscope_inner) {
+ if (Getattr(nscope_inner,"symtab") != Getattr(ns2,"symtab")) {
+ appendChild(nscope_inner,ns2);
+ Delete(ns2);
+ }
+ }
+ nscope_inner = ns2;
+ if (!nscope) nscope = ns2;
+ }
+ cname = Copy(last);
+ Delete(scopes);
+ }
+ }
+ Delete(prefix);
+ }
+ Delete(last);
+
+ return cname;
+}
+
+/* look for simple typedef name in typedef list */
+static String *try_to_find_a_name_for_unnamed_structure(const String *storage, Node *decls) {
+ String *name = 0;
+ Node *n = decls;
+ if (storage && Equal(storage, "typedef")) {
+ for (; n; n = nextSibling(n)) {
+ if (!Len(Getattr(n, "decl"))) {
+ name = Copy(Getattr(n, "name"));
+ break;
+ }
+ }
+ }
+ return name;
+}
+
+/* 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);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * nested_forward_declaration()
+ *
+ * Nested struct handling for C++ code if the nested classes are disabled.
+ * Create the nested class/struct/union as a forward declaration.
+ * ----------------------------------------------------------------------------- */
+
+static Node *nested_forward_declaration(const String *storage, const String *kind, String *sname, String *name, Node *cpp_opt_declarators) {
+ Node *nn = 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");
+ SetFlag(n, "nested:forward");
+ 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 && Equal(storage, "typedef"));
+ int variable_of_anonymous_type = !sname && !storage_typedef;
+ if (!variable_of_anonymous_type) {
+ int anonymous_typedef = !sname && storage_typedef;
+ 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;
+ }
+ }
+ }
+
+ if (!currentOuterClass || !GetFlag(currentOuterClass, "nested")) {
+ if (nn && Equal(nodeType(nn), "classforward")) {
+ Node *n = nn;
+ if (!GetFlag(n, "feature:ignore")) {
+ 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, SwigType_namestr(sname ? sname : name));
+ SWIG_WARN_NODE_END(n);
+ }
+ } else {
+ Swig_warning(WARN_PARSE_UNNAMED_NESTED_CLASS, cparse_file, cparse_line, "Nested %s not currently supported (ignored).\n", kind);
+ }
+ }
+
+ return nn;
+}
+
+
+Node *Swig_cparse(File *f) {
+ scanner_file(f);
+ top = 0;
+ if (yyparse() == 2) {
+ Swig_error(cparse_file, cparse_line, "Parser exceeded stack depth or ran out of memory\n");
+ Exit(EXIT_FAILURE);
+ }
+ return (Node *)top;
+}
+
+static void single_new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
+ String *fname;
+ String *name;
+ String *fixname;
+ SwigType *t = Copy(type);
+
+ /* Printf(stdout, "single_new_feature: [%s] [%s] [%s] [%s] [%s] [%s]\n", featurename, val, declaratorid, t, ParmList_str_defaultargs(declaratorparms), qualifier); */
+
+ fname = NewStringf("feature:%s",featurename);
+ if (declaratorid) {
+ fixname = feature_identifier_fix(declaratorid);
+ } else {
+ fixname = NewStringEmpty();
+ }
+ if (Namespaceprefix) {
+ name = NewStringf("%s::%s",Namespaceprefix, fixname);
+ } else {
+ name = fixname;
+ }
+
+ if (declaratorparms) Setmeta(val,"parms",declaratorparms);
+ if (!Len(t)) t = 0;
+ if (t) {
+ if (qualifier) SwigType_push(t,qualifier);
+ if (SwigType_isfunction(t)) {
+ SwigType *decl = SwigType_pop_function(t);
+ if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",name);
+ Swig_feature_set(Swig_cparse_features(), nname, decl, fname, val, featureattribs);
+ Delete(nname);
+ } else {
+ Swig_feature_set(Swig_cparse_features(), name, decl, fname, val, featureattribs);
+ }
+ Delete(decl);
+ } else if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",name);
+ Swig_feature_set(Swig_cparse_features(),nname,0,fname,val, featureattribs);
+ Delete(nname);
+ }
+ } else {
+ /* Global feature, that is, feature not associated with any particular symbol */
+ Swig_feature_set(Swig_cparse_features(),name,0,fname,val, featureattribs);
+ }
+ Delete(fname);
+ Delete(name);
+}
+
+/* Add a new feature to the Hash. Additional features are added if the feature has a parameter list (declaratorparms)
+ * and one or more of the parameters have a default argument. An extra feature is added for each defaulted parameter,
+ * simulating the equivalent overloaded method. */
+static void new_feature(const char *featurename, String *val, Hash *featureattribs, char *declaratorid, SwigType *type, ParmList *declaratorparms, String *qualifier) {
+
+ ParmList *declparms = declaratorparms;
+
+ /* remove the { and } braces if the noblock attribute is set */
+ String *newval = remove_block(featureattribs, val);
+ val = newval ? newval : val;
+
+ /* Add the feature */
+ single_new_feature(featurename, val, featureattribs, declaratorid, type, declaratorparms, qualifier);
+
+ /* Add extra features if there are default parameters in the parameter list */
+ if (type) {
+ while (declparms) {
+ if (ParmList_has_defaultargs(declparms)) {
+
+ /* Create a parameter list for the new feature by copying all
+ but the last (defaulted) parameter */
+ ParmList* newparms = CopyParmListMax(declparms, ParmList_len(declparms)-1);
+
+ /* Create new declaration - with the last parameter removed */
+ SwigType *newtype = Copy(type);
+ Delete(SwigType_pop_function(newtype)); /* remove the old parameter list from newtype */
+ SwigType_add_function(newtype,newparms);
+
+ single_new_feature(featurename, Copy(val), featureattribs, declaratorid, newtype, newparms, qualifier);
+ declparms = newparms;
+ } else {
+ declparms = 0;
+ }
+ }
+ }
+}
+
+/* check if a function declaration is a plain C object */
+static int is_cfunction(Node *n) {
+ if (!cparse_cplusplus || cparse_externc)
+ return 1;
+ if (Swig_storage_isexternc(n)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* If the Node is a function with parameters, check to see if any of the parameters
+ * have default arguments. If so create a new function for each defaulted argument.
+ * The additional functions form a linked list of nodes with the head being the original Node n. */
+static void default_arguments(Node *n) {
+ Node *function = n;
+
+ if (function) {
+ ParmList *varargs = Getattr(function,"feature:varargs");
+ if (varargs) {
+ /* Handles the %varargs directive by looking for "feature:varargs" and
+ * substituting ... with an alternative set of arguments. */
+ Parm *p = Getattr(function,"parms");
+ Parm *pp = 0;
+ while (p) {
+ SwigType *t = Getattr(p,"type");
+ if (Strcmp(t,"v(...)") == 0) {
+ if (pp) {
+ ParmList *cv = Copy(varargs);
+ set_nextSibling(pp,cv);
+ Delete(cv);
+ } else {
+ ParmList *cv = Copy(varargs);
+ Setattr(function,"parms", cv);
+ Delete(cv);
+ }
+ break;
+ }
+ pp = p;
+ p = nextSibling(p);
+ }
+ }
+
+ /* Do not add in functions if kwargs is being used or if user wants old default argument wrapping
+ (one wrapped method per function irrespective of number of default arguments) */
+ if (compact_default_args
+ || is_cfunction(function)
+ || GetFlag(function,"feature:compactdefaultargs")
+ || (GetFlag(function,"feature:kwargs") && kwargs_supported)) {
+ ParmList *p = Getattr(function,"parms");
+ if (p)
+ Setattr(p,"compactdefargs", "1"); /* mark parameters for special handling */
+ function = 0; /* don't add in extra methods */
+ }
+ }
+
+ while (function) {
+ ParmList *parms = Getattr(function,"parms");
+ if (ParmList_has_defaultargs(parms)) {
+
+ /* Create a parameter list for the new function by copying all
+ but the last (defaulted) parameter */
+ ParmList* newparms = CopyParmListMax(parms,ParmList_len(parms)-1);
+
+ /* Create new function and add to symbol table */
+ {
+ SwigType *ntype = Copy(nodeType(function));
+ char *cntype = Char(ntype);
+ Node *new_function = new_node(ntype);
+ SwigType *decl = Copy(Getattr(function,"decl"));
+ int constqualifier = SwigType_isconst(decl);
+ String *ccode = Copy(Getattr(function,"code"));
+ String *cstorage = Copy(Getattr(function,"storage"));
+ String *cvalue = Copy(Getattr(function,"value"));
+ SwigType *ctype = Copy(Getattr(function,"type"));
+ String *cthrow = Copy(Getattr(function,"throw"));
+
+ Delete(SwigType_pop_function(decl)); /* remove the old parameter list from decl */
+ SwigType_add_function(decl,newparms);
+ if (constqualifier)
+ SwigType_add_qualifier(decl,"const");
+
+ Setattr(new_function,"name", Getattr(function,"name"));
+ Setattr(new_function,"code", ccode);
+ Setattr(new_function,"decl", decl);
+ Setattr(new_function,"parms", newparms);
+ Setattr(new_function,"storage", cstorage);
+ Setattr(new_function,"value", cvalue);
+ Setattr(new_function,"type", ctype);
+ Setattr(new_function,"throw", cthrow);
+
+ Delete(ccode);
+ Delete(cstorage);
+ Delete(cvalue);
+ Delete(ctype);
+ Delete(cthrow);
+ Delete(decl);
+
+ {
+ Node *throws = Getattr(function,"throws");
+ ParmList *pl = CopyParmList(throws);
+ if (throws) Setattr(new_function,"throws",pl);
+ Delete(pl);
+ }
+
+ /* copy specific attributes for global (or in a namespace) template functions - these are not class template methods */
+ if (strcmp(cntype,"template") == 0) {
+ Node *templatetype = Getattr(function,"templatetype");
+ Node *symtypename = Getattr(function,"sym:typename");
+ Parm *templateparms = Getattr(function,"templateparms");
+ if (templatetype) {
+ Node *tmp = Copy(templatetype);
+ Setattr(new_function,"templatetype",tmp);
+ Delete(tmp);
+ }
+ if (symtypename) {
+ Node *tmp = Copy(symtypename);
+ Setattr(new_function,"sym:typename",tmp);
+ Delete(tmp);
+ }
+ if (templateparms) {
+ Parm *tmp = CopyParmList(templateparms);
+ Setattr(new_function,"templateparms",tmp);
+ Delete(tmp);
+ }
+ } else if (strcmp(cntype,"constructor") == 0) {
+ /* only copied for constructors as this is not a user defined feature - it is hard coded in the parser */
+ if (GetFlag(function,"feature:new")) SetFlag(new_function,"feature:new");
+ }
+
+ add_symbols(new_function);
+ /* mark added functions as ones with overloaded parameters and point to the parsed method */
+ Setattr(new_function,"defaultargs", n);
+
+ /* Point to the new function, extending the linked list */
+ set_nextSibling(function, new_function);
+ Delete(new_function);
+ function = new_function;
+
+ Delete(ntype);
+ }
+ } else {
+ function = 0;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * mark_nodes_as_extend()
+ *
+ * Used by the %extend to mark subtypes with "feature:extend".
+ * template instances declared within %extend are skipped
+ * ----------------------------------------------------------------------------- */
+
+static void mark_nodes_as_extend(Node *n) {
+ for (; n; n = nextSibling(n)) {
+ if (Getattr(n, "template") && Strcmp(nodeType(n), "class") == 0)
+ continue;
+ /* Fix me: extend is not a feature. Replace with isextendmember? */
+ Setattr(n, "feature:extend", "1");
+ mark_nodes_as_extend(firstChild(n));
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * add_qualifier_to_declarator()
+ *
+ * Normally the qualifier is pushed on to the front of the type.
+ * Adding a qualifier to a pointer to member function is a special case.
+ * For example : typedef double (Cls::*pmf)(void) const;
+ * The qualifier is : q(const).
+ * The declarator is : m(Cls).f(void).
+ * We need : m(Cls).q(const).f(void).
+ * ----------------------------------------------------------------------------- */
+
+static String *add_qualifier_to_declarator(SwigType *type, SwigType *qualifier) {
+ int is_pointer_to_member_function = 0;
+ String *decl = Copy(type);
+ String *poppedtype = NewString("");
+ assert(qualifier);
+
+ while (decl) {
+ if (SwigType_ismemberpointer(decl)) {
+ String *memberptr = SwigType_pop(decl);
+ if (SwigType_isfunction(decl)) {
+ is_pointer_to_member_function = 1;
+ SwigType_push(decl, qualifier);
+ SwigType_push(decl, memberptr);
+ Insert(decl, 0, poppedtype);
+ Delete(memberptr);
+ break;
+ } else {
+ Append(poppedtype, memberptr);
+ }
+ Delete(memberptr);
+ } else {
+ String *popped = SwigType_pop(decl);
+ if (!popped)
+ break;
+ Append(poppedtype, popped);
+ Delete(popped);
+ }
+ }
+
+ if (!is_pointer_to_member_function) {
+ Delete(decl);
+ decl = Copy(type);
+ SwigType_push(decl, qualifier);
+ }
+
+ Delete(poppedtype);
+ return decl;
+}
+
+%}
+
+%union {
+ const char *id;
+ List *bases;
+ struct Define {
+ // The value of the expression as C/C++ code.
+ String *val;
+ // If type is a string or char type, this is the actual value of that
+ // string or char type as a String (in cases where SWIG can determine
+ // it - currently that means for literals). This is useful in cases where
+ // we want to emit a string or character literal in the target language -
+ // we could just try emitting the C/C++ code for the literal, but that
+ // won't always be correct in most target languages.
+ //
+ // SWIG's scanner reads the string or character literal in the source code
+ // and interprets quoting and escape sequences. Concatenation of adjacent
+ // string literals is currently handled here in the parser (though
+ // technically it should happen before parsing).
+ //
+ // stringval holds the actual value of the string (from the scanner,
+ // taking into account concatenation of adjacent string literals).
+ // Then val is created by escaping stringval using SWIG's %(escape)s
+ // Printf specification, and adding the appropriate quotes (and
+ // an L-prefix for wide literals). So val is also a C/C++ source
+ // representation of the string, but may not be the same representation
+ // as in the source code (it should be equivalent though).
+ //
+ // Some examples:
+ //
+ // C/C++ source stringval val Notes
+ // ------------- ----------- --------- -------
+ // "bar" bar "bar"
+ // "b\x61r" bar "bar"
+ // "b\141r" bar "bar"
+ // "b" "ar" bar "bar"
+ // u8"bar" bar "bar" C++11
+ // R"bar" bar "bar" C++11
+ // "\228\22" "8" "\"8\""
+ // "\\\"\'" \"' "\\\"\'"
+ // R"(\"')" \"' "\\\"\'" C++11
+ // L"bar" bar L"bar"
+ // L"b" L"ar" bar L"bar"
+ // L"b" "ar" bar L"bar" C++11
+ // "b" L"ar" bar L"bar" C++11
+ // 'x' x 'x'
+ // '\"' " '\"'
+ // '\42' " '\"'
+ // '\042' " '\"'
+ // '\x22' " '\"'
+ //
+ // Zero bytes are allowed in stringval (DOH's String can hold a string
+ // with embedded zero bytes), but handling may currently be buggy in
+ // places.
+ String *stringval;
+ // If type is an integer or boolean type, this is the actual value of that
+ // type as a base 10 integer in a String (in cases where SWIG can determine
+ // this value - currently that means for literals). This is useful in
+ // cases where we want to emit an integer or boolean literal in the target
+ // language - we could just try emitting the C/C++ code for the literal,
+ // but that won't always be correct in most target languages.
+ //
+ // SWIG doesn't attempt to evaluate constant expressions, except that it
+ // can handle unary - (because a negative integer literal is actually
+ // syntactically unary minus applied to a positive integer literal),
+ // unary + (for consistency with unary -) and parentheses (because
+ // literals in #define are often in parentheses). These operators are
+ // handled in the parser so whitespace is also handled within such
+ // expressions.
+ //
+ // Some examples:
+ //
+ // C/C++ source numval val Notes
+ // ------------- ----------- --------- -------
+ // 123 123 123
+ // 0x7b 123 0x7b
+ // 0x7B 123 0x7B
+ // 0173 123 0173
+ // 0b1111011 123 0b1111011 C++14
+ // -10 -10 -10 numval not set for unsigned type
+ // -0x00a -10 -0x00a numval not set for unsigned type
+ // -012 -10 -012 numval not set for unsigned type
+ // -0b1010 -10 -0b1010 C++14; numval not set for unsigned
+ // (42) 42 (42)
+ // +42 42 +42
+ // +(42) 42 +(42)
+ // -(42) -42 -(42) numval not set for unsigned type
+ // (-(42)) -42 (-(42)) numval not set for unsigned type
+ // false 0 false
+ // (false) 0 (false)
+ // true 1 true
+ // (true) 1 (true)
+ String *numval;
+ int type;
+ /* The type code for the argument when the top level operator is unary.
+ * This is useful because our grammar parses cases such as (7)*6 as a
+ * cast applied to an unary operator.
+ */
+ int unary_arg_type;
+ String *qualifier;
+ String *refqualifier;
+ String *bitfield;
+ Parm *throws;
+ String *throwf;
+ String *nexcept;
+ String *final;
+ } dtype;
+ struct {
+ String *filename;
+ int line;
+ } loc;
+ struct Decl {
+ char *id;
+ SwigType *type;
+ String *defarg;
+ String *stringdefarg;
+ String *numdefarg;
+ ParmList *parms;
+ short have_parms;
+ ParmList *throws;
+ String *throwf;
+ String *nexcept;
+ String *final;
+ } decl;
+ Parm *tparms;
+ struct {
+ String *method;
+ Hash *kwargs;
+ } tmap;
+ struct {
+ String *type;
+ String *us;
+ } ptype;
+ SwigType *type;
+ String *str;
+ Parm *p;
+ ParmList *pl;
+ int intvalue;
+ enum { INCLUDE_INCLUDE, INCLUDE_IMPORT } includetype;
+ Node *node;
+ struct {
+ Parm *parms;
+ Parm *last;
+ } pbuilder;
+ struct {
+ Node *node;
+ Node *last;
+ } nodebuilder;
+};
+
+/* Define special token END for end of input. */
+%token END 0
+
+%token <id> ID
+%token <str> HBLOCK
+%token <id> POUND
+%token <str> STRING WSTRING
+%token INCLUDE IMPORT INSERT
+%token <str> CHARCONST WCHARCONST
+%token <dtype> NUM_INT NUM_DOUBLE NUM_FLOAT NUM_LONGDOUBLE NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL
+%token TYPEDEF
+%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64
+%token LPAREN RPAREN COMMA SEMI EXTERN LBRACE RBRACE PERIOD ELLIPSIS
+%token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF ALIGNOF MODULE LBRACKET RBRACKET
+%token BEGINFILE ENDOFFILE
+%token CONSTANT
+%token RENAME NAMEWARN EXTEND PRAGMA FEATURE VARARGS
+%token ENUM
+%token CLASS TYPENAME PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND THROW CATCH EXPLICIT
+%token STATIC_ASSERT CONSTEXPR THREAD_LOCAL DECLTYPE AUTO NOEXCEPT /* C++11 keywords */
+%token OVERRIDE FINAL /* C++11 identifiers with special meaning */
+%token USING
+%token NAMESPACE
+%token NATIVE INLINE
+%token TYPEMAP ECHO APPLY CLEAR SWIGTEMPLATE FRAGMENT
+%token WARN
+%token LESSTHAN GREATERTHAN DELETE_KW DEFAULT
+%token LESSTHANOREQUALTO GREATERTHANOREQUALTO EQUALTO NOTEQUALTO LESSEQUALGREATER
+%token ARROW
+%token QUESTIONMARK
+%token TYPES PARMS
+%token NONID DSTAR DCNOT
+%token TEMPLATE
+%token <str> OPERATOR
+%token <str> CONVERSIONOPERATOR
+%token PARSETYPE PARSEPARM PARSEPARMS
+
+%token <str> DOXYGENSTRING
+%token <str> DOXYGENPOSTSTRING
+
+%left QUESTIONMARK
+%left LOR
+%left LAND
+%left OR
+%left XOR
+%left AND
+%left EQUALTO NOTEQUALTO
+/* We don't currently allow < and > in any context where the associativity or
+ * precedence matters and Bison warns about that.
+ */
+%left /* GREATERTHAN LESSTHAN */ GREATERTHANOREQUALTO LESSTHANOREQUALTO
+%left LESSEQUALGREATER
+%left LSHIFT RSHIFT
+%left PLUS MINUS
+%left STAR SLASH MODULO
+%precedence UMINUS NOT LNOT CAST
+%token DCOLON
+
+%type <node> program interface declaration swig_directive ;
+
+/* SWIG directives */
+%type <node> extend_directive apply_directive clear_directive constant_directive ;
+%type <node> echo_directive fragment_directive include_directive inline_directive ;
+%type <node> insert_directive module_directive native_directive ;
+%type <node> pragma_directive rename_directive feature_directive varargs_directive typemap_directive ;
+%type <node> types_directive template_directive warn_directive ;
+
+/* C declarations */
+%type <node> c_declaration c_decl c_decl_tail c_enum_decl c_enum_forward_decl c_constructor_decl;
+%type <type> c_enum_inherit;
+%type <node> enumlist enumlist_item edecl_with_dox edecl;
+%type <id> c_enum_key;
+
+/* C++ declarations */
+%type <node> cpp_declaration cpp_class_decl cpp_forward_class_decl cpp_template_decl;
+%type <node> cpp_members cpp_member cpp_member_no_dox;
+%type <nodebuilder> cpp_members_builder;
+%type <node> cpp_constructor_decl cpp_destructor_decl cpp_protection_decl cpp_conversion_operator cpp_static_assert;
+%type <node> cpp_swig_directive cpp_template_possible cpp_opt_declarators ;
+%type <node> cpp_using_decl cpp_namespace_decl cpp_catch_decl cpp_lambda_decl;
+%type <node> kwargs options;
+%type <nodebuilder> kwargs_builder;
+
+/* Misc */
+%type <id> identifier;
+%type <dtype> initializer cpp_const exception_specification cv_ref_qualifier qualifiers_exception_specification;
+%type <str> storage_class;
+%type <intvalue> storage_class_raw storage_class_list;
+%type <pl> parms rawparms varargs_parms ;
+%type <p> parm_no_dox parm valparm valparms;
+%type <pbuilder> valparms_builder;
+%type <p> typemap_parm tm_list;
+%type <pbuilder> tm_list_builder;
+%type <p> templateparameter ;
+%type <type> templcpptype cpptype;
+%type classkey classkeyopt;
+%type <id> access_specifier;
+%type <node> base_specifier;
+%type <intvalue> variadic_opt;
+%type <type> type rawtype type_right anon_bitfield_type decltype decltypeexpr cpp_alternate_rettype;
+%type <bases> base_list inherit raw_inherit;
+%type <dtype> definetype def_args etype default_delete deleted_definition explicit_default;
+%type <dtype> expr exprnum exprsimple exprcompound valexpr exprmem;
+%type <id> ename ;
+%type <str> less_valparms_greater;
+%type <str> type_qualifier;
+%type <str> ref_qualifier;
+%type <id> type_qualifier_raw;
+%type <id> idstring idstringopt;
+%type <id> pragma_lang;
+%type <str> pragma_arg;
+%type <includetype> includetype;
+%type <type> pointer primitive_type;
+%type <decl> declarator direct_declarator notso_direct_declarator parameter_declarator plain_declarator;
+%type <decl> abstract_declarator direct_abstract_declarator ctor_end;
+%type <tmap> typemap_type;
+%type <str> idcolon idcolontail idcolonnt idcolontailnt idtemplate idtemplatetemplate stringbrace stringbracesemi;
+%type <str> string stringnum wstring;
+%type <tparms> template_parms;
+%type <pbuilder> template_parms_builder;
+%type <dtype> cpp_vend;
+%type <intvalue> rename_namewarn;
+%type <ptype> type_specifier primitive_type_list ;
+%type <node> fname stringtype;
+%type <node> featattr;
+%type lambda_introducer lambda_body lambda_template lambda_tail;
+%type <str> virt_specifier_seq virt_specifier_seq_opt;
+%type <str> class_virt_specifier_opt;
+
+%{
+
+// Default-initialised instances of token types to avoid uninitialised fields.
+// The compiler will initialise all fields to zero or NULL for us.
+
+static const struct Decl default_decl;
+static const struct Define default_dtype;
+
+/* C++ decltype/auto type deduction. */
+static SwigType *deduce_type(const struct Define *dtype) {
+ Node *n;
+ if (!dtype->val) return NULL;
+ n = Swig_symbol_clookup(dtype->val, 0);
+ if (n) {
+ if (Strcmp(nodeType(n),"enumitem") == 0) {
+ /* For an enumitem, the "type" attribute gives us the underlying integer
+ * type - we want the "type" attribute from the enum itself, which is
+ * "parentNode".
+ */
+ n = Getattr(n, "parentNode");
+ }
+ return Getattr(n, "type");
+ } else if (dtype->type != T_AUTO && dtype->type != T_UNKNOWN) {
+ /* Try to deduce the type from the T_* type code. */
+ String *deduced_type = NewSwigType(dtype->type);
+ if (Len(deduced_type) > 0) return deduced_type;
+ Delete(deduced_type);
+ }
+ return NULL;
+}
+
+static Node *new_enum_node(SwigType *enum_base_type) {
+ Node *n = new_node("enum");
+ if (enum_base_type) {
+ switch (SwigType_type(enum_base_type)) {
+ case T_USER:
+ // We get T_USER if the underlying type is a typedef. Unfortunately we
+ // aren't able to resolve a typedef at this point, so we have to assume
+ // it's a typedef to an integral or boolean type.
+ break;
+ case T_BOOL:
+ case T_SCHAR:
+ case T_UCHAR:
+ case T_SHORT:
+ case T_USHORT:
+ case T_INT:
+ case T_UINT:
+ case T_LONG:
+ case T_ULONG:
+ case T_LONGLONG:
+ case T_ULONGLONG:
+ case T_CHAR:
+ case T_WCHAR:
+ break;
+ default:
+ Swig_error(cparse_file, cparse_line, "Underlying type of enum must be an integral type\n");
+ }
+ Setattr(n, "enumbase", enum_base_type);
+ }
+ return n;
+}
+
+%}
+
+%%
+
+/* ======================================================================
+ * High-level Interface file
+ *
+ * An interface is just a sequence of declarations which may be SWIG directives
+ * or normal C declarations.
+ * ====================================================================== */
+
+program : interface {
+ if (!classes) classes = NewHash();
+ Setattr($interface,"classes",classes);
+ Setattr($interface,"name",ModuleName);
+
+ if ((!module_node) && ModuleName) {
+ module_node = new_node("module");
+ Setattr(module_node,"name",ModuleName);
+ }
+ Setattr($interface,"module",module_node);
+ top = $interface;
+ }
+ | PARSETYPE parm END {
+ top = Copy(Getattr($parm,"type"));
+ Delete($parm);
+ }
+ | PARSETYPE error {
+ top = 0;
+ }
+ | PARSEPARM parm END {
+ top = $parm;
+ }
+ | PARSEPARM error {
+ top = 0;
+ }
+ | PARSEPARMS LPAREN parms RPAREN END {
+ top = $parms;
+ }
+ | PARSEPARMS error {
+ top = 0;
+ }
+ ;
+
+interface : interface[in] declaration {
+ /* add declaration to end of linked list (the declaration isn't always a single declaration, sometimes it is a linked list itself) */
+ if (currentDeclComment != NULL) {
+ set_comment($declaration, currentDeclComment);
+ currentDeclComment = NULL;
+ }
+ appendChild($in,$declaration);
+ $$ = $in;
+ }
+ | interface[in] DOXYGENSTRING {
+ Delete(currentDeclComment);
+ currentDeclComment = $DOXYGENSTRING;
+ $$ = $in;
+ }
+ | interface[in] DOXYGENPOSTSTRING {
+ Node *node = lastChild($in);
+ if (node) {
+ set_comment(node, $DOXYGENPOSTSTRING);
+ } else {
+ Delete($DOXYGENPOSTSTRING);
+ }
+ $$ = $in;
+ }
+ | %empty {
+ $$ = new_node("top");
+ }
+ ;
+
+declaration : swig_directive
+ | c_declaration
+ | cpp_declaration
+ | SEMI { $$ = 0; }
+ | error {
+ if (cparse_unknown_directive) {
+ Swig_error(cparse_file, cparse_line, "Unknown directive '%s'.\n", cparse_unknown_directive);
+ } else {
+ Swig_error(cparse_file, cparse_line, "Syntax error in input(1).\n");
+ }
+ Exit(EXIT_FAILURE);
+ }
+/* Out of class constructor/destructor declarations */
+ | c_constructor_decl {
+ if ($$) {
+ add_symbols($$);
+ }
+ $$ = $c_constructor_decl;
+ }
+
+/* Out of class conversion operator. For example:
+ inline A::operator char *() const { ... }.
+
+ This is nearly impossible to parse normally. We just let the
+ first part generate a syntax error and then resynchronize on the
+ CONVERSIONOPERATOR token---discarding the rest of the definition. Ugh.
+
+ */
+
+ | error CONVERSIONOPERATOR {
+ $$ = 0;
+ Delete($CONVERSIONOPERATOR);
+ skip_decl();
+ }
+ ;
+
+/* ======================================================================
+ * SWIG DIRECTIVES
+ * ====================================================================== */
+
+swig_directive : extend_directive
+ | apply_directive
+ | clear_directive
+ | constant_directive
+ | echo_directive
+ | fragment_directive
+ | include_directive
+ | inline_directive
+ | insert_directive
+ | module_directive
+ | native_directive
+ | pragma_directive
+ | rename_directive
+ | feature_directive
+ | varargs_directive
+ | typemap_directive
+ | types_directive
+ | template_directive
+ | warn_directive
+ ;
+
+/* ------------------------------------------------------------
+ %extend classname { ... }
+ ------------------------------------------------------------ */
+
+extend_directive : EXTEND options classkeyopt idcolon LBRACE {
+ Node *cls;
+ String *clsname;
+ extendmode = 1;
+ cplus_mode = CPLUS_PUBLIC;
+ if (!classes) classes = NewHash();
+ if (!classes_typedefs) classes_typedefs = NewHash();
+ clsname = make_class_name($idcolon);
+ cls = Getattr(classes,clsname);
+ if (!cls) {
+ cls = Getattr(classes_typedefs, clsname);
+ if (!cls) {
+ /* No previous definition. Create a new scope */
+ Node *am = Getattr(Swig_extend_hash(),clsname);
+ if (!am) {
+ Swig_symbol_newscope();
+ Swig_symbol_setscopename($idcolon);
+ prev_symtab = 0;
+ } else {
+ prev_symtab = Swig_symbol_setscope(Getattr(am,"symtab"));
+ }
+ current_class = 0;
+ } else {
+ /* Previous typedef class definition. Use its symbol table.
+ Deprecated, just the real name should be used.
+ Note that %extend before the class typedef never worked, only %extend after the class typedef. */
+ prev_symtab = Swig_symbol_setscope(Getattr(cls, "symtab"));
+ current_class = cls;
+ 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")), $idcolon);
+ SWIG_WARN_NODE_END(cls);
+ }
+ } else {
+ /* Previous class definition. Use its symbol table */
+ prev_symtab = Swig_symbol_setscope(Getattr(cls,"symtab"));
+ current_class = cls;
+ }
+ Classprefix = NewString($idcolon);
+ Namespaceprefix= Swig_symbol_qualifiedscopename(0);
+ Delete(clsname);
+ } cpp_members RBRACE {
+ String *clsname;
+ extendmode = 0;
+ $$ = new_node("extend");
+ Setattr($$,"symtab",Swig_symbol_popscope());
+ if (prev_symtab) {
+ Swig_symbol_setscope(prev_symtab);
+ }
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ clsname = make_class_name($idcolon);
+ Setattr($$,"name",clsname);
+
+ mark_nodes_as_extend($cpp_members);
+ if (current_class) {
+ /* We add the extension to the previously defined class */
+ appendChild($$, $cpp_members);
+ appendChild(current_class,$$);
+ } else {
+ /* We store the extensions in the extensions hash */
+ Node *am = Getattr(Swig_extend_hash(),clsname);
+ if (am) {
+ /* Append the members to the previous extend methods */
+ appendChild(am, $cpp_members);
+ } else {
+ appendChild($$, $cpp_members);
+ Setattr(Swig_extend_hash(),clsname,$$);
+ }
+ }
+ current_class = 0;
+ Delete(Classprefix);
+ Delete(clsname);
+ Classprefix = 0;
+ prev_symtab = 0;
+ $$ = 0;
+
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %apply
+ ------------------------------------------------------------ */
+
+apply_directive : APPLY typemap_parm LBRACE tm_list RBRACE {
+ $$ = new_node("apply");
+ Setattr($$,"pattern",Getattr($typemap_parm,"pattern"));
+ appendChild($$,$tm_list);
+ };
+
+/* ------------------------------------------------------------
+ %clear
+ ------------------------------------------------------------ */
+
+clear_directive : CLEAR tm_list SEMI {
+ $$ = new_node("clear");
+ appendChild($$,$tm_list);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %constant name = value;
+ %constant type name = value;
+
+ Note: Source/Preprocessor/cpp.c injects `%constant X = Y;` for
+ each `#define X Y` so that's handled here too.
+ ------------------------------------------------------------ */
+
+constant_directive : CONSTANT identifier EQUAL definetype SEMI {
+ SwigType *type = NewSwigType($definetype.type);
+ if (Len(type) > 0) {
+ $$ = new_node("constant");
+ Setattr($$, "name", $identifier);
+ Setattr($$, "type", type);
+ Setattr($$, "value", $definetype.val);
+ if ($definetype.stringval) Setattr($$, "stringval", $definetype.stringval);
+ if ($definetype.numval) Setattr($$, "numval", $definetype.numval);
+ Setattr($$, "storage", "%constant");
+ SetFlag($$, "feature:immutable");
+ add_symbols($$);
+ Delete(type);
+ } else {
+ Swig_warning(WARN_PARSE_UNSUPPORTED_VALUE, cparse_file, cparse_line, "Unsupported constant value (ignored)\n");
+ $$ = 0;
+ }
+ }
+ | CONSTANT type declarator def_args SEMI {
+ SwigType_push($type, $declarator.type);
+ /* Sneaky callback function trick */
+ if (SwigType_isfunction($type)) {
+ SwigType_add_pointer($type);
+ }
+ $$ = new_node("constant");
+ Setattr($$, "name", $declarator.id);
+ Setattr($$, "type", $type);
+ Setattr($$, "value", $def_args.val);
+ if ($def_args.stringval) Setattr($$, "stringval", $def_args.stringval);
+ if ($def_args.numval) Setattr($$, "numval", $def_args.numval);
+ Setattr($$, "storage", "%constant");
+ SetFlag($$, "feature:immutable");
+ add_symbols($$);
+ }
+ /* Member function pointers with qualifiers. eg.
+ %constant short (Funcs::*pmf)(bool) const = &Funcs::F; */
+ | CONSTANT type direct_declarator LPAREN parms RPAREN cv_ref_qualifier def_args SEMI {
+ SwigType_add_function($type, $parms);
+ SwigType_push($type, $cv_ref_qualifier.qualifier);
+ SwigType_push($type, $direct_declarator.type);
+ /* Sneaky callback function trick */
+ if (SwigType_isfunction($type)) {
+ SwigType_add_pointer($type);
+ }
+ $$ = new_node("constant");
+ Setattr($$, "name", $direct_declarator.id);
+ Setattr($$, "type", $type);
+ Setattr($$, "value", $def_args.val);
+ if ($def_args.stringval) Setattr($$, "stringval", $def_args.stringval);
+ if ($def_args.numval) Setattr($$, "numval", $def_args.numval);
+ Setattr($$, "storage", "%constant");
+ SetFlag($$, "feature:immutable");
+ add_symbols($$);
+ }
+ | CONSTANT error SEMI {
+ Swig_warning(WARN_PARSE_BAD_VALUE,cparse_file,cparse_line,"Bad constant value (ignored).\n");
+ $$ = 0;
+ }
+ | CONSTANT error END {
+ Swig_error(cparse_file,cparse_line,"Missing semicolon (';') after %%constant.\n");
+ Exit(EXIT_FAILURE);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %echo "text"
+ %echo %{ ... %}
+ ------------------------------------------------------------ */
+
+echo_directive : ECHO HBLOCK {
+ char temp[64];
+ Replace($HBLOCK,"$file",cparse_file, DOH_REPLACE_ANY);
+ sprintf(temp,"%d", cparse_line);
+ Replace($HBLOCK,"$line",temp,DOH_REPLACE_ANY);
+ Printf(stderr,"%s\n", $HBLOCK);
+ Delete($HBLOCK);
+ $$ = 0;
+ }
+ | ECHO string {
+ char temp[64];
+ String *s = $string;
+ Replace(s,"$file",cparse_file, DOH_REPLACE_ANY);
+ sprintf(temp,"%d", cparse_line);
+ Replace(s,"$line",temp,DOH_REPLACE_ANY);
+ Printf(stderr,"%s\n", s);
+ Delete(s);
+ $$ = 0;
+ }
+ ;
+
+/* fragment keyword arguments */
+stringtype : string LBRACE parm RBRACE {
+ $$ = NewHash();
+ Setattr($$,"value",$string);
+ Setattr($$,"type",Getattr($parm,"type"));
+ }
+ ;
+
+fname : string {
+ $$ = NewHash();
+ Setattr($$,"value",$string);
+ }
+ | stringtype
+ ;
+
+/* ------------------------------------------------------------
+ %fragment(name, section) %{ ... %}
+ %fragment("name" {type}, "section") %{ ... %}
+ %fragment("name", "section", fragment="fragment1", fragment="fragment2") %{ ... %}
+ Also as above but using { ... }
+ %fragment("name");
+ ------------------------------------------------------------ */
+
+fragment_directive: FRAGMENT LPAREN fname COMMA kwargs RPAREN HBLOCK {
+ Hash *p = $kwargs;
+ $$ = new_node("fragment");
+ Setattr($$,"value",Getattr($fname,"value"));
+ Setattr($$,"type",Getattr($fname,"type"));
+ Setattr($$,"section",Getattr(p,"name"));
+ Setattr($$,"kwargs",nextSibling(p));
+ Setattr($$,"code",$HBLOCK);
+ Delete($HBLOCK);
+ }
+ | FRAGMENT LPAREN fname COMMA kwargs RPAREN LBRACE {
+ Hash *p = $kwargs;
+ String *code;
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = new_node("fragment");
+ Setattr($$,"value",Getattr($fname,"value"));
+ Setattr($$,"type",Getattr($fname,"type"));
+ Setattr($$,"section",Getattr(p,"name"));
+ Setattr($$,"kwargs",nextSibling(p));
+ Delitem(scanner_ccode,0);
+ Delitem(scanner_ccode,DOH_END);
+ code = Copy(scanner_ccode);
+ Setattr($$,"code",code);
+ Delete(code);
+ }
+ | FRAGMENT LPAREN fname RPAREN SEMI {
+ $$ = new_node("fragment");
+ Setattr($$,"value",Getattr($fname,"value"));
+ Setattr($$,"type",Getattr($fname,"type"));
+ Setattr($$,"emitonly","1");
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %includefile(option1="xyz", ...) "filename" [ declarations ]
+ %importfile(option1="xyz", ...) "filename" [ declarations ]
+ ------------------------------------------------------------ */
+
+include_directive: includetype options string BEGINFILE <loc>{
+ $$.filename = Copy(cparse_file);
+ $$.line = cparse_line;
+ scanner_set_location($string,1);
+ if ($options) {
+ String *maininput = Getattr($options, "maininput");
+ if (maininput)
+ scanner_set_main_input_file(NewString(maininput));
+ }
+ }[loc] interface ENDOFFILE {
+ String *mname = 0;
+ $$ = $interface;
+ scanner_set_location($loc.filename, $loc.line + 1);
+ Delete($loc.filename);
+ switch ($includetype) {
+ case INCLUDE_INCLUDE:
+ set_nodeType($$, "include");
+ break;
+ case INCLUDE_IMPORT:
+ mname = $options ? Getattr($options, "module") : 0;
+ set_nodeType($$, "import");
+ if (import_mode) --import_mode;
+ break;
+ }
+
+ Setattr($$,"name",$string);
+ /* Search for the module (if any) */
+ {
+ Node *n = firstChild($$);
+ while (n) {
+ if (Strcmp(nodeType(n),"module") == 0) {
+ if (mname) {
+ Setattr(n,"name", mname);
+ mname = 0;
+ }
+ Setattr($$,"module",Getattr(n,"name"));
+ break;
+ }
+ n = nextSibling(n);
+ }
+ if (mname) {
+ /* There is no module node in the import
+ node, ie, you imported a .h file
+ directly. We are forced then to create
+ a new import node with a module node.
+ */
+ Node *nint = new_node("import");
+ Node *mnode = new_node("module");
+ Setattr(mnode,"name", mname);
+ Setattr(mnode,"options",$options);
+ appendChild(nint,mnode);
+ Delete(mnode);
+ appendChild(nint,firstChild($$));
+ $$ = nint;
+ Setattr($$,"module",mname);
+ }
+ }
+ Setattr($$,"options",$options);
+ }
+ ;
+
+includetype : INCLUDE { $$ = INCLUDE_INCLUDE; }
+ | IMPORT { $$ = INCLUDE_IMPORT; ++import_mode;}
+ ;
+
+/* ------------------------------------------------------------
+ %inline %{ ... %}
+ ------------------------------------------------------------ */
+
+inline_directive : INLINE HBLOCK {
+ String *cpps;
+ if (Namespaceprefix) {
+ Swig_error(cparse_file, cparse_start_line, "%%inline directive inside a namespace is disallowed.\n");
+ $$ = 0;
+ } else {
+ $$ = new_node("insert");
+ Setattr($$,"code",$HBLOCK);
+ /* Need to run through the preprocessor */
+ Seek($HBLOCK,0,SEEK_SET);
+ Setline($HBLOCK,cparse_start_line);
+ Setfile($HBLOCK,cparse_file);
+ cpps = Preprocessor_parse($HBLOCK);
+ scanner_start_inline(cpps, cparse_start_line);
+ Delete(cpps);
+ }
+ Delete($HBLOCK);
+ }
+ | INLINE LBRACE {
+ String *cpps;
+ int start_line = cparse_line;
+ if (Namespaceprefix) {
+ Swig_error(cparse_file, cparse_start_line, "%%inline directive inside a namespace is disallowed.\n");
+ }
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ if (Namespaceprefix) {
+ $$ = 0;
+ } else {
+ String *code;
+ $$ = new_node("insert");
+ Delitem(scanner_ccode,0);
+ Delitem(scanner_ccode,DOH_END);
+ code = Copy(scanner_ccode);
+ Setattr($$,"code", code);
+ Delete(code);
+ cpps=Copy(scanner_ccode);
+ scanner_start_inline(cpps, start_line);
+ Delete(cpps);
+ }
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %{ ... %}
+ %insert(section) "filename"
+ %insert("section") "filename"
+ %insert(section) %{ ... %}
+ %insert("section") %{ ... %}
+ %insert(section) { ... }
+ %insert("section") { ... }
+ ------------------------------------------------------------ */
+
+insert_directive : HBLOCK {
+ $$ = new_node("insert");
+ Setattr($$,"code",$HBLOCK);
+ Delete($HBLOCK);
+ }
+ | INSERT LPAREN idstring RPAREN string {
+ String *code = NewStringEmpty();
+ $$ = new_node("insert");
+ Setattr($$,"section",$idstring);
+ Setattr($$,"code",code);
+ if (Swig_insert_file($string,code) < 0) {
+ Swig_error(cparse_file, cparse_line, "Couldn't find '%s'.\n", $string);
+ $$ = 0;
+ }
+ }
+ | INSERT LPAREN idstring RPAREN HBLOCK {
+ $$ = new_node("insert");
+ Setattr($$,"section",$idstring);
+ Setattr($$,"code",$HBLOCK);
+ Delete($HBLOCK);
+ }
+ | INSERT LPAREN idstring RPAREN LBRACE {
+ String *code;
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = new_node("insert");
+ Setattr($$,"section",$idstring);
+ Delitem(scanner_ccode,0);
+ Delitem(scanner_ccode,DOH_END);
+ code = Copy(scanner_ccode);
+ Setattr($$,"code", code);
+ Delete(code);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %module modname
+ %module "modname"
+ ------------------------------------------------------------ */
+
+module_directive: MODULE options idstring {
+ $$ = new_node("module");
+ if ($options) {
+ Setattr($$,"options",$options);
+ if (Getattr($options,"directors")) {
+ Wrapper_director_mode_set(1);
+ if (!cparse_cplusplus) {
+ Swig_error(cparse_file, cparse_line, "Directors are not supported for C code and require the -c++ option\n");
+ }
+ }
+ if (Getattr($options,"dirprot")) {
+ Wrapper_director_protected_mode_set(1);
+ }
+ if (Getattr($options,"allprotected")) {
+ Wrapper_all_protected_mode_set(1);
+ }
+ if (Getattr($options,"templatereduce")) {
+ template_reduce = 1;
+ }
+ if (Getattr($options,"notemplatereduce")) {
+ template_reduce = 0;
+ }
+ }
+ if (!ModuleName) ModuleName = NewString($idstring);
+ if (!import_mode) {
+ /* first module included, we apply global
+ ModuleName, which can be modify by -module */
+ String *mname = Copy(ModuleName);
+ Setattr($$,"name",mname);
+ Delete(mname);
+ } else {
+ /* import mode, we just pass the idstring */
+ Setattr($$,"name",$idstring);
+ }
+ if (!module_node) module_node = $$;
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %native(scriptname) name;
+ %native(scriptname) type name (parms);
+ ------------------------------------------------------------ */
+
+native_directive : NATIVE LPAREN identifier[name] RPAREN storage_class identifier[wrap_name] SEMI {
+ $$ = new_node("native");
+ Setattr($$,"name",$name);
+ Setattr($$,"wrap:name",$wrap_name);
+ Delete($storage_class);
+ add_symbols($$);
+ }
+ | NATIVE LPAREN identifier RPAREN storage_class type declarator SEMI {
+ if (!SwigType_isfunction($declarator.type)) {
+ Swig_error(cparse_file,cparse_line,"%%native declaration '%s' is not a function.\n", $declarator.id);
+ $$ = 0;
+ } else {
+ Delete(SwigType_pop_function($declarator.type));
+ /* Need check for function here */
+ SwigType_push($type,$declarator.type);
+ $$ = new_node("native");
+ Setattr($$,"name",$identifier);
+ Setattr($$,"wrap:name",$declarator.id);
+ Setattr($$,"type",$type);
+ Setattr($$,"parms",$declarator.parms);
+ Setattr($$,"decl",$declarator.type);
+ }
+ Delete($storage_class);
+ add_symbols($$);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %pragma(lang) name=value
+ %pragma(lang) name
+ %pragma name = value
+ %pragma name
+ ------------------------------------------------------------ */
+
+pragma_directive : PRAGMA pragma_lang identifier EQUAL pragma_arg {
+ $$ = new_node("pragma");
+ Setattr($$,"lang",$pragma_lang);
+ Setattr($$,"name",$identifier);
+ Setattr($$,"value",$pragma_arg);
+ }
+ | PRAGMA pragma_lang identifier {
+ $$ = new_node("pragma");
+ Setattr($$,"lang",$pragma_lang);
+ Setattr($$,"name",$identifier);
+ }
+ ;
+
+pragma_arg : string
+ | HBLOCK
+ ;
+
+pragma_lang : LPAREN identifier RPAREN { $$ = $identifier; }
+ | %empty { $$ = "swig"; }
+ ;
+
+/* ------------------------------------------------------------
+ %rename(newname) identifier;
+ ------------------------------------------------------------ */
+
+rename_directive : rename_namewarn declarator idstring SEMI {
+ SwigType *t = $declarator.type;
+ Hash *kws = NewHash();
+ String *fixname;
+ fixname = feature_identifier_fix($declarator.id);
+ Setattr(kws,"name",$idstring);
+ if (!Len(t)) t = 0;
+ /* Special declarator check */
+ if (t) {
+ if (SwigType_isfunction(t)) {
+ SwigType *decl = SwigType_pop_function(t);
+ if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",fixname);
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix, nname,decl,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,nname,decl,kws);
+ }
+ Delete(nname);
+ } else {
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,(fixname),decl,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,(fixname),decl,kws);
+ }
+ }
+ Delete(decl);
+ } else if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",fixname);
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,(nname),0,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,(nname),0,kws);
+ }
+ Delete(nname);
+ }
+ } else {
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,(fixname),0,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,(fixname),0,kws);
+ }
+ }
+ $$ = 0;
+ scanner_clear_rename();
+ }
+ | rename_namewarn LPAREN kwargs RPAREN declarator cpp_const SEMI {
+ String *fixname;
+ Hash *kws = $kwargs;
+ SwigType *t = $declarator.type;
+ fixname = feature_identifier_fix($declarator.id);
+ if (!Len(t)) t = 0;
+ /* Special declarator check */
+ if (t) {
+ if ($cpp_const.qualifier) SwigType_push(t,$cpp_const.qualifier);
+ if (SwigType_isfunction(t)) {
+ SwigType *decl = SwigType_pop_function(t);
+ if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",fixname);
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix, nname,decl,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,nname,decl,kws);
+ }
+ Delete(nname);
+ } else {
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,(fixname),decl,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,(fixname),decl,kws);
+ }
+ }
+ Delete(decl);
+ } else if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",fixname);
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,(nname),0,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,(nname),0,kws);
+ }
+ Delete(nname);
+ }
+ } else {
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,(fixname),0,kws,$declarator.parms);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,(fixname),0,kws);
+ }
+ }
+ $$ = 0;
+ scanner_clear_rename();
+ }
+ | rename_namewarn LPAREN kwargs RPAREN string SEMI {
+ if ($rename_namewarn) {
+ Swig_name_rename_add(Namespaceprefix,$string,0,$kwargs,0);
+ } else {
+ Swig_name_namewarn_add(Namespaceprefix,$string,0,$kwargs);
+ }
+ $$ = 0;
+ scanner_clear_rename();
+ }
+ ;
+
+rename_namewarn : RENAME {
+ $$ = 1;
+ }
+ | NAMEWARN {
+ $$ = 0;
+ };
+
+
+/* ------------------------------------------------------------
+ Feature targeting a symbol name (non-global feature):
+
+ %feature(featurename) name "val";
+ %feature(featurename, val) name;
+
+ where "val" could instead be the other bracket types, that is,
+ { val } or %{ val %} or indeed omitted whereupon it defaults to "1".
+ Or, the global feature which does not target a symbol name:
+
+ %feature(featurename) "val";
+ %feature(featurename, val);
+
+ An empty val (empty string) clears the feature.
+ Any number of feature attributes can optionally be added, for example
+ a non-global feature with 2 attributes:
+
+ %feature(featurename, attrib1="attribval1", attrib2="attribval2") name "val";
+ %feature(featurename, val, attrib1="attribval1", attrib2="attribval2") name;
+ ------------------------------------------------------------ */
+
+ /* Non-global feature */
+feature_directive : FEATURE LPAREN idstring featattr RPAREN declarator cpp_const stringbracesemi {
+ String *val = $stringbracesemi ? NewString($stringbracesemi) : NewString("1");
+ new_feature($idstring, val, $featattr, $declarator.id, $declarator.type, $declarator.parms, $cpp_const.qualifier);
+ $$ = 0;
+ scanner_clear_rename();
+ }
+ | FEATURE LPAREN idstring COMMA stringnum featattr RPAREN declarator cpp_const SEMI {
+ String *val = Len($stringnum) ? $stringnum : 0;
+ new_feature($idstring, val, $featattr, $declarator.id, $declarator.type, $declarator.parms, $cpp_const.qualifier);
+ $$ = 0;
+ scanner_clear_rename();
+ }
+
+ /* Global feature */
+ | FEATURE LPAREN idstring featattr RPAREN stringbracesemi {
+ String *val = $stringbracesemi ? NewString($stringbracesemi) : NewString("1");
+ new_feature($idstring, val, $featattr, 0, 0, 0, 0);
+ $$ = 0;
+ scanner_clear_rename();
+ }
+ | FEATURE LPAREN idstring COMMA stringnum featattr RPAREN SEMI {
+ String *val = Len($stringnum) ? $stringnum : 0;
+ new_feature($idstring, val, $featattr, 0, 0, 0, 0);
+ $$ = 0;
+ scanner_clear_rename();
+ }
+ ;
+
+stringbracesemi : stringbrace
+ | SEMI { $$ = 0; }
+ | PARMS LPAREN parms RPAREN SEMI { $$ = $parms; }
+ ;
+
+featattr : COMMA idstring EQUAL stringnum featattr[in] {
+ $$ = NewHash();
+ Setattr($$,"name",$idstring);
+ Setattr($$,"value",$stringnum);
+ if ($in) set_nextSibling($$, $in);
+ }
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+/* %varargs() directive. */
+
+varargs_directive : VARARGS LPAREN varargs_parms RPAREN declarator cpp_const SEMI {
+ Parm *val;
+ String *name;
+ SwigType *t;
+ if (Namespaceprefix) name = NewStringf("%s::%s", Namespaceprefix, $declarator.id);
+ else name = NewString($declarator.id);
+ val = $varargs_parms;
+ if ($declarator.parms) {
+ Setmeta(val,"parms",$declarator.parms);
+ }
+ t = $declarator.type;
+ if (!Len(t)) t = 0;
+ if (t) {
+ if ($cpp_const.qualifier) SwigType_push(t,$cpp_const.qualifier);
+ if (SwigType_isfunction(t)) {
+ SwigType *decl = SwigType_pop_function(t);
+ if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",name);
+ Swig_feature_set(Swig_cparse_features(), nname, decl, "feature:varargs", val, 0);
+ Delete(nname);
+ } else {
+ Swig_feature_set(Swig_cparse_features(), name, decl, "feature:varargs", val, 0);
+ }
+ Delete(decl);
+ } else if (SwigType_ispointer(t)) {
+ String *nname = NewStringf("*%s",name);
+ Swig_feature_set(Swig_cparse_features(),nname,0,"feature:varargs",val, 0);
+ Delete(nname);
+ }
+ } else {
+ Swig_feature_set(Swig_cparse_features(),name,0,"feature:varargs",val, 0);
+ }
+ Delete(name);
+ $$ = 0;
+ };
+
+varargs_parms : parms
+ | NUM_INT COMMA parm {
+ int i;
+ int n;
+ Parm *p;
+ n = atoi(Char($NUM_INT.val));
+ if (n <= 0) {
+ Swig_error(cparse_file, cparse_line,"Argument count in %%varargs must be positive.\n");
+ $$ = 0;
+ } else {
+ String *name = Getattr($parm, "name");
+ $$ = Copy($parm);
+ if (name)
+ Setattr($$, "name", NewStringf("%s%d", name, n));
+ for (i = 1; i < n; i++) {
+ p = Copy($parm);
+ name = Getattr(p, "name");
+ if (name)
+ Setattr(p, "name", NewStringf("%s%d", name, n-i));
+ set_nextSibling(p,$$);
+ Delete($$);
+ $$ = p;
+ }
+ }
+ }
+ ;
+
+
+/* ------------------------------------------------------------
+ %typemap(method) type { ... }
+ %typemap(method) type "..."
+ %typemap(method) type; - typemap deletion
+ %typemap(method) type1,type2,... = type; - typemap copy
+ ------------------------------------------------------------ */
+
+typemap_directive : TYPEMAP LPAREN typemap_type RPAREN tm_list stringbrace {
+ $$ = 0;
+ if ($typemap_type.method) {
+ String *code = 0;
+ $$ = new_node("typemap");
+ Setattr($$,"method",$typemap_type.method);
+ if ($typemap_type.kwargs) {
+ ParmList *kw = $typemap_type.kwargs;
+ code = remove_block(kw, $stringbrace);
+ Setattr($$,"kwargs", $typemap_type.kwargs);
+ }
+ code = code ? code : NewString($stringbrace);
+ Setattr($$,"code", code);
+ Delete(code);
+ appendChild($$,$tm_list);
+ Delete($typemap_type.kwargs);
+ Delete($typemap_type.method);
+ }
+ }
+ | TYPEMAP LPAREN typemap_type RPAREN tm_list SEMI {
+ $$ = 0;
+ if ($typemap_type.method) {
+ $$ = new_node("typemap");
+ Setattr($$,"method",$typemap_type.method);
+ appendChild($$,$tm_list);
+ Delete($typemap_type.method);
+ }
+ Delete($typemap_type.kwargs);
+ }
+ | TYPEMAP LPAREN typemap_type RPAREN tm_list EQUAL typemap_parm SEMI {
+ $$ = 0;
+ if ($typemap_type.method) {
+ $$ = new_node("typemapcopy");
+ Setattr($$,"method",$typemap_type.method);
+ Setattr($$,"pattern", Getattr($typemap_parm,"pattern"));
+ appendChild($$,$tm_list);
+ Delete($typemap_type.method);
+ }
+ Delete($typemap_type.kwargs);
+ }
+ ;
+
+/* typemap method and optional kwargs */
+
+typemap_type : kwargs {
+ String *name = Getattr($kwargs, "name");
+ Hash *p = nextSibling($kwargs);
+ $$.method = name;
+ $$.kwargs = p;
+ if (Getattr($kwargs, "value")) {
+ Swig_error(cparse_file, cparse_line,
+ "%%typemap method shouldn't have a value specified.\n");
+ }
+ while (p) {
+ if (!Getattr(p, "value")) {
+ Swig_error(cparse_file, cparse_line,
+ "%%typemap attribute '%s' is missing its value. If this is specifying the target language, that's no longer supported: use #ifdef SWIG<LANG> instead.\n",
+ Getattr(p, "name"));
+ /* Set to empty value to avoid segfaults later. */
+ Setattr(p, "value", NewStringEmpty());
+ }
+ p = nextSibling(p);
+ }
+ }
+ ;
+
+tm_list : tm_list_builder {
+ $$ = $tm_list_builder.parms;
+ }
+ ;
+
+tm_list_builder: typemap_parm {
+ $$.parms = $$.last = $typemap_parm;
+ }
+ | tm_list_builder[in] COMMA typemap_parm {
+ // Build a linked list in the order specified, but avoiding
+ // a right recursion rule because "Right recursion uses up
+ // space on the Bison stack in proportion to the number of
+ // elements in the sequence".
+ set_nextSibling($in.last, $typemap_parm);
+ $$.parms = $in.parms;
+ $$.last = $typemap_parm;
+ }
+ ;
+
+typemap_parm : type plain_declarator {
+ Parm *parm;
+ SwigType_push($type,$plain_declarator.type);
+ $$ = new_node("typemapitem");
+ parm = NewParmWithoutFileLineInfo($type,$plain_declarator.id);
+ Setattr($$,"pattern",parm);
+ Setattr($$,"parms", $plain_declarator.parms);
+ Delete(parm);
+ /* $$ = NewParmWithoutFileLineInfo($type,$plain_declarator.id);
+ Setattr($$,"parms",$plain_declarator.parms); */
+ }
+ | LPAREN parms RPAREN {
+ $$ = new_node("typemapitem");
+ Setattr($$,"pattern",$parms);
+ /* Setattr($$,"multitype",$parms); */
+ }
+ | LPAREN parms[pattern] RPAREN LPAREN parms[in] RPAREN {
+ $$ = new_node("typemapitem");
+ Setattr($$,"pattern", $pattern);
+ /* Setattr($$,"multitype",$in); */
+ Setattr($$,"parms",$in);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %types(parmlist);
+ %types(parmlist) %{ ... %}
+ ------------------------------------------------------------ */
+
+types_directive : TYPES LPAREN parms RPAREN stringbracesemi {
+ $$ = new_node("types");
+ Setattr($$,"parms",$parms);
+ if ($stringbracesemi)
+ Setattr($$,"convcode",NewString($stringbracesemi));
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %template(name) tname<args>;
+ ------------------------------------------------------------ */
+
+template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN valparms GREATERTHAN SEMI {
+ Parm *p;
+ Node *n = 0;
+ Node *outer_class = currentOuterClass;
+ Symtab *tscope = 0;
+ String *symname = $idstringopt ? NewString($idstringopt) : 0;
+ int errored_flag = 0;
+ String *idcolonnt;
+
+ $$ = 0;
+
+ tscope = Swig_symbol_current(); /* Get the current scope */
+
+ /* If the class name is qualified, we need to create or lookup namespace entries */
+ idcolonnt = resolve_create_node_scope($idcolonnt, 0, &errored_flag);
+
+ if (!errored_flag) {
+ if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0)
+ outer_class = nscope_inner;
+
+ /*
+ We use the new namespace entry 'nscope' only to
+ emit the template node. The template parameters are
+ resolved in the current 'tscope'.
+
+ This is closer to the C++ (typedef) behavior.
+ */
+ n = Swig_cparse_template_locate(idcolonnt, $valparms, symname, tscope);
+ }
+
+ /* Patch the argument types to respect namespaces */
+ p = $valparms;
+ while (p) {
+ SwigType *value = Getattr(p,"value");
+ if (!value) {
+ SwigType *ty = Getattr(p,"type");
+ if (ty) {
+ SwigType *rty = 0;
+ int reduce = template_reduce;
+ if (reduce || !SwigType_ispointer(ty)) {
+ rty = Swig_symbol_typedef_reduce(ty,tscope);
+ if (!reduce) reduce = SwigType_ispointer(rty);
+ }
+ ty = reduce ? Swig_symbol_type_qualify(rty,tscope) : Swig_symbol_type_qualify(ty,tscope);
+ Setattr(p,"type",ty);
+ Delete(ty);
+ Delete(rty);
+ }
+ } else {
+ value = Swig_symbol_type_qualify(value,tscope);
+ Setattr(p,"value",value);
+ Delete(value);
+ }
+
+ p = nextSibling(p);
+ }
+
+ /* Look for the template */
+ {
+ Node *nn = n;
+ Node *linklistend = 0;
+ Node *linkliststart = 0;
+ while (nn) {
+ Node *templnode = 0;
+ if (GetFlag(nn, "instantiate")) {
+ Delattr(nn, "instantiate");
+ {
+ int nnisclass = (Strcmp(Getattr(nn, "templatetype"), "class") == 0); /* class template not a classforward nor function template */
+ Parm *tparms = Getattr(nn, "templateparms");
+ int specialized = !tparms; /* fully specialized (an explicit specialization) */
+ String *tname = Copy(idcolonnt);
+ Node *primary_template = Swig_symbol_clookup(tname, 0);
+
+ /* Expand the template */
+ ParmList *temparms = Swig_cparse_template_parms_expand($valparms, primary_template, nn);
+
+ templnode = copy_node(nn);
+ update_nested_classes(templnode); /* update classes nested within template */
+ /* We need to set the node name based on name used to instantiate */
+ Setattr(templnode,"name",tname);
+ Delete(tname);
+ if (!specialized) {
+ Delattr(templnode,"sym:typename");
+ } else {
+ Setattr(templnode,"sym:typename","1");
+ }
+ /* for now, nested %template is allowed only in the same scope as the template declaration */
+ if (symname && !(nnisclass && ((outer_class && (outer_class != Getattr(nn, "nested:outer")))
+ ||(extendmode && current_class && (current_class != Getattr(nn, "nested:outer")))))) {
+ /*
+ Comment this out for 1.3.28. We need to
+ re-enable it later but first we need to
+ move %ignore from using %rename to use
+ %feature(ignore).
+
+ String *symname = Swig_name_make(templnode, 0, symname, 0, 0);
+ */
+ Swig_cparse_template_expand(templnode, symname, temparms, tscope);
+ Setattr(templnode, "sym:name", symname);
+ } else {
+ static int cnt = 0;
+ String *nname = NewStringf("__dummy_%d__", cnt++);
+ Swig_cparse_template_expand(templnode,nname,temparms,tscope);
+ Setattr(templnode,"sym:name",nname);
+ SetFlag(templnode,"hidden");
+ Delete(nname);
+ Setattr(templnode,"feature:onlychildren", "typemap,typemapitem,typemapcopy,typedef,types,fragment,apply");
+ if (symname) {
+ Swig_warning(WARN_PARSE_NESTED_TEMPLATE, cparse_file, cparse_line, "Named nested template instantiations not supported. Processing as if no name was given to %%template().\n");
+ }
+ }
+ Delattr(templnode,"templatetype");
+ Setattr(templnode,"template",nn);
+ Setfile(templnode,cparse_file);
+ Setline(templnode,cparse_line);
+ Delete(temparms);
+ if (outer_class && nnisclass) {
+ SetFlag(templnode, "nested");
+ Setattr(templnode, "nested:outer", outer_class);
+ }
+ add_symbols_copy(templnode);
+
+ if (Equal(nodeType(templnode), "classforward") && !(GetFlag(templnode, "feature:ignore") || GetFlag(templnode, "hidden"))) {
+ SWIG_WARN_NODE_BEGIN(templnode);
+ /* A full template class definition is required in order to wrap a template class as a proxy class so this %template is ineffective. */
+ if (GetFlag(templnode, "nested:forward"))
+ Swig_warning(WARN_PARSE_TEMPLATE_NESTED, cparse_file, cparse_line, "Unsupported template nested class '%s' cannot be used to instantiate a full template class with name '%s'.\n", Swig_name_decl(templnode), Getattr(templnode, "sym:name"));
+ else
+ Swig_warning(WARN_PARSE_TEMPLATE_FORWARD, cparse_file, cparse_line, "Template forward class '%s' cannot be used to instantiate a full template class with name '%s'.\n", Swig_name_decl(templnode), Getattr(templnode, "sym:name"));
+ SWIG_WARN_NODE_END(templnode);
+ }
+
+ if (Strcmp(nodeType(templnode),"class") == 0) {
+
+ /* Identify pure abstract methods */
+ Setattr(templnode,"abstracts", pure_abstracts(firstChild(templnode)));
+
+ /* Set up inheritance in symbol table */
+ {
+ Symtab *csyms;
+ List *baselist = Getattr(templnode,"baselist");
+ csyms = Swig_symbol_current();
+ Swig_symbol_setscope(Getattr(templnode,"symtab"));
+ if (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)) {
+ 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_symbol_setscope(csyms);
+ }
+
+ /* Merge in %extend methods for this class.
+ This only merges methods within %extend for a template specialized class such as
+ template<typename T> class K {}; %extend K<int> { ... }
+ The copy_node() call above has already added in the generic %extend methods such as
+ template<typename T> class K {}; %extend K { ... } */
+
+ /* !!! This may be broken. We may have to add the
+ %extend methods at the beginning of the class */
+ {
+ String *stmp = 0;
+ String *clsname;
+ Node *am;
+ if (Namespaceprefix) {
+ clsname = stmp = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
+ } else {
+ clsname = Getattr(templnode,"name");
+ }
+ am = Getattr(Swig_extend_hash(),clsname);
+ if (am) {
+ Symtab *st = Swig_symbol_current();
+ Swig_symbol_setscope(Getattr(templnode,"symtab"));
+ /* Printf(stdout,"%s: %s %p %p\n", Getattr(templnode,"name"), clsname, Swig_symbol_current(), Getattr(templnode,"symtab")); */
+ Swig_extend_merge(templnode,am);
+ Swig_symbol_setscope(st);
+ Swig_extend_append_previous(templnode,am);
+ Delattr(Swig_extend_hash(),clsname);
+ }
+ if (stmp) Delete(stmp);
+ }
+
+ /* Add to classes hash */
+ if (!classes)
+ classes = NewHash();
+
+ if (Namespaceprefix) {
+ String *temp = NewStringf("%s::%s", Namespaceprefix, Getattr(templnode,"name"));
+ Setattr(classes,temp,templnode);
+ Delete(temp);
+ } else {
+ String *qs = Swig_symbol_qualifiedscopename(templnode);
+ Setattr(classes, qs,templnode);
+ Delete(qs);
+ }
+ }
+ }
+
+ /* all the overloaded function templates are added into a linked list */
+ if (!linkliststart)
+ linkliststart = templnode;
+ if (nscope_inner) {
+ /* non-global namespace */
+ if (templnode) {
+ appendChild(nscope_inner,templnode);
+ Delete(templnode);
+ if (nscope) $$ = nscope;
+ }
+ } else {
+ /* global namespace */
+ if (!linklistend) {
+ $$ = templnode;
+ } else {
+ set_nextSibling(linklistend,templnode);
+ Delete(templnode);
+ }
+ linklistend = templnode;
+ }
+ }
+ nn = Getattr(nn,"sym:nextSibling"); /* repeat for overloaded function templates. If a class template there will never be a sibling. */
+ }
+ update_defaultargs(linkliststart);
+ update_abstracts(linkliststart);
+ }
+ Swig_symbol_setscope(tscope);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ Delete(symname);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ %warn "text"
+ ------------------------------------------------------------ */
+
+warn_directive : WARN string {
+ Swig_warning(0,cparse_file, cparse_line,"%s\n", $string);
+ $$ = 0;
+ }
+ ;
+
+/* ======================================================================
+ * C Parsing
+ * ====================================================================== */
+
+c_declaration : c_decl {
+ $$ = $c_decl;
+ if ($$) {
+ add_symbols($$);
+ default_arguments($$);
+ }
+ }
+ | c_enum_decl
+ | c_enum_forward_decl
+
+/* An extern C type declaration, disable cparse_cplusplus if needed. */
+
+ | EXTERN string LBRACE {
+ if (Strcmp($string,"C") == 0) {
+ cparse_externc = 1;
+ }
+ } interface RBRACE {
+ cparse_externc = 0;
+ if (Strcmp($string,"C") == 0) {
+ Node *n = firstChild($interface);
+ $$ = new_node("extern");
+ Setattr($$,"name",$string);
+ appendChild($$,n);
+ while (n) {
+ String *s = Getattr(n, "storage");
+ if (s) {
+ if (Strstr(s, "thread_local")) {
+ Insert(s,0,"externc ");
+ } else if (!Equal(s, "typedef")) {
+ Setattr(n,"storage","externc");
+ }
+ } else {
+ Setattr(n,"storage","externc");
+ }
+ n = nextSibling(n);
+ }
+ } else {
+ if (!Equal($string,"C++")) {
+ Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $string);
+ }
+ $$ = new_node("extern");
+ Setattr($$,"name",$string);
+ appendChild($$,firstChild($interface));
+ }
+ }
+ | cpp_lambda_decl {
+ $$ = $cpp_lambda_decl;
+ SWIG_WARN_NODE_BEGIN($$);
+ Swig_warning(WARN_CPP11_LAMBDA, cparse_file, cparse_line, "Lambda expressions and closures are not fully supported yet.\n");
+ SWIG_WARN_NODE_END($$);
+ }
+ | USING idcolon EQUAL type plain_declarator SEMI {
+ /* Convert using statement to a typedef statement */
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"storage","typedef");
+ Setattr($$,"name",$idcolon);
+ Setattr($$,"decl",$plain_declarator.type);
+ SetFlag($$,"typealias");
+ add_symbols($$);
+ }
+ | TEMPLATE LESSTHAN template_parms GREATERTHAN USING idcolon EQUAL type plain_declarator SEMI {
+ /* Convert alias template to a "template" typedef statement */
+ $$ = new_node("template");
+ Setattr($$,"type",$type);
+ Setattr($$,"storage","typedef");
+ Setattr($$,"name",$idcolon);
+ Setattr($$,"decl",$plain_declarator.type);
+ Setattr($$,"templateparms",$template_parms);
+ Setattr($$,"templatetype","cdecl");
+ SetFlag($$,"aliastemplate");
+ add_symbols($$);
+ }
+ | cpp_static_assert
+ ;
+
+/* ------------------------------------------------------------
+ A C global declaration of some kind (may be variable, function, typedef, etc.)
+ ------------------------------------------------------------ */
+
+c_decl : storage_class type declarator cpp_const initializer c_decl_tail {
+ String *decl = $declarator.type;
+ $$ = new_node("cdecl");
+ if ($cpp_const.qualifier)
+ decl = add_qualifier_to_declarator($declarator.type, $cpp_const.qualifier);
+ Setattr($$,"refqualifier",$cpp_const.refqualifier);
+ Setattr($$,"type",$type);
+ Setattr($$,"storage",$storage_class);
+ Setattr($$,"name",$declarator.id);
+ Setattr($$,"decl",decl);
+ Setattr($$,"parms",$declarator.parms);
+ Setattr($$,"value",$initializer.val);
+ if ($initializer.stringval) Setattr($$, "stringval", $initializer.stringval);
+ if ($initializer.numval) Setattr($$, "numval", $initializer.numval);
+ Setattr($$,"throws",$cpp_const.throws);
+ Setattr($$,"throw",$cpp_const.throwf);
+ Setattr($$,"noexcept",$cpp_const.nexcept);
+ Setattr($$,"final",$cpp_const.final);
+ if ($initializer.val && $initializer.type) {
+ /* store initializer type as it might be different to the declared type */
+ SwigType *valuetype = NewSwigType($initializer.type);
+ if (Len(valuetype) > 0) {
+ Setattr($$, "valuetype", valuetype);
+ } else {
+ /* If we can't determine the initializer type use the declared type. */
+ Setattr($$, "valuetype", $type);
+ }
+ Delete(valuetype);
+ }
+ if (!$c_decl_tail) {
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr($$,"code",code);
+ Delete(code);
+ }
+ } else {
+ Node *n = $c_decl_tail;
+ /* Inherit attributes */
+ while (n) {
+ String *type = Copy($type);
+ Setattr(n,"type",type);
+ Setattr(n,"storage",$storage_class);
+ n = nextSibling(n);
+ Delete(type);
+ }
+ }
+ if ($initializer.bitfield) {
+ Setattr($$,"bitfield", $initializer.bitfield);
+ }
+
+ if ($declarator.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($declarator.id);
+ if (p) {
+ /* This is a special case. If the scope name of the declaration exactly
+ matches that of the declaration, then we will allow it. Otherwise, delete. */
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($declarator.id);
+ Setattr($$, "name", lstr);
+ Delete(lstr);
+ set_nextSibling($$, $c_decl_tail);
+ } else {
+ Delete($$);
+ $$ = $c_decl_tail;
+ }
+ Delete(p);
+ } else if (Strncmp($declarator.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = $c_decl_tail;
+ } else {
+ set_nextSibling($$, $c_decl_tail);
+ }
+ } else {
+ Swig_error(cparse_file, cparse_line, "Missing symbol name for global declaration\n");
+ $$ = 0;
+ }
+
+ if ($cpp_const.qualifier && $storage_class && Strstr($storage_class, "static"))
+ Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
+ Delete($storage_class);
+ }
+ | storage_class type declarator cpp_const EQUAL error SEMI {
+ String *decl = $declarator.type;
+ $$ = new_node("cdecl");
+ if ($cpp_const.qualifier)
+ decl = add_qualifier_to_declarator($declarator.type, $cpp_const.qualifier);
+ Setattr($$, "refqualifier", $cpp_const.refqualifier);
+ Setattr($$, "type", $type);
+ Setattr($$, "storage", $storage_class);
+ Setattr($$, "name", $declarator.id);
+ Setattr($$, "decl", decl);
+ Setattr($$, "parms", $declarator.parms);
+
+ /* Set dummy value to avoid adding in code for handling missing value in later stages */
+ Setattr($$, "value", "*parse error*");
+ SetFlag($$, "valueignored");
+
+ Setattr($$, "throws", $cpp_const.throws);
+ Setattr($$, "throw", $cpp_const.throwf);
+ Setattr($$, "noexcept", $cpp_const.nexcept);
+ Setattr($$, "final", $cpp_const.final);
+
+ if ($declarator.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($declarator.id);
+ if (p) {
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($declarator.id);
+ Setattr($$, "name", lstr);
+ Delete(lstr);
+ } else {
+ Delete($$);
+ $$ = 0;
+ }
+ Delete(p);
+ } else if (Strncmp($declarator.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = 0;
+ }
+ }
+
+ if ($cpp_const.qualifier && $storage_class && Strstr($storage_class, "static"))
+ Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
+ Delete($storage_class);
+ }
+ /* Alternate function syntax introduced in C++11:
+ auto funcName(int x, int y) -> int; */
+ | storage_class AUTO declarator cpp_const ARROW cpp_alternate_rettype virt_specifier_seq_opt initializer c_decl_tail {
+ $$ = new_node("cdecl");
+ if ($cpp_const.qualifier) SwigType_push($declarator.type, $cpp_const.qualifier);
+ Setattr($$,"refqualifier",$cpp_const.refqualifier);
+ Setattr($$,"type",$cpp_alternate_rettype);
+ Setattr($$,"storage",$storage_class);
+ Setattr($$,"name",$declarator.id);
+ Setattr($$,"decl",$declarator.type);
+ Setattr($$,"parms",$declarator.parms);
+ Setattr($$,"throws",$cpp_const.throws);
+ Setattr($$,"throw",$cpp_const.throwf);
+ Setattr($$,"noexcept",$cpp_const.nexcept);
+ Setattr($$,"final",$cpp_const.final);
+ if (!$c_decl_tail) {
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr($$,"code",code);
+ Delete(code);
+ }
+ } else {
+ Node *n = $c_decl_tail;
+ while (n) {
+ String *type = Copy($cpp_alternate_rettype);
+ Setattr(n,"type",type);
+ Setattr(n,"storage",$storage_class);
+ n = nextSibling(n);
+ Delete(type);
+ }
+ }
+
+ if ($declarator.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($declarator.id);
+ if (p) {
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($declarator.id);
+ Setattr($$,"name",lstr);
+ Delete(lstr);
+ set_nextSibling($$, $c_decl_tail);
+ } else {
+ Delete($$);
+ $$ = $c_decl_tail;
+ }
+ Delete(p);
+ } else if (Strncmp($declarator.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = $c_decl_tail;
+ }
+ } else {
+ set_nextSibling($$, $c_decl_tail);
+ }
+
+ if ($cpp_const.qualifier && $storage_class && Strstr($storage_class, "static"))
+ Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
+ Delete($storage_class);
+ }
+ /* C++14 allows the trailing return type to be omitted. It's
+ * probably not feasible for SWIG to deduce it but we should
+ * at least support parsing this so that the rest of an API
+ * can be wrapped. This also means you can provide declaration
+ * with an explicit return type in the interface file for SWIG
+ * to wrap.
+ */
+ | storage_class AUTO declarator cpp_const LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+
+ $$ = new_node("cdecl");
+ if ($cpp_const.qualifier) SwigType_push($declarator.type, $cpp_const.qualifier);
+ Setattr($$, "refqualifier", $cpp_const.refqualifier);
+ Setattr($$, "type", NewString("auto"));
+ Setattr($$, "storage", $storage_class);
+ Setattr($$, "name", $declarator.id);
+ Setattr($$, "decl", $declarator.type);
+ Setattr($$, "parms", $declarator.parms);
+ Setattr($$, "throws", $cpp_const.throws);
+ Setattr($$, "throw", $cpp_const.throwf);
+ Setattr($$, "noexcept", $cpp_const.nexcept);
+ Setattr($$, "final", $cpp_const.final);
+
+ if ($declarator.id) {
+ /* Ignore all scoped declarations, could be 1. out of class function definition 2. friend function declaration 3. ... */
+ String *p = Swig_scopename_prefix($declarator.id);
+ if (p) {
+ if ((Namespaceprefix && Strcmp(p, Namespaceprefix) == 0) ||
+ (Classprefix && Strcmp(p, Classprefix) == 0)) {
+ String *lstr = Swig_scopename_last($declarator.id);
+ Setattr($$, "name", lstr);
+ Delete(lstr);
+ } else {
+ Delete($$);
+ $$ = 0;
+ }
+ Delete(p);
+ } else if (Strncmp($declarator.id, "::", 2) == 0) {
+ /* global scope declaration/definition ignored */
+ Delete($$);
+ $$ = 0;
+ }
+ }
+
+ if ($cpp_const.qualifier && $storage_class && Strstr($storage_class, "static"))
+ Swig_error(cparse_file, cparse_line, "Static function %s cannot have a qualifier.\n", Swig_name_decl($$));
+ Delete($storage_class);
+ }
+ /* C++11 auto variable declaration. */
+ | storage_class AUTO idcolon EQUAL definetype SEMI {
+ SwigType *type = deduce_type(&$definetype);
+ if (!type)
+ type = NewString("auto");
+ $$ = new_node("cdecl");
+ Setattr($$, "type", type);
+ Setattr($$, "storage", $storage_class);
+ Setattr($$, "name", $idcolon);
+ Setattr($$, "decl", NewStringEmpty());
+ Setattr($$, "value", $definetype.val);
+ if ($definetype.stringval) Setattr($$, "stringval", $definetype.stringval);
+ if ($definetype.numval) Setattr($$, "numval", $definetype.numval);
+ Setattr($$, "valuetype", type);
+ Delete($storage_class);
+ Delete(type);
+ }
+ /* C++11 auto variable declaration for which we can't parse the initialiser. */
+ | storage_class AUTO idcolon EQUAL error SEMI {
+ SwigType *type = NewString("auto");
+ $$ = new_node("cdecl");
+ Setattr($$, "type", type);
+ Setattr($$, "storage", $storage_class);
+ Setattr($$, "name", $idcolon);
+ Setattr($$, "decl", NewStringEmpty());
+ Setattr($$, "valuetype", type);
+ Delete($storage_class);
+ Delete(type);
+ }
+ ;
+
+/* Allow lists of variables and functions to be built up */
+
+c_decl_tail : SEMI {
+ $$ = 0;
+ Clear(scanner_ccode);
+ }
+ | COMMA declarator cpp_const initializer c_decl_tail[in] {
+ $$ = new_node("cdecl");
+ if ($cpp_const.qualifier) SwigType_push($declarator.type,$cpp_const.qualifier);
+ Setattr($$,"refqualifier",$cpp_const.refqualifier);
+ Setattr($$,"name",$declarator.id);
+ Setattr($$,"decl",$declarator.type);
+ Setattr($$,"parms",$declarator.parms);
+ Setattr($$,"value",$initializer.val);
+ if ($initializer.stringval) Setattr($$, "stringval", $initializer.stringval);
+ if ($initializer.numval) Setattr($$, "numval", $initializer.numval);
+ Setattr($$,"throws",$cpp_const.throws);
+ Setattr($$,"throw",$cpp_const.throwf);
+ Setattr($$,"noexcept",$cpp_const.nexcept);
+ Setattr($$,"final",$cpp_const.final);
+ if ($initializer.bitfield) {
+ Setattr($$,"bitfield", $initializer.bitfield);
+ }
+ if (!$in) {
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr($$,"code",code);
+ Delete(code);
+ }
+ } else {
+ set_nextSibling($$, $in);
+ }
+ }
+ | LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = 0;
+ }
+ | error {
+ $$ = 0;
+ if (yychar == RPAREN) {
+ Swig_error(cparse_file, cparse_line, "Unexpected closing parenthesis (')').\n");
+ } else {
+ Swig_error(cparse_file, cparse_line, "Syntax error - possibly a missing semicolon (';').\n");
+ }
+ Exit(EXIT_FAILURE);
+ }
+ ;
+
+initializer : def_args
+ | COLON expr {
+ $$ = default_dtype;
+ $$.bitfield = $expr.val;
+ }
+ ;
+
+cpp_alternate_rettype : primitive_type
+ | TYPE_BOOL
+ | TYPE_VOID
+ | c_enum_key idcolon {
+ $$ = $idcolon;
+ Insert($$, 0, "enum ");
+ }
+ | TYPE_RAW
+ | idcolon { $$ = $idcolon; }
+ | idcolon AND {
+ $$ = $idcolon;
+ SwigType_add_reference($$);
+ }
+ | idcolon LAND {
+ $$ = $idcolon;
+ SwigType_add_rvalue_reference($$);
+ }
+ | CONST_QUAL idcolon AND {
+ $$ = $idcolon;
+ SwigType_add_qualifier($$, "const");
+ SwigType_add_reference($$);
+ }
+ | CONST_QUAL idcolon LAND {
+ $$ = $idcolon;
+ SwigType_add_qualifier($$, "const");
+ SwigType_add_rvalue_reference($$);
+ }
+ | decltype
+ ;
+
+/* ------------------------------------------------------------
+ Lambda functions and expressions, such as:
+ auto myFunc = [] { return something; };
+ auto myFunc = [](int x, int y) { return x+y; };
+ auto myFunc = [](int x, int y) -> int { return x+y; };
+ auto myFunc = [](int x, int y) throw() -> int { return x+y; };
+ auto six = [](int x, int y) { return x+y; }(4, 2);
+ ------------------------------------------------------------ */
+cpp_lambda_decl : storage_class AUTO idcolon EQUAL lambda_introducer lambda_template LPAREN parms RPAREN cpp_const lambda_body lambda_tail {
+ $$ = new_node("lambda");
+ Setattr($$,"name",$idcolon);
+ Delete($storage_class);
+ add_symbols($$);
+ }
+ | storage_class AUTO idcolon EQUAL lambda_introducer lambda_template LPAREN parms RPAREN cpp_const ARROW type lambda_body lambda_tail {
+ $$ = new_node("lambda");
+ Setattr($$,"name",$idcolon);
+ Delete($storage_class);
+ add_symbols($$);
+ }
+ | storage_class AUTO idcolon EQUAL lambda_introducer lambda_template lambda_body lambda_tail {
+ $$ = new_node("lambda");
+ Setattr($$,"name",$idcolon);
+ Delete($storage_class);
+ add_symbols($$);
+ }
+ ;
+
+lambda_introducer : LBRACKET {
+ if (skip_balanced('[',']') < 0) Exit(EXIT_FAILURE);
+ }
+ ;
+
+lambda_template : LESSTHAN {
+ if (skip_balanced('<','>') < 0) Exit(EXIT_FAILURE);
+ }
+ | %empty
+ ;
+
+lambda_body : LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ }
+
+lambda_tail : SEMI
+ | LPAREN {
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
+ } SEMI {
+ }
+ ;
+
+/* ------------------------------------------------------------
+ enum
+ or
+ enum class
+ ------------------------------------------------------------ */
+
+c_enum_key : ENUM {
+ $$ = "enum";
+ }
+ | ENUM CLASS {
+ $$ = "enum class";
+ }
+ | ENUM STRUCT {
+ $$ = "enum struct";
+ }
+ ;
+
+/* ------------------------------------------------------------
+ base enum type (eg. unsigned short)
+ ------------------------------------------------------------ */
+
+c_enum_inherit : COLON type_right {
+ $$ = $type_right;
+ }
+ | %empty { $$ = 0; }
+ ;
+/* ------------------------------------------------------------
+ enum [class] Name;
+ enum [class] Name [: base_type];
+ ------------------------------------------------------------ */
+
+c_enum_forward_decl : storage_class c_enum_key ename c_enum_inherit SEMI {
+ SwigType *ty = 0;
+ int scopedenum = $ename && !Equal($c_enum_key, "enum");
+ $$ = new_node("enumforward");
+ ty = NewStringf("enum %s", $ename);
+ Setattr($$,"enumkey",$c_enum_key);
+ if (scopedenum)
+ SetFlag($$, "scopedenum");
+ Setattr($$,"name",$ename);
+ Setattr($$, "enumbase", $c_enum_inherit);
+ Setattr($$,"type",ty);
+ Setattr($$,"sym:weak", "1");
+ Delete($storage_class);
+ add_symbols($$);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ enum [class] Name [: base_type] { ... };
+ or
+ enum [class] Name [: base_type] { ... } MyEnum [= ...];
+ * ------------------------------------------------------------ */
+
+c_enum_decl : storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBRACE SEMI {
+ SwigType *ty = 0;
+ int scopedenum = $ename && !Equal($c_enum_key, "enum");
+ $$ = new_enum_node($c_enum_inherit);
+ ty = NewStringf("enum %s", $ename);
+ Setattr($$,"enumkey",$c_enum_key);
+ if (scopedenum)
+ SetFlag($$, "scopedenum");
+ Setattr($$,"name",$ename);
+ Setattr($$,"type",ty);
+ appendChild($$,$enumlist);
+ add_symbols($$); /* Add to tag space */
+
+ if (scopedenum) {
+ Swig_symbol_newscope();
+ Swig_symbol_setscopename($ename);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+
+ add_symbols($enumlist); /* Add enum values to appropriate enum or enum class scope */
+
+ if (scopedenum) {
+ Setattr($$,"symtab", Swig_symbol_popscope());
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+ Delete($storage_class);
+ }
+ | storage_class c_enum_key ename c_enum_inherit LBRACE enumlist RBRACE declarator cpp_const initializer c_decl_tail {
+ Node *n;
+ SwigType *ty = 0;
+ String *unnamed = 0;
+ int unnamedinstance = 0;
+ int scopedenum = $ename && !Equal($c_enum_key, "enum");
+
+ $$ = new_enum_node($c_enum_inherit);
+ Setattr($$,"enumkey",$c_enum_key);
+ if (scopedenum)
+ SetFlag($$, "scopedenum");
+ if ($ename) {
+ Setattr($$,"name",$ename);
+ ty = NewStringf("enum %s", $ename);
+ } else if ($declarator.id) {
+ unnamed = make_unnamed();
+ ty = NewStringf("enum %s", unnamed);
+ Setattr($$,"unnamed",unnamed);
+ /* name is not set for unnamed enum instances, e.g. enum { foo } Instance; */
+ if ($storage_class && Cmp($storage_class,"typedef") == 0) {
+ Setattr($$,"name",$declarator.id);
+ } else {
+ unnamedinstance = 1;
+ }
+ Setattr($$,"storage",$storage_class);
+ }
+ if ($declarator.id && Cmp($storage_class,"typedef") == 0) {
+ Setattr($$,"tdname",$declarator.id);
+ Setattr($$,"allows_typedef","1");
+ }
+ appendChild($$,$enumlist);
+ n = new_node("cdecl");
+ Setattr(n,"type",ty);
+ Setattr(n,"name",$declarator.id);
+ Setattr(n,"storage",$storage_class);
+ Setattr(n,"decl",$declarator.type);
+ Setattr(n,"parms",$declarator.parms);
+ Setattr(n,"unnamed",unnamed);
+
+ if (unnamedinstance) {
+ SwigType *cty = NewString("enum ");
+ Setattr($$,"type",cty);
+ SetFlag($$,"unnamedinstance");
+ SetFlag(n,"unnamedinstance");
+ Delete(cty);
+ }
+ if ($c_decl_tail) {
+ Node *p = $c_decl_tail;
+ set_nextSibling(n,p);
+ while (p) {
+ SwigType *cty = Copy(ty);
+ Setattr(p,"type",cty);
+ Setattr(p,"unnamed",unnamed);
+ Setattr(p,"storage",$storage_class);
+ Delete(cty);
+ p = nextSibling(p);
+ }
+ } else {
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr(n,"code",code);
+ Delete(code);
+ }
+ }
+
+ /* Ensure that typedef enum ABC {foo} XYZ; uses XYZ for sym:name, like structs.
+ * Note that class_rename/yyrename are bit of a mess so used this simple approach to change the name. */
+ if ($declarator.id && $ename && Cmp($storage_class,"typedef") == 0) {
+ String *name = NewString($declarator.id);
+ Setattr($$, "parser:makename", name);
+ Delete(name);
+ }
+
+ add_symbols($$); /* Add enum to tag space */
+ set_nextSibling($$,n);
+ Delete(n);
+
+ if (scopedenum) {
+ Swig_symbol_newscope();
+ Swig_symbol_setscopename($ename);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+
+ add_symbols($enumlist); /* Add enum values to appropriate enum or enum class scope */
+
+ if (scopedenum) {
+ Setattr($$,"symtab", Swig_symbol_popscope());
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+
+ add_symbols(n);
+ Delete($storage_class);
+ Delete(unnamed);
+ }
+ ;
+
+c_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
+ /* This is a sick hack. If the ctor_end has parameters,
+ and the parms parameter only has 1 parameter, this
+ could be a declaration of the form:
+
+ type (id)(parms)
+
+ Otherwise it's an error. */
+ int err = 0;
+ $$ = 0;
+
+ if ((ParmList_len($parms) == 1) && (!Swig_scopename_check($type))) {
+ SwigType *ty = Getattr($parms,"type");
+ String *name = Getattr($parms,"name");
+ err = 1;
+ if (!name) {
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"storage",$storage_class);
+ Setattr($$,"name",ty);
+
+ if ($ctor_end.have_parms) {
+ SwigType *decl = NewStringEmpty();
+ SwigType_add_function(decl,$ctor_end.parms);
+ Setattr($$,"decl",decl);
+ Setattr($$,"parms",$ctor_end.parms);
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr($$,"code",code);
+ Delete(code);
+ }
+ }
+ if ($ctor_end.defarg)
+ Setattr($$, "value", $ctor_end.defarg);
+ if ($ctor_end.stringdefarg)
+ Setattr($$, "stringval", $ctor_end.stringdefarg);
+ if ($ctor_end.numdefarg)
+ Setattr($$, "numval", $ctor_end.numdefarg);
+ Setattr($$,"throws",$ctor_end.throws);
+ Setattr($$,"throw",$ctor_end.throwf);
+ Setattr($$,"noexcept",$ctor_end.nexcept);
+ Setattr($$,"final",$ctor_end.final);
+ err = 0;
+ }
+ }
+ Delete($storage_class);
+ if (err) {
+ Swig_error(cparse_file,cparse_line,"Syntax error in input(2).\n");
+ Exit(EXIT_FAILURE);
+ }
+ }
+ ;
+
+/* ======================================================================
+ * C++ Support
+ * ====================================================================== */
+
+cpp_declaration : cpp_class_decl
+ | cpp_forward_class_decl
+ | cpp_template_decl
+ | cpp_using_decl
+ | cpp_namespace_decl
+ | cpp_catch_decl
+ ;
+
+
+/* A simple class/struct/union definition */
+
+/* Note that class_virt_specifier_opt for supporting final classes introduces one shift-reduce conflict
+ with C style variable declarations, such as: struct X final; */
+
+cpp_class_decl: storage_class cpptype idcolon class_virt_specifier_opt inherit LBRACE <node>{
+ String *prefix;
+ List *bases = 0;
+ Node *scope = 0;
+ int errored_flag = 0;
+ String *code;
+ $$ = new_node("class");
+ Setattr($$,"kind",$cpptype);
+ if ($inherit) {
+ Setattr($$,"baselist", Getattr($inherit,"public"));
+ Setattr($$,"protectedbaselist", Getattr($inherit,"protected"));
+ Setattr($$,"privatebaselist", Getattr($inherit,"private"));
+ }
+ Setattr($$,"allows_typedef","1");
+
+ /* Temporary unofficial symtab for use until add_symbols() adds "sym:symtab" */
+ Setattr($$, "unofficial:symtab", Swig_symbol_current());
+
+ /* If the class name is qualified. We need to create or lookup namespace/scope entries */
+ scope = resolve_create_node_scope($idcolon, 1, &errored_flag);
+ /* save nscope_inner to the class - it may be overwritten in nested classes*/
+ Setattr($$, "nested:innerscope", nscope_inner);
+ Setattr($$, "nested:nscope", nscope);
+ Setfile(scope,cparse_file);
+ Setline(scope,cparse_line);
+ Setattr($$, "name", scope);
+
+ if (currentOuterClass) {
+ SetFlag($$, "nested");
+ Setattr($$, "nested:outer", currentOuterClass);
+ set_access_mode($$);
+ }
+ Swig_features_get(Swig_cparse_features(), Namespaceprefix, Getattr($$, "name"), 0, $$);
+ /* save yyrename to the class attribute, to be used later in add_symbols()*/
+ Setattr($$, "class_rename", make_name($$, scope, 0));
+ Setattr($$, "Classprefix", scope);
+ Classprefix = NewString(scope);
+ /* Deal with inheritance */
+ if ($inherit)
+ bases = Swig_make_inherit_list(scope, Getattr($inherit, "public"), Namespaceprefix);
+ prefix = SwigType_istemplate_templateprefix(scope);
+ if (prefix) {
+ String *fbase, *tbase;
+ if (Namespaceprefix) {
+ fbase = NewStringf("%s::%s", Namespaceprefix, scope);
+ tbase = NewStringf("%s::%s", Namespaceprefix, prefix);
+ } else {
+ fbase = Copy(scope);
+ tbase = Copy(prefix);
+ }
+ Swig_name_inherit(tbase,fbase);
+ Delete(fbase);
+ Delete(tbase);
+ }
+ if (Strcmp($cpptype, "class") == 0) {
+ cplus_mode = CPLUS_PRIVATE;
+ } else {
+ cplus_mode = CPLUS_PUBLIC;
+ }
+ if (!cparse_cplusplus) {
+ set_scope_to_global();
+ }
+ Swig_symbol_newscope();
+ Swig_symbol_setscopename(scope);
+ Swig_inherit_base_symbols(bases);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ cparse_start_line = cparse_line;
+
+ /* If there are active template parameters, we need to make sure they are
+ placed in the class symbol table so we can catch shadows */
+
+ if (template_parameters) {
+ Parm *tp = template_parameters;
+ while(tp) {
+ String *tpname = Copy(Getattr(tp,"name"));
+ Node *tn = new_node("templateparm");
+ Setattr(tn,"name",tpname);
+ Swig_symbol_cadd(tpname,tn);
+ tp = nextSibling(tp);
+ Delete(tpname);
+ }
+ }
+ Delete(prefix);
+ inclass = 1;
+ currentOuterClass = $$;
+ if (cparse_cplusplusout) {
+ /* save the structure declaration to declare it in global scope for C++ to see */
+ code = get_raw_text_balanced('{', '}');
+ Setattr($$, "code", code);
+ Delete(code);
+ }
+ }[node] cpp_members RBRACE cpp_opt_declarators {
+ Node *p;
+ SwigType *ty;
+ Symtab *cscope;
+ Node *am = 0;
+ String *scpname = 0;
+ $$ = currentOuterClass;
+ currentOuterClass = Getattr($$, "nested:outer");
+ nscope_inner = Getattr($$, "nested:innerscope");
+ nscope = Getattr($$, "nested:nscope");
+ Delattr($$, "nested:innerscope");
+ Delattr($$, "nested:nscope");
+ if (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0) { /* actual parent class for this class */
+ Node* forward_declaration = Swig_symbol_clookup_no_inherit(Getattr($$,"name"), Getattr(nscope_inner, "symtab"));
+ if (forward_declaration) {
+ Setattr($$, "access", Getattr(forward_declaration, "access"));
+ }
+ Setattr($$, "nested:outer", nscope_inner);
+ SetFlag($$, "nested");
+ }
+ if (!currentOuterClass)
+ inclass = 0;
+ cscope = Getattr($$, "unofficial:symtab");
+ Delattr($$, "unofficial:symtab");
+
+ /* Check for pure-abstract class */
+ Setattr($$,"abstracts", pure_abstracts($cpp_members));
+
+ /* This bit of code merges in a previously defined %extend directive (if any) */
+ {
+ String *clsname = Swig_symbol_qualifiedscopename(0);
+ am = Getattr(Swig_extend_hash(), clsname);
+ if (am) {
+ Swig_extend_merge($$, am);
+ Delattr(Swig_extend_hash(), clsname);
+ }
+ Delete(clsname);
+ }
+ if (!classes) classes = NewHash();
+ scpname = Swig_symbol_qualifiedscopename(0);
+ Setattr(classes, scpname, $$);
+
+ appendChild($$, $cpp_members);
+
+ if (am)
+ Swig_extend_append_previous($$, am);
+
+ p = $cpp_opt_declarators;
+ if (p && !nscope_inner) {
+ if (!cparse_cplusplus && currentOuterClass)
+ appendChild(currentOuterClass, p);
+ else
+ appendSibling($$, p);
+ }
+
+ 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(Getattr($node, "name"));
+ } else {
+ ty = NewStringf("%s %s", $cpptype, Getattr($node, "name"));
+ }
+ while (p) {
+ Setattr(p, "storage", $storage_class);
+ Setattr(p, "type" ,ty);
+ if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) {
+ SetFlag(p, "hasconsttype");
+ }
+ p = nextSibling(p);
+ }
+ if ($cpp_opt_declarators && Cmp($storage_class,"typedef") == 0)
+ add_typedef_name($$, $cpp_opt_declarators, Getattr($node, "name"), 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");
+ cplus_mode = CPLUS_PUBLIC;
+ appendChild($$, pa);
+ Delete(pa);
+ }
+ if (currentOuterClass)
+ restore_access_mode($$);
+ Setattr($$, "symtab", Swig_symbol_popscope());
+ Classprefix = Getattr($$, "Classprefix");
+ Delattr($$, "Classprefix");
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ if (cplus_mode == CPLUS_PRIVATE) {
+ $$ = 0; /* skip private nested classes */
+ } else if (cparse_cplusplus && currentOuterClass && ignore_nested_classes && !GetFlag($$, "feature:flatnested")) {
+ $$ = nested_forward_declaration($storage_class, $cpptype, Getattr($node, "name"), Copy(Getattr($node, "name")), $cpp_opt_declarators);
+ } else if (nscope_inner) {
+ /* this is tricky */
+ /* we add the declaration in the original namespace */
+ if (Strcmp(nodeType(nscope_inner), "class") == 0 && cparse_cplusplus && ignore_nested_classes && !GetFlag($$, "feature:flatnested"))
+ $$ = nested_forward_declaration($storage_class, $cpptype, Getattr($node, "name"), Copy(Getattr($node, "name")), $cpp_opt_declarators);
+ appendChild(nscope_inner, $$);
+ Swig_symbol_setscope(Getattr(nscope_inner, "symtab"));
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ yyrename = Copy(Getattr($$, "class_rename"));
+ add_symbols($$);
+ Delattr($$, "class_rename");
+ /* but the variable definition in the current scope */
+ Swig_symbol_setscope(cscope);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ add_symbols($cpp_opt_declarators);
+ if (nscope) {
+ $$ = nscope; /* here we return recreated namespace tower instead of the class itself */
+ if ($cpp_opt_declarators) {
+ appendSibling($$, $cpp_opt_declarators);
+ }
+ } else if (!SwigType_istemplate(ty) && template_parameters == 0) { /* for template we need the class itself */
+ $$ = $cpp_opt_declarators;
+ }
+ } else {
+ Delete(yyrename);
+ yyrename = 0;
+ 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, $$);
+ Swig_symbol_setscope(cscope); /* declaration goes in the parent scope */
+ add_symbols($cpp_opt_declarators);
+ set_scope_to_global();
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ yyrename = Copy(Getattr($$, "class_rename"));
+ add_symbols($$);
+ if (!cparse_cplusplusout)
+ Delattr($$, "nested:outer");
+ Delattr($$, "class_rename");
+ $$ = 0;
+ } else {
+ yyrename = Copy(Getattr($$, "class_rename"));
+ add_symbols($$);
+ add_symbols($cpp_opt_declarators);
+ Delattr($$, "class_rename");
+ }
+ }
+ Delete(ty);
+ Swig_symbol_setscope(cscope);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ Classprefix = currentOuterClass ? Getattr(currentOuterClass, "Classprefix") : 0;
+ Delete($storage_class);
+ }
+
+/* An unnamed struct, possibly with a typedef */
+
+ | storage_class cpptype inherit LBRACE <node>{
+ String *unnamed;
+ String *code;
+ unnamed = make_unnamed();
+ $$ = new_node("class");
+ Setattr($$,"kind",$cpptype);
+ if ($inherit) {
+ Setattr($$,"baselist", Getattr($inherit,"public"));
+ Setattr($$,"protectedbaselist", Getattr($inherit,"protected"));
+ Setattr($$,"privatebaselist", Getattr($inherit,"private"));
+ }
+ Setattr($$,"storage",$storage_class);
+ Setattr($$,"unnamed",unnamed);
+ Setattr($$,"allows_typedef","1");
+
+ /* Temporary unofficial symtab for use until add_symbols() adds "sym:symtab" */
+ Setattr($$, "unofficial:symtab", Swig_symbol_current());
+
+ if (currentOuterClass) {
+ SetFlag($$, "nested");
+ Setattr($$, "nested:outer", currentOuterClass);
+ set_access_mode($$);
+ }
+ Swig_features_get(Swig_cparse_features(), Namespaceprefix, 0, 0, $$);
+ /* save yyrename to the class attribute, to be used later in add_symbols()*/
+ Setattr($$, "class_rename", make_name($$,0,0));
+ if (Strcmp($cpptype, "class") == 0) {
+ cplus_mode = CPLUS_PRIVATE;
+ } else {
+ cplus_mode = CPLUS_PUBLIC;
+ }
+ Swig_symbol_newscope();
+ cparse_start_line = cparse_line;
+ currentOuterClass = $$;
+ inclass = 1;
+ Classprefix = 0;
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ /* save the structure declaration to make a typedef for it later*/
+ code = get_raw_text_balanced('{', '}');
+ Setattr($$, "code", code);
+ Delete(code);
+ }[node] cpp_members RBRACE cpp_opt_declarators {
+ String *unnamed;
+ List *bases = 0;
+ String *name = 0;
+ Node *n;
+ Symtab *cscope;
+ Classprefix = 0;
+ (void)$node;
+ $$ = currentOuterClass;
+ currentOuterClass = Getattr($$, "nested:outer");
+ if (!currentOuterClass)
+ inclass = 0;
+ else
+ restore_access_mode($$);
+
+ cscope = Getattr($$, "unofficial:symtab");
+ Delattr($$, "unofficial:symtab");
+
+ unnamed = Getattr($$,"unnamed");
+ /* Check for pure-abstract class */
+ Setattr($$,"abstracts", pure_abstracts($cpp_members));
+ n = $cpp_opt_declarators;
+ if (cparse_cplusplus && currentOuterClass && ignore_nested_classes && !GetFlag($$, "feature:flatnested")) {
+ String *name = n ? Copy(Getattr(n, "name")) : 0;
+ $$ = nested_forward_declaration($storage_class, $cpptype, 0, name, n);
+ } else if (n) {
+ appendSibling($$,n);
+ /* If a proper typedef name was given, we'll use it to set the scope name */
+ name = try_to_find_a_name_for_unnamed_structure($storage_class, n);
+ if (name) {
+ String *scpname = 0;
+ SwigType *ty;
+ Setattr($$,"tdname",name);
+ Setattr($$,"name",name);
+ Swig_symbol_setscopename(name);
+ if ($inherit)
+ bases = Swig_make_inherit_list(name,Getattr($inherit,"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);
+ if (cparse_cplusplus && !cparse_externc) {
+ ty = NewString(name);
+ } else {
+ ty = NewStringf("%s %s", $cpptype,name);
+ }
+ while (n) {
+ Setattr(n,"storage",$storage_class);
+ Setattr(n, "type", ty);
+ if (!cparse_cplusplus && currentOuterClass && (!Getattr(currentOuterClass, "name"))) {
+ SetFlag(n,"hasconsttype");
+ }
+ n = nextSibling(n);
+ }
+ n = $cpp_opt_declarators;
+
+ /* Check for previous extensions */
+ {
+ String *clsname = Swig_symbol_qualifiedscopename(0);
+ Node *am = Getattr(Swig_extend_hash(),clsname);
+ if (am) {
+ /* Merge the extension into the symbol table */
+ Swig_extend_merge($$,am);
+ Swig_extend_append_previous($$,am);
+ Delattr(Swig_extend_hash(),clsname);
+ }
+ 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", $storage_class);
+ n = nextSibling(n);
+ }
+ n = $cpp_opt_declarators;
+ Swig_symbol_setscopename("<unnamed>");
+ }
+ appendChild($$,$cpp_members);
+ /* Pop the scope */
+ Setattr($$,"symtab",Swig_symbol_popscope());
+ if (name) {
+ Delete(yyrename);
+ yyrename = Copy(Getattr($$, "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 without declarator*/
+ Swig_symbol_popscope();
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ add_symbols($cpp_members);
+ Delete($$);
+ $$ = $cpp_members; /* pass member list to outer class/namespace (instead of self)*/
+ }
+ Swig_symbol_setscope(cscope);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ Classprefix = currentOuterClass ? Getattr(currentOuterClass, "Classprefix") : 0;
+ Delete($storage_class);
+ }
+ ;
+
+cpp_opt_declarators : SEMI { $$ = 0; }
+ | declarator cpp_const initializer c_decl_tail {
+ $$ = new_node("cdecl");
+ Setattr($$,"name",$declarator.id);
+ Setattr($$,"decl",$declarator.type);
+ Setattr($$,"parms",$declarator.parms);
+ set_nextSibling($$, $c_decl_tail);
+ }
+ ;
+/* ------------------------------------------------------------
+ class Name;
+ ------------------------------------------------------------ */
+
+cpp_forward_class_decl : storage_class cpptype idcolon SEMI {
+ if ($storage_class && Strstr($storage_class, "friend")) {
+ /* Ignore */
+ $$ = 0;
+ } else {
+ $$ = new_node("classforward");
+ Setattr($$,"kind",$cpptype);
+ Setattr($$,"name",$idcolon);
+ Setattr($$,"sym:weak", "1");
+ add_symbols($$);
+ }
+ Delete($storage_class);
+ }
+ ;
+
+/* ------------------------------------------------------------
+ template<...> decl
+ ------------------------------------------------------------ */
+
+cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
+ if (currentOuterClass)
+ Setattr(currentOuterClass, "template_parameters", template_parameters);
+ template_parameters = $template_parms;
+ parsing_template_declaration = 1;
+ } cpp_template_possible {
+ String *tname = 0;
+ int error = 0;
+
+ /* check if we get a namespace node with a class declaration, and retrieve the class */
+ Symtab *cscope = Swig_symbol_current();
+ Symtab *sti = 0;
+ Node *ntop = $cpp_template_possible;
+ Node *ni = ntop;
+ SwigType *ntype = ni ? nodeType(ni) : 0;
+ while (ni && Strcmp(ntype,"namespace") == 0) {
+ sti = Getattr(ni,"symtab");
+ ni = firstChild(ni);
+ ntype = nodeType(ni);
+ }
+ if (sti) {
+ Swig_symbol_setscope(sti);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ $$ = ni;
+ } else {
+ $$ = $cpp_template_possible;
+ }
+
+ if ($$) tname = Getattr($$,"name");
+
+ /* Check if the class is a template specialization */
+ if (($$) && (Strchr(tname,'<')) && (!is_operator(tname))) {
+ /* If a specialization. Check if defined. */
+ Node *tempn = 0;
+ {
+ String *tbase = SwigType_templateprefix(tname);
+ tempn = Swig_symbol_clookup_local(tbase,0);
+ if (!tempn || (Strcmp(nodeType(tempn),"template") != 0)) {
+ SWIG_WARN_NODE_BEGIN(tempn);
+ Swig_warning(WARN_PARSE_TEMPLATE_SP_UNDEF, Getfile($$),Getline($$),"Specialization of non-template '%s'.\n", tbase);
+ SWIG_WARN_NODE_END(tempn);
+ tempn = 0;
+ error = 1;
+ }
+ Delete(tbase);
+ }
+ Setattr($$,"specialization","1");
+ Setattr($$,"templatetype",nodeType($$));
+ set_nodeType($$,"template");
+ /* Template partial specialization */
+ if (tempn && ($template_parms) && ($$)) {
+ ParmList *primary_templateparms = Getattr(tempn, "templateparms");
+ String *targs = SwigType_templateargs(tname); /* tname contains name and specialized template parameters, for example: X<(p.T,TT)> */
+ List *tlist = SwigType_parmlist(targs);
+ int specialization_parms_len = Len(tlist);
+ if (!Getattr($$,"sym:weak")) {
+ Setattr($$,"sym:typename","1");
+ }
+ Setattr($$, "primarytemplate", tempn);
+ Setattr($$, "templateparms", $template_parms);
+ Delattr($$, "specialization");
+ Setattr($$, "partialspecialization", "1");
+
+ if (specialization_parms_len > ParmList_len(primary_templateparms)) {
+ Swig_error(Getfile($$), Getline($$), "Template partial specialization has more arguments than primary template %d %d.\n", specialization_parms_len, ParmList_len(primary_templateparms));
+
+ } else if (specialization_parms_len < ParmList_numrequired(primary_templateparms)) {
+ Swig_error(Getfile($$), Getline($$), "Template partial specialization has fewer arguments than primary template %d %d.\n", specialization_parms_len, ParmList_len(primary_templateparms));
+ } else {
+ /* Create a specialized name with template parameters replaced with $ variables, such as, X<(T1,p.T2) => X<($1,p.$2)> */
+ Parm *p = $template_parms;
+ String *fname = NewString(tname);
+ String *ffname = 0;
+ ParmList *partialparms = 0;
+
+ char tmp[32];
+ int i = 0;
+ while (p) {
+ String *name = Getattr(p,"name");
+ ++i;
+ if (!name) {
+ p = nextSibling(p);
+ continue;
+ }
+ sprintf(tmp, "$%d", i);
+ Replaceid(fname, name, tmp);
+ p = nextSibling(p);
+ }
+ /* Patch argument names with typedef */
+ {
+ Iterator tt;
+ Parm *parm_current = 0;
+ List *tparms = SwigType_parmlist(fname);
+ ffname = SwigType_templateprefix(fname);
+ Append(ffname,"<(");
+ for (tt = First(tparms); tt.item; ) {
+ SwigType *rtt = Swig_symbol_typedef_reduce(tt.item,0);
+ SwigType *ttr = Swig_symbol_type_qualify(rtt,0);
+
+ Parm *newp = NewParmWithoutFileLineInfo(ttr, 0);
+ if (partialparms)
+ set_nextSibling(parm_current, newp);
+ else
+ partialparms = newp;
+ parm_current = newp;
+
+ Append(ffname,ttr);
+ tt = Next(tt);
+ if (tt.item) Putc(',',ffname);
+ Delete(rtt);
+ Delete(ttr);
+ }
+ Delete(tparms);
+ Append(ffname,")>");
+ }
+ {
+ /* Replace each primary template parameter's name and value with $ variables, such as, class Y,class T=Y => class $1,class $2=$1 */
+ ParmList *primary_templateparms_copy = CopyParmList(primary_templateparms);
+ p = primary_templateparms_copy;
+ i = 0;
+ while (p) {
+ String *name = Getattr(p, "name");
+ Parm *pp = nextSibling(p);
+ ++i;
+ sprintf(tmp, "$%d", i);
+ while (pp) {
+ Replaceid(Getattr(pp, "value"), name, tmp);
+ pp = nextSibling(pp);
+ }
+ Setattr(p, "name", NewString(tmp));
+ p = nextSibling(p);
+ }
+ /* Modify partialparms by adding in missing default values ($ variables) from primary template parameters */
+ partialparms = Swig_cparse_template_partialargs_expand(partialparms, tempn, primary_templateparms_copy);
+ Delete(primary_templateparms_copy);
+ }
+ {
+ Node *new_partial = NewHash();
+ String *partials = Getattr(tempn,"partials");
+ if (!partials) {
+ partials = NewList();
+ Setattr(tempn,"partials",partials);
+ Delete(partials);
+ }
+ /* Printf(stdout,"partial: fname = '%s', '%s'\n", fname, Swig_symbol_typedef_reduce(fname,0)); */
+ Setattr(new_partial, "partialparms", partialparms);
+ Setattr(new_partial, "templcsymname", ffname);
+ Append(partials, new_partial);
+ }
+ Setattr($$,"partialargs",ffname);
+ Swig_symbol_cadd(ffname,$$);
+ }
+ Delete(tlist);
+ Delete(targs);
+ } else {
+ /* An explicit template specialization */
+ /* add default args from primary (unspecialized) template */
+ String *ty = Swig_symbol_template_deftype(tname,0);
+ String *fname = Swig_symbol_type_qualify(ty,0);
+ Swig_symbol_cadd(fname,$$);
+ Delete(ty);
+ Delete(fname);
+ }
+ } else if ($$) {
+ Setattr($$, "templatetype", nodeType($$));
+ set_nodeType($$,"template");
+ Setattr($$,"templateparms", $template_parms);
+ if (!Getattr($$,"sym:weak")) {
+ Setattr($$,"sym:typename","1");
+ }
+ add_symbols($$);
+ default_arguments($$);
+ /* We also place a fully parameterized version in the symbol table */
+ {
+ Parm *p;
+ String *fname = NewStringf("%s<(", Getattr($$,"name"));
+ p = $template_parms;
+ while (p) {
+ String *n = Getattr(p,"name");
+ if (!n) n = Getattr(p,"type");
+ Append(fname,n);
+ p = nextSibling(p);
+ if (p) Putc(',',fname);
+ }
+ Append(fname,")>");
+ Swig_symbol_cadd(fname,$$);
+ }
+ }
+ $$ = ntop;
+ Swig_symbol_setscope(cscope);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ if (error || (nscope_inner && Strcmp(nodeType(nscope_inner), "class") == 0)) {
+ $$ = 0;
+ }
+ if (currentOuterClass)
+ template_parameters = Getattr(currentOuterClass, "template_parameters");
+ else
+ template_parameters = 0;
+ parsing_template_declaration = 0;
+ }
+
+ /* Class template explicit instantiation definition */
+ | TEMPLATE cpptype idcolon {
+ Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
+ $$ = 0;
+ }
+
+ /* Function template explicit instantiation definition */
+ | TEMPLATE cpp_alternate_rettype idcolon LPAREN parms RPAREN {
+ Swig_warning(WARN_PARSE_EXPLICIT_TEMPLATE, cparse_file, cparse_line, "Explicit template instantiation ignored.\n");
+ $$ = 0;
+ }
+
+ /* Class template explicit instantiation declaration (extern template) */
+ | EXTERN TEMPLATE cpptype idcolon {
+ Swig_warning(WARN_PARSE_EXTERN_TEMPLATE, cparse_file, cparse_line, "Extern template ignored.\n");
+ $$ = 0;
+ }
+
+ /* Function template explicit instantiation declaration (extern template) */
+ | EXTERN TEMPLATE cpp_alternate_rettype idcolon LPAREN parms RPAREN {
+ Swig_warning(WARN_PARSE_EXTERN_TEMPLATE, cparse_file, cparse_line, "Extern template ignored.\n");
+ $$ = 0;
+ }
+ ;
+
+cpp_template_possible: c_decl
+ | cpp_class_decl
+ | cpp_constructor_decl
+ | cpp_template_decl {
+ $$ = 0;
+ }
+ | cpp_forward_class_decl
+ | cpp_conversion_operator
+ ;
+
+template_parms : template_parms_builder {
+ $$ = $template_parms_builder.parms;
+ }
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+template_parms_builder : templateparameter {
+ $$.parms = $$.last = $templateparameter;
+ }
+ | template_parms_builder[in] COMMA templateparameter {
+ // Build a linked list in the order specified, but avoiding
+ // a right recursion rule because "Right recursion uses up
+ // space on the Bison stack in proportion to the number of
+ // elements in the sequence".
+ set_nextSibling($in.last, $templateparameter);
+ $$.parms = $in.parms;
+ $$.last = $templateparameter;
+ }
+ ;
+
+templateparameter : templcpptype def_args {
+ $$ = NewParmWithoutFileLineInfo($templcpptype, 0);
+ Setfile($$, cparse_file);
+ Setline($$, cparse_line);
+ Setattr($$, "value", $def_args.val);
+ if ($def_args.stringval) Setattr($$, "stringval", $def_args.stringval);
+ if ($def_args.numval) Setattr($$, "numval", $def_args.numval);
+ }
+ | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype idcolon def_args {
+ $$ = NewParmWithoutFileLineInfo(NewStringf("template< %s > %s %s", ParmList_str_defaultargs($template_parms), $cpptype, $idcolon), $idcolon);
+ Setfile($$, cparse_file);
+ Setline($$, cparse_line);
+ if ($def_args.val) {
+ Setattr($$, "value", $def_args.val);
+ }
+ }
+ | TEMPLATE LESSTHAN template_parms GREATERTHAN cpptype def_args {
+ $$ = NewParmWithoutFileLineInfo(NewStringf("template< %s > %s", ParmList_str_defaultargs($template_parms), $cpptype), 0);
+ Setfile($$, cparse_file);
+ Setline($$, cparse_line);
+ if ($def_args.val) {
+ Setattr($$, "value", $def_args.val);
+ }
+ }
+ | parm {
+ Parm *p = $parm;
+ String *name = Getattr(p, "name");
+ $$ = $parm;
+
+ /* Correct the 'type name' parameter string, split into the appropriate "name" and "type" attributes */
+ if (!name) {
+ String *type = Getattr(p, "type");
+ if ((Strncmp(type, "class ", 6) == 0) || (Strncmp(type, "typename ", 9) == 0)) {
+ /* A 'class T' parameter */
+ const char *t = Strchr(type, ' ');
+ Setattr(p, "name", t + 1);
+ Setattr(p, "type", NewStringWithSize(type, (int)(t - Char(type))));
+ } else if ((Strncmp(type, "v.class ", 8) == 0) || (Strncmp(type, "v.typename ", 11) == 0)) {
+ /* Variadic template args */
+ const char *t = Strchr(type, ' ');
+ Setattr(p, "name", t + 1);
+ Setattr(p, "type", NewStringWithSize(type, (int)(t - Char(type))));
+ }
+ }
+ }
+ ;
+
+/* Namespace support */
+
+cpp_using_decl : USING idcolon SEMI {
+ String *uname = Swig_symbol_type_qualify($idcolon,0);
+ /* Possible TODO: In testcase using_member_multiple_inherit class Susing3, uname is "Susing1::usingmethod" instead of "Susing2::usingmethod" */
+ String *name = Swig_scopename_last($idcolon);
+ $$ = new_node("using");
+ Setattr($$,"uname",uname);
+ Setattr($$,"name", name);
+ Delete(uname);
+ Delete(name);
+ add_symbols($$);
+ }
+ | USING TYPENAME idcolon SEMI {
+ String *uname = Swig_symbol_type_qualify($idcolon,0);
+ String *name = Swig_scopename_last($idcolon);
+ $$ = new_node("using");
+ Setattr($$,"uname",uname);
+ Setattr($$,"name", name);
+ Delete(uname);
+ Delete(name);
+ add_symbols($$);
+ }
+ | USING NAMESPACE idcolon SEMI {
+ Node *n = Swig_symbol_clookup($idcolon,0);
+ if (!n) {
+ Swig_error(cparse_file, cparse_line, "Nothing known about namespace '%s'\n", SwigType_namestr($idcolon));
+ $$ = 0;
+ } else {
+
+ while (Strcmp(nodeType(n),"using") == 0) {
+ n = Getattr(n,"node");
+ }
+ if (n) {
+ if (Strcmp(nodeType(n),"namespace") == 0) {
+ Symtab *current = Swig_symbol_current();
+ Symtab *symtab = Getattr(n,"symtab");
+ $$ = new_node("using");
+ Setattr($$,"node",n);
+ Setattr($$,"namespace", $idcolon);
+ if (current != symtab) {
+ Swig_symbol_inherit(symtab);
+ }
+ } else {
+ Swig_error(cparse_file, cparse_line, "'%s' is not a namespace.\n", SwigType_namestr($idcolon));
+ $$ = 0;
+ }
+ } else {
+ $$ = 0;
+ }
+ }
+ }
+ ;
+
+cpp_namespace_decl : NAMESPACE idcolon LBRACE <node>{
+ Hash *h;
+ Node *parent_ns = 0;
+ List *scopes = Swig_scopename_tolist($idcolon);
+ int ilen = Len(scopes);
+ int i;
+
+/*
+Printf(stdout, "==== Namespace %s creation...\n", $idcolon);
+*/
+ $$ = 0;
+ for (i = 0; i < ilen; i++) {
+ Node *ns = new_node("namespace");
+ Symtab *current_symtab = Swig_symbol_current();
+ String *scopename = Getitem(scopes, i);
+ Setattr(ns, "name", scopename);
+ $$ = ns;
+ if (parent_ns)
+ appendChild(parent_ns, ns);
+ parent_ns = ns;
+ h = Swig_symbol_clookup(scopename, 0);
+ if (h && (current_symtab == Getattr(h, "sym:symtab")) && (Strcmp(nodeType(h), "namespace") == 0)) {
+/*
+Printf(stdout, " Scope %s [found C++17 style]\n", scopename);
+*/
+ if (Getattr(h, "alias")) {
+ h = Getattr(h, "namespace");
+ Swig_warning(WARN_PARSE_NAMESPACE_ALIAS, cparse_file, cparse_line, "Namespace alias '%s' not allowed here. Assuming '%s'\n",
+ scopename, Getattr(h, "name"));
+ scopename = Getattr(h, "name");
+ }
+ Swig_symbol_setscope(Getattr(h, "symtab"));
+ } else {
+/*
+Printf(stdout, " Scope %s [creating single scope C++17 style]\n", scopename);
+*/
+ h = Swig_symbol_newscope();
+ Swig_symbol_setscopename(scopename);
+ }
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ }
+ Delete(scopes);
+ }[node] interface RBRACE {
+ Node *n = $node;
+ Node *top_ns = 0;
+ do {
+ Setattr(n, "symtab", Swig_symbol_popscope());
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ add_symbols(n);
+ top_ns = n;
+ n = parentNode(n);
+ } while(n);
+ appendChild($node, firstChild($interface));
+ Delete($interface);
+ $$ = top_ns;
+ }
+ | NAMESPACE LBRACE <node>{
+ Hash *h;
+ $$ = Swig_symbol_current();
+ h = Swig_symbol_clookup(" ",0);
+ if (h && (Strcmp(nodeType(h),"namespace") == 0)) {
+ Swig_symbol_setscope(Getattr(h,"symtab"));
+ } else {
+ Swig_symbol_newscope();
+ /* we don't use "__unnamed__", but a long 'empty' name */
+ Swig_symbol_setscopename(" ");
+ }
+ Namespaceprefix = 0;
+ }[node] interface RBRACE {
+ $$ = $interface;
+ set_nodeType($$,"namespace");
+ Setattr($$,"unnamed","1");
+ Setattr($$,"symtab", Swig_symbol_popscope());
+ Swig_symbol_setscope($node);
+ Delete(Namespaceprefix);
+ Namespaceprefix = Swig_symbol_qualifiedscopename(0);
+ add_symbols($$);
+ }
+ | NAMESPACE identifier EQUAL idcolon SEMI {
+ /* Namespace alias */
+ Node *n;
+ $$ = new_node("namespace");
+ Setattr($$,"name",$identifier);
+ Setattr($$,"alias",$idcolon);
+ n = Swig_symbol_clookup($idcolon,0);
+ if (!n) {
+ Swig_error(cparse_file, cparse_line, "Unknown namespace '%s'\n", SwigType_namestr($idcolon));
+ $$ = 0;
+ } else {
+ if (Strcmp(nodeType(n),"namespace") != 0) {
+ Swig_error(cparse_file, cparse_line, "'%s' is not a namespace\n", SwigType_namestr($idcolon));
+ $$ = 0;
+ } else {
+ while (Getattr(n,"alias")) {
+ n = Getattr(n,"namespace");
+ }
+ Setattr($$,"namespace",n);
+ add_symbols($$);
+ /* Set up a scope alias */
+ Swig_symbol_alias($identifier,Getattr(n,"symtab"));
+ }
+ }
+ }
+ ;
+
+cpp_members : cpp_members_builder {
+ $$ = $cpp_members_builder.node;
+ }
+ | cpp_members_builder DOXYGENSTRING {
+ /* Quietly ignore misplaced doxygen string after a member, like Doxygen does */
+ $$ = $cpp_members_builder.node;
+ Delete($DOXYGENSTRING);
+ }
+ | %empty {
+ $$ = 0;
+ }
+ | DOXYGENSTRING {
+ /* Quietly ignore misplaced doxygen string in empty class, like Doxygen does */
+ $$ = 0;
+ Delete($DOXYGENSTRING);
+ }
+ | error {
+ Swig_error(cparse_file, cparse_line, "Syntax error in input(3).\n");
+ Exit(EXIT_FAILURE);
+ }
+ ;
+
+cpp_members_builder : cpp_member {
+ $$.node = $$.last = $cpp_member;
+ }
+ | cpp_members_builder[in] cpp_member {
+ // Build a linked list in the order specified, but avoiding
+ // a right recursion rule because "Right recursion uses up
+ // space on the Bison stack in proportion to the number of
+ // elements in the sequence".
+ if ($cpp_member) {
+ if ($in.node) {
+ Node *last = $in.last;
+ /* Advance to the last sibling. */
+ for (Node *p = last; p; p = nextSibling(p)) {
+ last = p;
+ }
+ set_nextSibling(last, $cpp_member);
+ set_previousSibling($cpp_member, last);
+ $$.node = $in.node;
+ } else {
+ $$.node = $$.last = $cpp_member;
+ }
+ } else {
+ $$ = $in;
+ }
+ }
+ ;
+
+/* ======================================================================
+ * C++ Class members
+ * ====================================================================== */
+
+/* A class member. May be data or a function. Static or virtual as well */
+
+cpp_member_no_dox : c_declaration
+ | cpp_constructor_decl {
+ $$ = $cpp_constructor_decl;
+ if (extendmode && current_class) {
+ String *symname;
+ symname= make_name($$,Getattr($$,"name"), Getattr($$,"decl"));
+ if (Strcmp(symname,Getattr($$,"name")) == 0) {
+ /* No renaming operation. Set name to class name */
+ Delete(yyrename);
+ yyrename = NewString(Getattr(current_class,"sym:name"));
+ } else {
+ Delete(yyrename);
+ yyrename = symname;
+ }
+ }
+ add_symbols($$);
+ default_arguments($$);
+ }
+ | cpp_destructor_decl
+ | cpp_protection_decl
+ | cpp_swig_directive
+ | cpp_conversion_operator
+ | cpp_forward_class_decl
+ | cpp_class_decl
+ | storage_class idcolon SEMI { $$ = 0; Delete($storage_class); }
+ | cpp_using_decl
+ | cpp_template_decl
+ | cpp_catch_decl
+ | include_directive
+ | template_directive
+ | warn_directive
+ | anonymous_bitfield { $$ = 0; }
+ | fragment_directive
+ | types_directive
+ | SEMI { $$ = 0; }
+
+cpp_member : cpp_member_no_dox
+ | DOXYGENSTRING cpp_member_no_dox {
+ $$ = $cpp_member_no_dox;
+ set_comment($cpp_member_no_dox, $DOXYGENSTRING);
+ }
+ | cpp_member_no_dox DOXYGENPOSTSTRING {
+ $$ = $cpp_member_no_dox;
+ set_comment($cpp_member_no_dox, $DOXYGENPOSTSTRING);
+ }
+ | EXTEND LBRACE {
+ extendmode = 1;
+ if (cplus_mode != CPLUS_PUBLIC) {
+ Swig_error(cparse_file,cparse_line,"%%extend can only be used in a public section\n");
+ }
+ } cpp_members RBRACE {
+ extendmode = 0;
+ $$ = new_node("extend");
+ mark_nodes_as_extend($cpp_members);
+ appendChild($$, $cpp_members);
+ }
+ ;
+
+/* Possibly a constructor */
+/* Note: the use of 'type' is here to resolve a shift-reduce conflict. For example:
+ typedef Foo ();
+ typedef Foo (*ptr)();
+*/
+
+cpp_constructor_decl : storage_class type LPAREN parms RPAREN ctor_end {
+ /* Cannot be a constructor declaration/definition if parsed as a friend destructor/constructor
+ or a badly declared friend function without return type */
+ int isfriend = Strstr($storage_class, "friend") != NULL;
+ if (!isfriend && (inclass || extendmode)) {
+ String *name = SwigType_templateprefix($type); /* A constructor can optionally be declared with template parameters before C++20, strip these off */
+ SwigType *decl = NewStringEmpty();
+ $$ = new_node("constructor");
+ Setattr($$,"storage",$storage_class);
+ Setattr($$, "name", name);
+ Setattr($$,"parms",$parms);
+ SwigType_add_function(decl,$parms);
+ Setattr($$,"decl",decl);
+ Setattr($$,"throws",$ctor_end.throws);
+ Setattr($$,"throw",$ctor_end.throwf);
+ Setattr($$,"noexcept",$ctor_end.nexcept);
+ Setattr($$,"final",$ctor_end.final);
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr($$,"code",code);
+ Delete(code);
+ }
+ SetFlag($$,"feature:new");
+ if ($ctor_end.defarg)
+ Setattr($$, "value", $ctor_end.defarg);
+ if ($ctor_end.stringdefarg)
+ Setattr($$, "stringval", $ctor_end.stringdefarg);
+ if ($ctor_end.numdefarg)
+ Setattr($$, "numval", $ctor_end.numdefarg);
+ } else {
+ $$ = 0;
+ }
+ Delete($storage_class);
+ }
+ ;
+
+/* A destructor */
+
+cpp_destructor_decl : storage_class NOT idtemplate LPAREN parms RPAREN cpp_vend {
+ String *name = SwigType_templateprefix($idtemplate); /* A destructor can optionally be declared with template parameters before C++20, strip these off */
+ Insert(name, 0, "~");
+ $$ = new_node("destructor");
+ Setattr($$, "storage", $storage_class);
+ Setattr($$, "name", name);
+ Delete(name);
+ if (Len(scanner_ccode)) {
+ String *code = Copy(scanner_ccode);
+ Setattr($$, "code", code);
+ Delete(code);
+ }
+ {
+ String *decl = NewStringEmpty();
+ SwigType_add_function(decl, $parms);
+ Setattr($$, "decl", decl);
+ Delete(decl);
+ }
+ Setattr($$, "throws", $cpp_vend.throws);
+ Setattr($$, "throw", $cpp_vend.throwf);
+ Setattr($$, "noexcept", $cpp_vend.nexcept);
+ Setattr($$, "final", $cpp_vend.final);
+ if ($cpp_vend.val) {
+ if (Equal($cpp_vend.val, "0")) {
+ if (!Strstr($storage_class, "virtual"))
+ Swig_error(cparse_file, cparse_line, "Destructor %s uses a pure specifier but is not virtual.\n", Swig_name_decl($$));
+ } else if (!(Equal($cpp_vend.val, "delete") || Equal($cpp_vend.val, "default"))) {
+ Swig_error(cparse_file, cparse_line, "Destructor %s has an invalid pure specifier, only = 0 is allowed.\n", Swig_name_decl($$));
+ }
+ Setattr($$, "value", $cpp_vend.val);
+ }
+ /* TODO: check all storage decl-specifiers are valid */
+ if ($cpp_vend.qualifier)
+ Swig_error(cparse_file, cparse_line, "Destructor %s %s cannot have a qualifier.\n", Swig_name_decl($$), SwigType_str($cpp_vend.qualifier, 0));
+ add_symbols($$);
+ Delete($storage_class);
+ }
+ ;
+
+
+/* C++ type conversion operator */
+cpp_conversion_operator : storage_class CONVERSIONOPERATOR type pointer LPAREN parms RPAREN cpp_vend {
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"name",$CONVERSIONOPERATOR);
+ Setattr($$,"storage",$storage_class);
+
+ SwigType_add_function($pointer,$parms);
+ if ($cpp_vend.qualifier) {
+ SwigType_push($pointer,$cpp_vend.qualifier);
+ }
+ if ($cpp_vend.val) {
+ Setattr($$,"value",$cpp_vend.val);
+ }
+ Setattr($$,"refqualifier",$cpp_vend.refqualifier);
+ Setattr($$,"decl",$pointer);
+ Setattr($$,"parms",$parms);
+ Setattr($$,"conversion_operator","1");
+ add_symbols($$);
+ Delete($CONVERSIONOPERATOR);
+ Delete($storage_class);
+ }
+ | storage_class CONVERSIONOPERATOR type AND LPAREN parms RPAREN cpp_vend {
+ SwigType *decl;
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"name",$CONVERSIONOPERATOR);
+ Setattr($$,"storage",$storage_class);
+ decl = NewStringEmpty();
+ SwigType_add_reference(decl);
+ SwigType_add_function(decl,$parms);
+ if ($cpp_vend.qualifier) {
+ SwigType_push(decl,$cpp_vend.qualifier);
+ }
+ if ($cpp_vend.val) {
+ Setattr($$,"value",$cpp_vend.val);
+ }
+ Setattr($$,"refqualifier",$cpp_vend.refqualifier);
+ Setattr($$,"decl",decl);
+ Setattr($$,"parms",$parms);
+ Setattr($$,"conversion_operator","1");
+ add_symbols($$);
+ Delete($CONVERSIONOPERATOR);
+ Delete($storage_class);
+ }
+ | storage_class CONVERSIONOPERATOR type LAND LPAREN parms RPAREN cpp_vend {
+ SwigType *decl;
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"name",$CONVERSIONOPERATOR);
+ Setattr($$,"storage",$storage_class);
+ decl = NewStringEmpty();
+ SwigType_add_rvalue_reference(decl);
+ SwigType_add_function(decl,$parms);
+ if ($cpp_vend.qualifier) {
+ SwigType_push(decl,$cpp_vend.qualifier);
+ }
+ if ($cpp_vend.val) {
+ Setattr($$,"value",$cpp_vend.val);
+ }
+ Setattr($$,"refqualifier",$cpp_vend.refqualifier);
+ Setattr($$,"decl",decl);
+ Setattr($$,"parms",$parms);
+ Setattr($$,"conversion_operator","1");
+ add_symbols($$);
+ Delete($CONVERSIONOPERATOR);
+ Delete($storage_class);
+ }
+
+ | storage_class CONVERSIONOPERATOR type pointer AND LPAREN parms RPAREN cpp_vend {
+ SwigType *decl;
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"name",$CONVERSIONOPERATOR);
+ Setattr($$,"storage",$storage_class);
+ decl = NewStringEmpty();
+ SwigType_add_pointer(decl);
+ SwigType_add_reference(decl);
+ SwigType_add_function(decl,$parms);
+ if ($cpp_vend.qualifier) {
+ SwigType_push(decl,$cpp_vend.qualifier);
+ }
+ if ($cpp_vend.val) {
+ Setattr($$,"value",$cpp_vend.val);
+ }
+ Setattr($$,"refqualifier",$cpp_vend.refqualifier);
+ Setattr($$,"decl",decl);
+ Setattr($$,"parms",$parms);
+ Setattr($$,"conversion_operator","1");
+ add_symbols($$);
+ Delete($CONVERSIONOPERATOR);
+ Delete($storage_class);
+ }
+
+ | storage_class CONVERSIONOPERATOR type LPAREN parms RPAREN cpp_vend {
+ String *t = NewStringEmpty();
+ $$ = new_node("cdecl");
+ Setattr($$,"type",$type);
+ Setattr($$,"name",$CONVERSIONOPERATOR);
+ Setattr($$,"storage",$storage_class);
+ SwigType_add_function(t,$parms);
+ if ($cpp_vend.qualifier) {
+ SwigType_push(t,$cpp_vend.qualifier);
+ }
+ if ($cpp_vend.val) {
+ Setattr($$,"value",$cpp_vend.val);
+ }
+ Setattr($$,"refqualifier",$cpp_vend.refqualifier);
+ Setattr($$,"decl",t);
+ Setattr($$,"parms",$parms);
+ Setattr($$,"conversion_operator","1");
+ add_symbols($$);
+ Delete($CONVERSIONOPERATOR);
+ Delete($storage_class);
+ }
+ ;
+
+/* isolated catch clause. */
+
+cpp_catch_decl : CATCH LPAREN parms RPAREN LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = 0;
+ }
+ ;
+
+/* static_assert(bool, const char*); (C++11)
+ * static_assert(bool); (C++17) */
+cpp_static_assert : STATIC_ASSERT LPAREN {
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
+ $$ = 0;
+ }
+ ;
+
+/* public: */
+cpp_protection_decl : PUBLIC COLON {
+ $$ = new_node("access");
+ Setattr($$,"kind","public");
+ cplus_mode = CPLUS_PUBLIC;
+ }
+
+/* private: */
+ | PRIVATE COLON {
+ $$ = new_node("access");
+ Setattr($$,"kind","private");
+ cplus_mode = CPLUS_PRIVATE;
+ }
+
+/* protected: */
+
+ | PROTECTED COLON {
+ $$ = new_node("access");
+ Setattr($$,"kind","protected");
+ cplus_mode = CPLUS_PROTECTED;
+ }
+ ;
+/* These directives can be included inside a class definition */
+
+cpp_swig_directive: pragma_directive
+
+/* A constant (includes #defines) inside a class */
+ | constant_directive
+
+ | rename_directive
+ | feature_directive
+ | varargs_directive
+ | insert_directive
+ | typemap_directive
+ | apply_directive
+ | clear_directive
+ | echo_directive
+ ;
+
+cpp_vend : cpp_const SEMI {
+ Clear(scanner_ccode);
+ $$ = $cpp_const;
+ }
+ | cpp_const EQUAL definetype SEMI {
+ Clear(scanner_ccode);
+ $$ = $cpp_const;
+ $$.val = $definetype.val;
+ }
+ | cpp_const LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = $cpp_const;
+ }
+ ;
+
+
+anonymous_bitfield : storage_class anon_bitfield_type COLON expr SEMI { Delete($storage_class); };
+
+/* Equals type_right without the ENUM keyword and cpptype (templates etc.): */
+anon_bitfield_type : primitive_type
+ | TYPE_BOOL
+ | TYPE_VOID
+ | TYPE_RAW
+
+ | idcolon { $$ = $idcolon; }
+ ;
+
+/* ======================================================================
+ * PRIMITIVES
+ * ====================================================================== */
+storage_class : storage_class_list {
+ String *r = NewStringEmpty();
+
+ /* Check for invalid combinations. */
+ if (multiple_bits_set($storage_class_list & (SWIG_STORAGE_CLASS_EXTERN |
+ SWIG_STORAGE_CLASS_STATIC))) {
+ Swig_error(cparse_file, cparse_line, "Storage class can't be both 'static' and 'extern'");
+ }
+ if (multiple_bits_set($storage_class_list & (SWIG_STORAGE_CLASS_EXTERNC |
+ SWIG_STORAGE_CLASS_EXTERN |
+ SWIG_STORAGE_CLASS_EXTERNCPP))) {
+ Swig_error(cparse_file, cparse_line, "Declaration can only be one of 'extern', 'extern \"C\"' and 'extern \"C++\"'");
+ }
+
+ if ($storage_class_list & SWIG_STORAGE_CLASS_TYPEDEF) {
+ Append(r, "typedef ");
+ } else {
+ if ($storage_class_list & SWIG_STORAGE_CLASS_EXTERNC)
+ Append(r, "externc ");
+ if ($storage_class_list & (SWIG_STORAGE_CLASS_EXTERN|SWIG_STORAGE_CLASS_EXTERNCPP))
+ Append(r, "extern ");
+ if ($storage_class_list & SWIG_STORAGE_CLASS_STATIC)
+ Append(r, "static ");
+ }
+ if ($storage_class_list & SWIG_STORAGE_CLASS_VIRTUAL)
+ Append(r, "virtual ");
+ if ($storage_class_list & SWIG_STORAGE_CLASS_FRIEND)
+ Append(r, "friend ");
+ if ($storage_class_list & SWIG_STORAGE_CLASS_EXPLICIT)
+ Append(r, "explicit ");
+ if ($storage_class_list & SWIG_STORAGE_CLASS_CONSTEXPR)
+ Append(r, "constexpr ");
+ if ($storage_class_list & SWIG_STORAGE_CLASS_THREAD_LOCAL)
+ Append(r, "thread_local ");
+ if (Len(r) == 0) {
+ Delete(r);
+ $$ = 0;
+ } else {
+ Chop(r);
+ $$ = r;
+ }
+ }
+ | %empty { $$ = 0; }
+ ;
+
+storage_class_list: storage_class_raw
+ | storage_class_list[in] storage_class_raw {
+ if ($in & $storage_class_raw) {
+ Swig_error(cparse_file, cparse_line, "Repeated storage class or type specifier '%s'\n", storage_class_string($storage_class_raw));
+ }
+ $$ = $in | $storage_class_raw;
+ }
+ ;
+
+storage_class_raw : EXTERN { $$ = SWIG_STORAGE_CLASS_EXTERN; }
+ | EXTERN string {
+ if (Strcmp($string,"C") == 0) {
+ $$ = SWIG_STORAGE_CLASS_EXTERNC;
+ } else if (Strcmp($string,"C++") == 0) {
+ $$ = SWIG_STORAGE_CLASS_EXTERNCPP;
+ } else {
+ Swig_warning(WARN_PARSE_UNDEFINED_EXTERN,cparse_file, cparse_line,"Unrecognized extern type \"%s\".\n", $string);
+ $$ = 0;
+ }
+ }
+ | STATIC { $$ = SWIG_STORAGE_CLASS_STATIC; }
+ | TYPEDEF { $$ = SWIG_STORAGE_CLASS_TYPEDEF; }
+ | VIRTUAL { $$ = SWIG_STORAGE_CLASS_VIRTUAL; }
+ | FRIEND { $$ = SWIG_STORAGE_CLASS_FRIEND; }
+ | EXPLICIT { $$ = SWIG_STORAGE_CLASS_EXPLICIT; }
+ | CONSTEXPR { $$ = SWIG_STORAGE_CLASS_CONSTEXPR; }
+ | THREAD_LOCAL { $$ = SWIG_STORAGE_CLASS_THREAD_LOCAL; }
+ ;
+
+/* ------------------------------------------------------------------------------
+ Function parameter lists
+ ------------------------------------------------------------------------------ */
+
+parms : rawparms {
+ Parm *p;
+ $$ = $rawparms;
+ p = $rawparms;
+ while (p) {
+ Replace(Getattr(p,"type"),"typename ", "", DOH_REPLACE_ANY);
+ p = nextSibling(p);
+ }
+ }
+ ;
+
+/* rawparms constructs parameter lists and deal with quirks of doxygen post strings (after the parameter's comma */
+rawparms : parm { $$ = $parm; }
+ | parm DOXYGENPOSTSTRING {
+ set_comment($parm, $DOXYGENPOSTSTRING);
+ $$ = $parm;
+ }
+ | parm DOXYGENSTRING {
+ /* Misplaced doxygen string, attach it to previous parameter, like Doxygen does */
+ set_comment($parm, $DOXYGENSTRING);
+ $$ = $parm;
+ }
+ | parm COMMA parms {
+ if ($parms) {
+ set_nextSibling($parm, $parms);
+ }
+ $$ = $parm;
+ }
+ | parm DOXYGENPOSTSTRING COMMA parms {
+ if ($parms) {
+ set_nextSibling($parm, $parms);
+ }
+ set_comment($parm, $DOXYGENPOSTSTRING);
+ $$ = $parm;
+ }
+ | parm COMMA DOXYGENPOSTSTRING parms {
+ if ($parms) {
+ set_nextSibling($parm, $parms);
+ }
+ set_comment($parm, $DOXYGENPOSTSTRING);
+ $$ = $parm;
+ }
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+parm_no_dox : rawtype parameter_declarator {
+ SwigType_push($rawtype,$parameter_declarator.type);
+ $$ = NewParmWithoutFileLineInfo($rawtype,$parameter_declarator.id);
+ Setfile($$,cparse_file);
+ Setline($$,cparse_line);
+ if ($parameter_declarator.defarg)
+ Setattr($$, "value", $parameter_declarator.defarg);
+ if ($parameter_declarator.stringdefarg)
+ Setattr($$, "stringval", $parameter_declarator.stringdefarg);
+ if ($parameter_declarator.numdefarg)
+ Setattr($$, "numval", $parameter_declarator.numdefarg);
+ }
+ | ELLIPSIS {
+ SwigType *t = NewString("v(...)");
+ $$ = NewParmWithoutFileLineInfo(t, 0);
+ Setfile($$,cparse_file);
+ Setline($$,cparse_line);
+ }
+ ;
+
+parm : parm_no_dox
+ | DOXYGENSTRING parm_no_dox {
+ $$ = $parm_no_dox;
+ set_comment($parm_no_dox, $DOXYGENSTRING);
+ }
+ ;
+
+valparms : valparms_builder {
+ $$ = $valparms_builder.parms;
+ for (Parm *p = $$; p; p = nextSibling(p)) {
+ if (Getattr(p,"type")) {
+ Replace(Getattr(p,"type"),"typename ", "", DOH_REPLACE_ANY);
+ }
+ }
+ }
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+valparms_builder : valparm {
+ $$.parms = $$.last = $valparm;
+ }
+ | valparms_builder[in] COMMA valparm {
+ // Build a linked list in the order specified, but avoiding
+ // a right recursion rule because "Right recursion uses up
+ // space on the Bison stack in proportion to the number of
+ // elements in the sequence".
+ set_nextSibling($in.last, $valparm);
+ $$.parms = $in.parms;
+ $$.last = $valparm;
+ }
+ ;
+
+valparm : parm {
+ $$ = $parm;
+ {
+ /* We need to make a possible adjustment for integer parameters. */
+ SwigType *type;
+ Node *n = 0;
+
+ while (!n) {
+ type = Getattr($parm,"type");
+ n = Swig_symbol_clookup(type,0); /* See if we can find a node that matches the typename */
+ if ((n) && (Strcmp(nodeType(n),"cdecl") == 0)) {
+ SwigType *decl = Getattr(n,"decl");
+ if (!SwigType_isfunction(decl)) {
+ String *value = Getattr(n,"value");
+ if (value) {
+ String *v = Copy(value);
+ Setattr($parm,"type",v);
+ Delete(v);
+ n = 0;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ }
+ | valexpr {
+ $$ = NewParmWithoutFileLineInfo(0,0);
+ Setfile($$,cparse_file);
+ Setline($$,cparse_line);
+ Setattr($$,"value",$valexpr.val);
+ if ($valexpr.stringval) Setattr($$, "stringval", $valexpr.stringval);
+ if ($valexpr.numval) Setattr($$, "numval", $valexpr.numval);
+ }
+ ;
+
+def_args : EQUAL definetype {
+ $$ = $definetype;
+ }
+ | EQUAL definetype LBRACKET {
+ if (skip_balanced('[', ']') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.type = T_UNKNOWN;
+ $$.val = $definetype.val;
+ Append($$.val, scanner_ccode);
+ Clear(scanner_ccode);
+ }
+ | EQUAL LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.val = NewString(scanner_ccode);
+ $$.type = T_UNKNOWN;
+ }
+ | %empty {
+ $$ = default_dtype;
+ $$.type = T_UNKNOWN;
+ }
+ ;
+
+parameter_declarator : declarator def_args {
+ $$ = $declarator;
+ $$.defarg = $def_args.val;
+ $$.stringdefarg = $def_args.stringval;
+ $$.numdefarg = $def_args.numval;
+ }
+ | abstract_declarator def_args {
+ $$ = $abstract_declarator;
+ $$.defarg = $def_args.val;
+ $$.stringdefarg = $def_args.stringval;
+ $$.numdefarg = $def_args.numval;
+ }
+ | def_args {
+ $$ = default_decl;
+ $$.defarg = $def_args.val;
+ $$.stringdefarg = $def_args.stringval;
+ $$.numdefarg = $def_args.numval;
+ }
+ /* Member function pointers with qualifiers. eg.
+ int f(short (Funcs::*parm)(bool) const); */
+ | direct_declarator LPAREN parms RPAREN qualifiers_exception_specification {
+ SwigType *t;
+ $$ = $direct_declarator;
+ t = NewStringEmpty();
+ SwigType_add_function(t,$parms);
+ if ($qualifiers_exception_specification.qualifier)
+ SwigType_push(t, $qualifiers_exception_specification.qualifier);
+ if ($qualifiers_exception_specification.nexcept)
+ SwigType_add_qualifier(t, "noexcept");
+ if (!$$.have_parms) {
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ if (!$$.type) {
+ $$.type = t;
+ } else {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ $$.type = t;
+ }
+ }
+ ;
+
+plain_declarator : declarator {
+ $$ = $declarator;
+ if (SwigType_isfunction($declarator.type)) {
+ Delete(SwigType_pop_function($declarator.type));
+ } else if (SwigType_isarray($declarator.type)) {
+ SwigType *ta = SwigType_pop_arrays($declarator.type);
+ if (SwigType_isfunction($declarator.type)) {
+ Delete(SwigType_pop_function($declarator.type));
+ } else {
+ $$.parms = 0;
+ }
+ SwigType_push($declarator.type,ta);
+ Delete(ta);
+ } else {
+ $$.parms = 0;
+ }
+ }
+ | abstract_declarator {
+ $$ = $abstract_declarator;
+ if (SwigType_isfunction($abstract_declarator.type)) {
+ Delete(SwigType_pop_function($abstract_declarator.type));
+ } else if (SwigType_isarray($abstract_declarator.type)) {
+ SwigType *ta = SwigType_pop_arrays($abstract_declarator.type);
+ if (SwigType_isfunction($abstract_declarator.type)) {
+ Delete(SwigType_pop_function($abstract_declarator.type));
+ } else {
+ $$.parms = 0;
+ }
+ SwigType_push($abstract_declarator.type,ta);
+ Delete(ta);
+ } else {
+ $$.parms = 0;
+ }
+ }
+ /* Member function pointers with qualifiers. eg.
+ int f(short (Funcs::*parm)(bool) const) */
+ | direct_declarator LPAREN parms RPAREN cv_ref_qualifier {
+ SwigType *t;
+ $$ = $direct_declarator;
+ t = NewStringEmpty();
+ SwigType_add_function(t, $parms);
+ if ($cv_ref_qualifier.qualifier)
+ SwigType_push(t, $cv_ref_qualifier.qualifier);
+ if (!$$.have_parms) {
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ if (!$$.type) {
+ $$.type = t;
+ } else {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ $$.type = t;
+ }
+ }
+ | %empty {
+ $$ = default_decl;
+ }
+ ;
+
+declarator : pointer notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | pointer AND notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | pointer LAND notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_rvalue_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | direct_declarator {
+ $$ = $direct_declarator;
+ if (!$$.type) $$.type = NewStringEmpty();
+ }
+ | AND notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ $$.type = NewStringEmpty();
+ SwigType_add_reference($$.type);
+ if ($notso_direct_declarator.type) {
+ SwigType_push($$.type,$notso_direct_declarator.type);
+ Delete($notso_direct_declarator.type);
+ }
+ }
+ | LAND notso_direct_declarator {
+ /* Introduced in C++11, move operator && */
+ /* Adds one S/R conflict */
+ $$ = $notso_direct_declarator;
+ $$.type = NewStringEmpty();
+ SwigType_add_rvalue_reference($$.type);
+ if ($notso_direct_declarator.type) {
+ SwigType_push($$.type,$notso_direct_declarator.type);
+ Delete($notso_direct_declarator.type);
+ }
+ }
+ | idcolon DSTAR notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | pointer idcolon DSTAR notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_push($pointer,t);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ Delete(t);
+ }
+ | pointer idcolon DSTAR AND notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer($pointer,$idcolon);
+ SwigType_add_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | idcolon DSTAR AND notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_add_reference(t);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+
+ /* Variadic versions eg. MyClasses&... myIds */
+
+ | pointer ELLIPSIS notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ SwigType_add_variadic($$.type);
+ }
+ | pointer AND ELLIPSIS notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ SwigType_add_variadic($$.type);
+ }
+ | pointer LAND ELLIPSIS notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_rvalue_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ SwigType_add_variadic($$.type);
+ }
+ | AND ELLIPSIS notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ $$.type = NewStringEmpty();
+ SwigType_add_reference($$.type);
+ SwigType_add_variadic($$.type);
+ if ($notso_direct_declarator.type) {
+ SwigType_push($$.type,$notso_direct_declarator.type);
+ Delete($notso_direct_declarator.type);
+ }
+ }
+ | LAND ELLIPSIS notso_direct_declarator {
+ /* Introduced in C++11, move operator && */
+ /* Adds one S/R conflict */
+ $$ = $notso_direct_declarator;
+ $$.type = NewStringEmpty();
+ SwigType_add_rvalue_reference($$.type);
+ SwigType_add_variadic($$.type);
+ if ($notso_direct_declarator.type) {
+ SwigType_push($$.type,$notso_direct_declarator.type);
+ Delete($notso_direct_declarator.type);
+ }
+ }
+ | idcolon DSTAR ELLIPSIS notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_add_variadic(t);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | pointer idcolon DSTAR ELLIPSIS notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_add_variadic(t);
+ SwigType_push($pointer,t);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ Delete(t);
+ }
+ | pointer idcolon DSTAR AND ELLIPSIS notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer($pointer,$idcolon);
+ SwigType_add_reference($pointer);
+ SwigType_add_variadic($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | pointer idcolon DSTAR LAND ELLIPSIS notso_direct_declarator {
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer($pointer,$idcolon);
+ SwigType_add_rvalue_reference($pointer);
+ SwigType_add_variadic($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | idcolon DSTAR AND ELLIPSIS notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_add_reference(t);
+ SwigType_add_variadic(t);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | idcolon DSTAR LAND ELLIPSIS notso_direct_declarator {
+ SwigType *t = NewStringEmpty();
+ $$ = $notso_direct_declarator;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_add_rvalue_reference(t);
+ SwigType_add_variadic(t);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ ;
+
+notso_direct_declarator : idcolon {
+ /* Note: This is non-standard C. Template declarator is allowed to follow an identifier */
+ $$ = default_decl;
+ $$.id = Char($idcolon);
+ }
+ | NOT idcolon {
+ $$ = default_decl;
+ $$.id = Char(NewStringf("~%s",$idcolon));
+ }
+
+/* This generates a shift-reduce conflict with constructors */
+ | LPAREN idcolon RPAREN {
+ $$ = default_decl;
+ $$.id = Char($idcolon);
+ }
+
+/*
+ | LPAREN AND idcolon RPAREN {
+ $$ = default_decl;
+ $$.id = Char($idcolon);
+ }
+*/
+/* Technically, this should be LPAREN declarator RPAREN, but we get reduce/reduce conflicts */
+ | LPAREN pointer notso_direct_declarator[in] RPAREN {
+ $$ = $in;
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | LPAREN idcolon DSTAR notso_direct_declarator[in] RPAREN {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_memberpointer(t,$idcolon);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | notso_direct_declarator[in] LBRACKET RBRACKET {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_array(t,"");
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | notso_direct_declarator[in] LBRACKET expr RBRACKET {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_array(t,$expr.val);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | notso_direct_declarator[in] LPAREN parms RPAREN {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_function(t,$parms);
+ if (!$$.have_parms) {
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ if (!$$.type) {
+ $$.type = t;
+ } else {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ $$.type = t;
+ }
+ }
+ ;
+
+direct_declarator : idcolon {
+ /* Note: This is non-standard C. Template declarator is allowed to follow an identifier */
+ $$ = default_decl;
+ $$.id = Char($idcolon);
+ }
+
+ | NOT idcolon {
+ $$ = default_decl;
+ $$.id = Char(NewStringf("~%s",$idcolon));
+ }
+
+/* This generate a shift-reduce conflict with constructors */
+/*
+ | LPAREN idcolon RPAREN {
+ $$ = default_decl;
+ $$.id = Char($idcolon);
+ }
+*/
+/* Technically, this should be LPAREN declarator RPAREN, but we get reduce/reduce conflicts */
+ | LPAREN pointer direct_declarator[in] RPAREN {
+ $$ = $in;
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | LPAREN AND direct_declarator[in] RPAREN {
+ $$ = $in;
+ if (!$$.type) {
+ $$.type = NewStringEmpty();
+ }
+ SwigType_add_reference($$.type);
+ }
+ | LPAREN LAND direct_declarator[in] RPAREN {
+ $$ = $in;
+ if (!$$.type) {
+ $$.type = NewStringEmpty();
+ }
+ SwigType_add_rvalue_reference($$.type);
+ }
+ | LPAREN idcolon DSTAR declarator RPAREN {
+ SwigType *t;
+ $$ = $declarator;
+ t = NewStringEmpty();
+ SwigType_add_memberpointer(t,$idcolon);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | LPAREN idcolon DSTAR type_qualifier declarator RPAREN {
+ SwigType *t;
+ $$ = $declarator;
+ t = NewStringEmpty();
+ SwigType_add_memberpointer(t, $idcolon);
+ SwigType_push(t, $type_qualifier);
+ if ($$.type) {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | LPAREN idcolon DSTAR abstract_declarator RPAREN {
+ SwigType *t;
+ $$ = $abstract_declarator;
+ t = NewStringEmpty();
+ SwigType_add_memberpointer(t, $idcolon);
+ if ($$.type) {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | LPAREN idcolon DSTAR type_qualifier abstract_declarator RPAREN {
+ SwigType *t;
+ $$ = $abstract_declarator;
+ t = NewStringEmpty();
+ SwigType_add_memberpointer(t, $idcolon);
+ SwigType_push(t, $type_qualifier);
+ if ($$.type) {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | direct_declarator[in] LBRACKET RBRACKET {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_array(t,"");
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | direct_declarator[in] LBRACKET expr RBRACKET {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_array(t,$expr.val);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | direct_declarator[in] LPAREN parms RPAREN {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_function(t,$parms);
+ if (!$$.have_parms) {
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ if (!$$.type) {
+ $$.type = t;
+ } else {
+ SwigType_push(t, $$.type);
+ Delete($$.type);
+ $$.type = t;
+ }
+ }
+ /* User-defined string literals. eg.
+ int operator"" _mySuffix(const char* val, int length) {...} */
+ /* This produces one S/R conflict. */
+ | OPERATOR ID LPAREN parms RPAREN {
+ $$ = default_decl;
+ SwigType *t;
+ Append($OPERATOR, " "); /* intervening space is mandatory */
+ Append($OPERATOR, $ID);
+ $$.id = Char($OPERATOR);
+ t = NewStringEmpty();
+ SwigType_add_function(t,$parms);
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ $$.type = t;
+ }
+ ;
+
+abstract_declarator : pointer variadic_opt {
+ $$ = default_decl;
+ $$.type = $pointer;
+ if ($variadic_opt) SwigType_add_variadic($$.type);
+ }
+ | pointer direct_abstract_declarator {
+ $$ = $direct_abstract_declarator;
+ SwigType_push($pointer,$direct_abstract_declarator.type);
+ $$.type = $pointer;
+ Delete($direct_abstract_declarator.type);
+ }
+ | pointer AND variadic_opt {
+ $$ = default_decl;
+ $$.type = $pointer;
+ SwigType_add_reference($$.type);
+ if ($variadic_opt) SwigType_add_variadic($$.type);
+ }
+ | pointer LAND variadic_opt {
+ $$ = default_decl;
+ $$.type = $pointer;
+ SwigType_add_rvalue_reference($$.type);
+ if ($variadic_opt) SwigType_add_variadic($$.type);
+ }
+ | pointer AND direct_abstract_declarator {
+ $$ = $direct_abstract_declarator;
+ SwigType_add_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | pointer LAND direct_abstract_declarator {
+ $$ = $direct_abstract_declarator;
+ SwigType_add_rvalue_reference($pointer);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ | direct_abstract_declarator
+ | AND direct_abstract_declarator {
+ $$ = $direct_abstract_declarator;
+ $$.type = NewStringEmpty();
+ SwigType_add_reference($$.type);
+ if ($direct_abstract_declarator.type) {
+ SwigType_push($$.type,$direct_abstract_declarator.type);
+ Delete($direct_abstract_declarator.type);
+ }
+ }
+ | LAND direct_abstract_declarator {
+ $$ = $direct_abstract_declarator;
+ $$.type = NewStringEmpty();
+ SwigType_add_rvalue_reference($$.type);
+ if ($direct_abstract_declarator.type) {
+ SwigType_push($$.type,$direct_abstract_declarator.type);
+ Delete($direct_abstract_declarator.type);
+ }
+ }
+ | AND variadic_opt {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_reference($$.type);
+ if ($variadic_opt) SwigType_add_variadic($$.type);
+ }
+ | LAND variadic_opt {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_rvalue_reference($$.type);
+ if ($variadic_opt) SwigType_add_variadic($$.type);
+ }
+ | idcolon DSTAR {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_memberpointer($$.type,$idcolon);
+ }
+ | idcolon DSTAR type_qualifier {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_memberpointer($$.type, $idcolon);
+ SwigType_push($$.type, $type_qualifier);
+ }
+ | pointer idcolon DSTAR {
+ $$ = default_decl;
+ SwigType *t = NewStringEmpty();
+ $$.type = $pointer;
+ SwigType_add_memberpointer(t,$idcolon);
+ SwigType_push($$.type,t);
+ Delete(t);
+ }
+ | pointer idcolon DSTAR direct_abstract_declarator {
+ $$ = $direct_abstract_declarator;
+ SwigType_add_memberpointer($pointer,$idcolon);
+ if ($$.type) {
+ SwigType_push($pointer,$$.type);
+ Delete($$.type);
+ }
+ $$.type = $pointer;
+ }
+ ;
+
+direct_abstract_declarator : direct_abstract_declarator[in] LBRACKET RBRACKET {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_array(t,"");
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | direct_abstract_declarator[in] LBRACKET expr RBRACKET {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_array(t,$expr.val);
+ if ($$.type) {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ }
+ $$.type = t;
+ }
+ | LBRACKET RBRACKET {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_array($$.type,"");
+ }
+ | LBRACKET expr RBRACKET {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_array($$.type,$expr.val);
+ }
+ | LPAREN abstract_declarator RPAREN {
+ $$ = $abstract_declarator;
+ }
+ | direct_abstract_declarator[in] LPAREN parms RPAREN {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_function(t,$parms);
+ if (!$$.type) {
+ $$.type = t;
+ } else {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ $$.type = t;
+ }
+ if (!$$.have_parms) {
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ }
+ | direct_abstract_declarator[in] LPAREN parms RPAREN cv_ref_qualifier {
+ SwigType *t;
+ $$ = $in;
+ t = NewStringEmpty();
+ SwigType_add_function(t,$parms);
+ SwigType_push(t, $cv_ref_qualifier.qualifier);
+ if (!$$.type) {
+ $$.type = t;
+ } else {
+ SwigType_push(t,$$.type);
+ Delete($$.type);
+ $$.type = t;
+ }
+ if (!$$.have_parms) {
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ }
+ | LPAREN parms RPAREN {
+ $$ = default_decl;
+ $$.type = NewStringEmpty();
+ SwigType_add_function($$.type,$parms);
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ ;
+
+
+pointer : pointer[in] STAR type_qualifier {
+ $$ = $in;
+ SwigType_add_pointer($$);
+ SwigType_push($$,$type_qualifier);
+ }
+ | pointer[in] STAR {
+ $$ = $in;
+ SwigType_add_pointer($$);
+ }
+ | STAR type_qualifier {
+ $$ = NewStringEmpty();
+ SwigType_add_pointer($$);
+ SwigType_push($$,$type_qualifier);
+ }
+ | STAR {
+ $$ = NewStringEmpty();
+ SwigType_add_pointer($$);
+ }
+ ;
+
+/* cv-qualifier plus C++11 ref-qualifier for non-static member functions */
+cv_ref_qualifier : type_qualifier {
+ $$.qualifier = $type_qualifier;
+ }
+ | type_qualifier ref_qualifier {
+ $$.qualifier = $type_qualifier;
+ $$.refqualifier = $ref_qualifier;
+ SwigType_push($$.qualifier, $ref_qualifier);
+ }
+ | ref_qualifier {
+ $$.qualifier = NewStringEmpty();
+ $$.refqualifier = $ref_qualifier;
+ SwigType_push($$.qualifier, $ref_qualifier);
+ }
+ ;
+
+ref_qualifier : AND {
+ $$ = NewStringEmpty();
+ SwigType_add_reference($$);
+ }
+ | LAND {
+ $$ = NewStringEmpty();
+ SwigType_add_rvalue_reference($$);
+ }
+ ;
+
+type_qualifier : type_qualifier_raw {
+ $$ = NewStringEmpty();
+ if ($type_qualifier_raw) SwigType_add_qualifier($$,$type_qualifier_raw);
+ }
+ | type_qualifier[in] type_qualifier_raw {
+ $$ = $in;
+ if ($type_qualifier_raw) SwigType_add_qualifier($$,$type_qualifier_raw);
+ }
+ ;
+
+type_qualifier_raw : CONST_QUAL { $$ = "const"; }
+ | VOLATILE { $$ = "volatile"; }
+ | REGISTER { $$ = 0; }
+ ;
+
+/* Data type must be a built in type or an identifier for user-defined types
+ This type can be preceded by a modifier. */
+
+type : rawtype %expect 4 {
+ $$ = $rawtype;
+ Replace($$,"typename ","", DOH_REPLACE_ANY);
+ }
+ ;
+
+rawtype : type_qualifier type_right {
+ $$ = $type_right;
+ SwigType_push($$,$type_qualifier);
+ }
+ | type_right
+ | type_right type_qualifier {
+ $$ = $type_right;
+ SwigType_push($$,$type_qualifier);
+ }
+ | type_qualifier[type_qualifier1] type_right type_qualifier[type_qualifier2] {
+ $$ = $type_right;
+ SwigType_push($$,$type_qualifier2);
+ SwigType_push($$,$type_qualifier1);
+ }
+ | rawtype[in] ELLIPSIS {
+ $$ = $in;
+ SwigType_add_variadic($$);
+ }
+ ;
+
+type_right : primitive_type
+ | TYPE_BOOL
+ | TYPE_VOID
+ | c_enum_key idcolon { $$ = NewStringf("enum %s", $idcolon); }
+ | TYPE_RAW
+
+ | idcolon %expect 1 {
+ $$ = $idcolon;
+ }
+ | cpptype idcolon %expect 1 {
+ $$ = NewStringf("%s %s", $cpptype, $idcolon);
+ }
+ | decltype
+ ;
+
+decltype : DECLTYPE LPAREN <str>{
+ $$ = get_raw_text_balanced('(', ')');
+ }[expr] decltypeexpr {
+ String *expr = $expr;
+ if ($decltypeexpr) {
+ $$ = $decltypeexpr;
+ } else {
+ $$ = NewStringf("decltype%s", expr);
+ /* expr includes parentheses but don't include them in the warning message. */
+ Delitem(expr, 0);
+ Delitem(expr, DOH_END);
+ Swig_warning(WARN_CPP11_DECLTYPE, cparse_file, cparse_line, "Unable to deduce decltype for '%s'.\n", expr);
+ }
+ Delete(expr);
+ }
+ ;
+
+decltypeexpr : expr RPAREN {
+ $$ = deduce_type(&$expr);
+ }
+ | error RPAREN {
+ /* Avoid a parse error if we can't parse the expression
+ * decltype() is applied to.
+ *
+ * Set $$ to 0 here to trigger the decltype rule above to
+ * issue a warning.
+ */
+ $$ = 0;
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
+ Clear(scanner_ccode);
+ }
+ ;
+
+primitive_type : primitive_type_list {
+ String *type = $primitive_type_list.type;
+ if (!type) type = NewString("int");
+ if ($primitive_type_list.us) {
+ $$ = NewStringf("%s %s", $primitive_type_list.us, type);
+ Delete($primitive_type_list.us);
+ Delete(type);
+ } else {
+ $$ = type;
+ }
+ if (Cmp($$,"signed int") == 0) {
+ Delete($$);
+ $$ = NewString("int");
+ } else if (Cmp($$,"signed long") == 0) {
+ Delete($$);
+ $$ = NewString("long");
+ } else if (Cmp($$,"signed short") == 0) {
+ Delete($$);
+ $$ = NewString("short");
+ } else if (Cmp($$,"signed long long") == 0) {
+ Delete($$);
+ $$ = NewString("long long");
+ }
+ }
+ ;
+
+primitive_type_list : type_specifier
+ | type_specifier primitive_type_list[in] {
+ if ($type_specifier.us && $in.us) {
+ Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $in.us);
+ }
+ $$ = $in;
+ if ($type_specifier.us) $$.us = $type_specifier.us;
+ if ($type_specifier.type) {
+ if (!$in.type) $$.type = $type_specifier.type;
+ else {
+ int err = 0;
+ if ((Cmp($type_specifier.type,"long") == 0)) {
+ if ((Cmp($in.type,"long") == 0) || (Strncmp($in.type,"double",6) == 0)) {
+ $$.type = NewStringf("long %s", $in.type);
+ } else if (Cmp($in.type,"int") == 0) {
+ $$.type = $type_specifier.type;
+ } else {
+ err = 1;
+ }
+ } else if ((Cmp($type_specifier.type,"short")) == 0) {
+ if (Cmp($in.type,"int") == 0) {
+ $$.type = $type_specifier.type;
+ } else {
+ err = 1;
+ }
+ } else if (Cmp($type_specifier.type,"int") == 0) {
+ $$.type = $in.type;
+ } else if (Cmp($type_specifier.type,"double") == 0) {
+ if (Cmp($in.type,"long") == 0) {
+ $$.type = NewString("long double");
+ } else if (Cmp($in.type,"_Complex") == 0) {
+ $$.type = NewString("double _Complex");
+ } else {
+ err = 1;
+ }
+ } else if (Cmp($type_specifier.type,"float") == 0) {
+ if (Cmp($in.type,"_Complex") == 0) {
+ $$.type = NewString("float _Complex");
+ } else {
+ err = 1;
+ }
+ } else if (Cmp($type_specifier.type,"_Complex") == 0) {
+ $$.type = NewStringf("%s _Complex", $in.type);
+ } else {
+ err = 1;
+ }
+ if (err) {
+ Swig_error(cparse_file, cparse_line, "Extra %s specifier.\n", $type_specifier.type);
+ }
+ }
+ }
+ }
+ ;
+
+
+type_specifier : TYPE_INT {
+ $$.type = NewString("int");
+ $$.us = 0;
+ }
+ | TYPE_SHORT {
+ $$.type = NewString("short");
+ $$.us = 0;
+ }
+ | TYPE_LONG {
+ $$.type = NewString("long");
+ $$.us = 0;
+ }
+ | TYPE_CHAR {
+ $$.type = NewString("char");
+ $$.us = 0;
+ }
+ | TYPE_WCHAR {
+ $$.type = NewString("wchar_t");
+ $$.us = 0;
+ }
+ | TYPE_FLOAT {
+ $$.type = NewString("float");
+ $$.us = 0;
+ }
+ | TYPE_DOUBLE {
+ $$.type = NewString("double");
+ $$.us = 0;
+ }
+ | TYPE_SIGNED {
+ $$.us = NewString("signed");
+ $$.type = 0;
+ }
+ | TYPE_UNSIGNED {
+ $$.us = NewString("unsigned");
+ $$.type = 0;
+ }
+ | TYPE_COMPLEX {
+ $$.type = NewString("_Complex");
+ $$.us = 0;
+ }
+ | TYPE_NON_ISO_INT8 {
+ $$.type = NewString("__int8");
+ $$.us = 0;
+ }
+ | TYPE_NON_ISO_INT16 {
+ $$.type = NewString("__int16");
+ $$.us = 0;
+ }
+ | TYPE_NON_ISO_INT32 {
+ $$.type = NewString("__int32");
+ $$.us = 0;
+ }
+ | TYPE_NON_ISO_INT64 {
+ $$.type = NewString("__int64");
+ $$.us = 0;
+ }
+ ;
+
+definetype : expr
+ | default_delete
+ ;
+
+default_delete : deleted_definition
+ | explicit_default
+ ;
+
+/* For C++ deleted definition '= delete' */
+deleted_definition : DELETE_KW {
+ $$ = default_dtype;
+ $$.val = NewString("delete");
+ $$.type = T_STRING;
+ }
+ ;
+
+/* For C++ explicitly defaulted functions '= default' */
+explicit_default : DEFAULT {
+ $$ = default_dtype;
+ $$.val = NewString("default");
+ $$.type = T_STRING;
+ }
+ ;
+
+/* Some stuff for handling enums */
+
+ename : identifier
+ | %empty { $$ = 0; }
+ ;
+
+constant_directives : constant_directive
+ | constant_directive constant_directives
+ ;
+
+optional_ignored_defines
+ : constant_directives
+ | %empty
+ ;
+
+/* Enum lists - any #define macros (constant directives) within the enum list are ignored. Trailing commas accepted. */
+
+/*
+ Note that "_last" attribute is not supposed to be set on the last enum element, as might be expected from its name, but on the _first_ one, and _only_ on it,
+ so we propagate it back to the first item while parsing and reset it on all the subsequent ones.
+ */
+
+enumlist : enumlist_item {
+ Setattr($enumlist_item,"_last",$enumlist_item);
+ $$ = $enumlist_item;
+ }
+ | enumlist_item DOXYGENPOSTSTRING {
+ Setattr($enumlist_item,"_last",$enumlist_item);
+ set_comment($enumlist_item, $DOXYGENPOSTSTRING);
+ $$ = $enumlist_item;
+ }
+ | enumlist_item DOXYGENSTRING {
+ Setattr($enumlist_item, "_last", $enumlist_item);
+ /* Misplaced doxygen string, attach it to previous parameter, like Doxygen does */
+ set_comment($enumlist_item, $DOXYGENSTRING);
+ $$ = $enumlist_item;
+ }
+ | enumlist_item COMMA enumlist[in] {
+ if ($in) {
+ set_nextSibling($enumlist_item, $in);
+ Setattr($enumlist_item,"_last",Getattr($in,"_last"));
+ Setattr($in,"_last",NULL);
+ } else {
+ Setattr($enumlist_item,"_last",$enumlist_item);
+ }
+ $$ = $enumlist_item;
+ }
+ | enumlist_item DOXYGENPOSTSTRING COMMA enumlist[in] {
+ if ($in) {
+ set_nextSibling($enumlist_item, $in);
+ Setattr($enumlist_item,"_last",Getattr($in,"_last"));
+ Setattr($in,"_last",NULL);
+ } else {
+ Setattr($enumlist_item,"_last",$enumlist_item);
+ }
+ set_comment($enumlist_item, $DOXYGENPOSTSTRING);
+ $$ = $enumlist_item;
+ }
+ | enumlist_item COMMA DOXYGENPOSTSTRING enumlist[in] {
+ if ($in) {
+ set_nextSibling($enumlist_item, $in);
+ Setattr($enumlist_item,"_last",Getattr($in,"_last"));
+ Setattr($in,"_last",NULL);
+ } else {
+ Setattr($enumlist_item,"_last",$enumlist_item);
+ }
+ set_comment($enumlist_item, $DOXYGENPOSTSTRING);
+ $$ = $enumlist_item;
+ }
+ | optional_ignored_defines {
+ $$ = 0;
+ }
+ ;
+
+enumlist_item : optional_ignored_defines edecl_with_dox optional_ignored_defines {
+ $$ = $edecl_with_dox;
+ }
+ ;
+
+edecl_with_dox : edecl
+ | DOXYGENSTRING edecl {
+ $$ = $edecl;
+ set_comment($edecl, $DOXYGENSTRING);
+ }
+ ;
+
+edecl : identifier {
+ SwigType *type = NewSwigType(T_INT);
+ $$ = new_node("enumitem");
+ Setattr($$,"name",$identifier);
+ Setattr($$,"type",type);
+ SetFlag($$,"feature:immutable");
+ Delete(type);
+ }
+ | identifier EQUAL etype {
+ SwigType *type = NewSwigType($etype.type == T_BOOL ? T_BOOL : ($etype.type == T_CHAR ? T_CHAR : T_INT));
+ $$ = new_node("enumitem");
+ Setattr($$,"name",$identifier);
+ Setattr($$,"type",type);
+ SetFlag($$,"feature:immutable");
+ Setattr($$,"enumvalue", $etype.val);
+ if ($etype.stringval) {
+ Setattr($$, "enumstringval", $etype.stringval);
+ }
+ if ($etype.numval) {
+ Setattr($$, "enumnumval", $etype.numval);
+ }
+ Setattr($$,"value",$identifier);
+ Delete(type);
+ }
+ ;
+
+etype : expr {
+ $$ = $expr;
+ /* We get T_USER here for a typedef - unfortunately we can't
+ * currently resolve typedefs at this stage of parsing. */
+ if (($$.type != T_INT) && ($$.type != T_UINT) &&
+ ($$.type != T_LONG) && ($$.type != T_ULONG) &&
+ ($$.type != T_LONGLONG) && ($$.type != T_ULONGLONG) &&
+ ($$.type != T_SHORT) && ($$.type != T_USHORT) &&
+ ($$.type != T_SCHAR) && ($$.type != T_UCHAR) &&
+ ($$.type != T_CHAR) && ($$.type != T_BOOL) &&
+ ($$.type != T_UNKNOWN) && ($$.type != T_USER)) {
+ Swig_error(cparse_file,cparse_line,"Type error. Expecting an integral type\n");
+ }
+ }
+ ;
+
+/* Arithmetic expressions. Used for constants, C++ templates, and other cool stuff. */
+
+expr : valexpr
+ | type {
+ Node *n;
+ $$ = default_dtype;
+ $$.val = $type;
+ $$.type = T_UNKNOWN;
+ /* Check if value is in scope */
+ n = Swig_symbol_clookup($type,0);
+ if (n) {
+ /* A band-aid for enum values used in expressions. */
+ if (Strcmp(nodeType(n),"enumitem") == 0) {
+ String *q = Swig_symbol_qualified(n);
+ if (q) {
+ $$.val = NewStringf("%s::%s", q, Getattr(n,"name"));
+ $$.type = SwigType_type(Getattr(n, "type"));
+ Delete(q);
+ }
+ } else {
+ SwigType *type = Getattr(n, "type");
+ if (type) {
+ $$.type = SwigType_type(type);
+ }
+ }
+ }
+ }
+ ;
+
+/* simple member access expressions */
+exprmem : ID[lhs] ARROW ID[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s->%s", $lhs, $rhs);
+ }
+ | ID[lhs] ARROW ID[rhs] LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.val = NewStringf("%s->%s%s", $lhs, $rhs, scanner_ccode);
+ Clear(scanner_ccode);
+ }
+ | exprmem[in] ARROW ID {
+ $$ = $in;
+ Printf($$.val, "->%s", $ID);
+ }
+ | exprmem[in] ARROW ID LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = $in;
+ Printf($$.val, "->%s%s", $ID, scanner_ccode);
+ Clear(scanner_ccode);
+ }
+ | ID[lhs] PERIOD ID[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s.%s", $lhs, $rhs);
+ }
+ | ID[lhs] PERIOD ID[rhs] LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.val = NewStringf("%s.%s%s", $lhs, $rhs, scanner_ccode);
+ Clear(scanner_ccode);
+ }
+ | exprmem[in] PERIOD ID {
+ $$ = $in;
+ Printf($$.val, ".%s", $ID);
+ }
+ | exprmem[in] PERIOD ID LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = $in;
+ Printf($$.val, ".%s%s", $ID, scanner_ccode);
+ Clear(scanner_ccode);
+ }
+ ;
+
+/* Non-compound expression */
+exprsimple : exprnum
+ | exprmem
+ | string {
+ $$ = default_dtype;
+ $$.stringval = $string;
+ $$.val = NewStringf("\"%(escape)s\"", $string);
+ $$.type = T_STRING;
+ }
+ | wstring {
+ $$ = default_dtype;
+ $$.stringval = $wstring;
+ $$.val = NewStringf("L\"%(escape)s\"", $wstring);
+ $$.type = T_WSTRING;
+ }
+ | CHARCONST {
+ $$ = default_dtype;
+ $$.stringval = $CHARCONST;
+ $$.val = NewStringf("'%(escape)s'", $CHARCONST);
+ $$.type = T_CHAR;
+ }
+ | WCHARCONST {
+ $$ = default_dtype;
+ $$.stringval = $WCHARCONST;
+ $$.val = NewStringf("L'%(escape)s'", $WCHARCONST);
+ $$.type = T_WCHAR;
+ }
+
+ /* In sizeof(X) X can be a type or expression. We don't actually
+ * need to parse X as the type of sizeof is always size_t (which
+ * SWIG handles as T_ULONG), so we just skip to the closing ')' and
+ * grab the skipped text to use in the value of the expression.
+ */
+ | SIZEOF LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.val = NewStringf("sizeof%s", scanner_ccode);
+ Clear(scanner_ccode);
+ $$.type = T_ULONG;
+ }
+ /* alignof(T) always has type size_t. */
+ | ALIGNOF LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.val = NewStringf("alignof%s", scanner_ccode);
+ Clear(scanner_ccode);
+ $$.type = T_ULONG;
+ }
+ /* noexcept(X) always has type bool. */
+ | NOEXCEPT LPAREN {
+ if (skip_balanced('(', ')') < 0) Exit(EXIT_FAILURE);
+ $$ = default_dtype;
+ $$.val = NewStringf("noexcept%s", scanner_ccode);
+ Clear(scanner_ccode);
+ $$.type = T_BOOL;
+ }
+ | SIZEOF ELLIPSIS LPAREN identifier RPAREN {
+ $$ = default_dtype;
+ $$.val = NewStringf("sizeof...(%s)", $identifier);
+ $$.type = T_ULONG;
+ }
+ /* `sizeof expr` without parentheses is valid for an expression,
+ * but not for a type. This doesn't support `sizeof x` (or
+ * `sizeof <unaryop> x` but that's unlikely to be seen in real
+ * code).
+ */
+ | SIZEOF exprsimple[in] {
+ $$ = default_dtype;
+ $$.val = NewStringf("sizeof(%s)", $in.val);
+ $$.type = T_ULONG;
+ }
+ ;
+
+valexpr : exprsimple
+ | exprcompound
+
+/* grouping */
+ | LPAREN expr RPAREN %prec CAST {
+ $$ = default_dtype;
+ $$.val = NewStringf("(%s)",$expr.val);
+ $$.stringval = Copy($expr.stringval);
+ $$.numval = Copy($expr.numval);
+ $$.type = $expr.type;
+ }
+
+/* A few common casting operations */
+
+ | LPAREN expr[lhs] RPAREN expr[rhs] %prec CAST {
+ int cast_type_code = SwigType_type($lhs.val);
+ $$ = $rhs;
+ $$.unary_arg_type = 0;
+ if ($rhs.type != T_STRING) {
+ switch ($lhs.type) {
+ case T_FLOAT:
+ case T_DOUBLE:
+ case T_LONGDOUBLE:
+ case T_FLTCPLX:
+ case T_DBLCPLX:
+ $$.val = NewStringf("(%s)%s", $lhs.val, $rhs.val); /* SwigType_str and decimal points don't mix! */
+ break;
+ default:
+ $$.val = NewStringf("(%s) %s", SwigType_str($lhs.val,0), $rhs.val);
+ break;
+ }
+ $$.stringval = 0;
+ $$.numval = 0;
+ }
+ /* As well as C-style casts, this grammar rule currently also
+ * matches a binary operator with a LHS in parentheses for
+ * binary operators which also have an unary form, e.g.:
+ *
+ * (6)*7
+ * (6)&7
+ * (6)+7
+ * (6)-7
+ */
+ if (cast_type_code != T_USER && cast_type_code != T_UNKNOWN) {
+ /* $lhs is definitely a type so we know this is a cast. */
+ $$.type = cast_type_code;
+ } else if ($rhs.type == 0 || $rhs.unary_arg_type == 0) {
+ /* Not one of the cases above, so we know this is a cast. */
+ $$.type = cast_type_code;
+ } else {
+ $$.type = promote($lhs.type, $rhs.unary_arg_type);
+ }
+ }
+ | LPAREN expr[lhs] pointer RPAREN expr[rhs] %prec CAST {
+ $$ = $rhs;
+ $$.unary_arg_type = 0;
+ if ($rhs.type != T_STRING) {
+ SwigType_push($lhs.val,$pointer);
+ $$.val = NewStringf("(%s) %s", SwigType_str($lhs.val,0), $rhs.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ }
+ }
+ | LPAREN expr[lhs] AND RPAREN expr[rhs] %prec CAST {
+ $$ = $rhs;
+ $$.unary_arg_type = 0;
+ if ($rhs.type != T_STRING) {
+ SwigType_add_reference($lhs.val);
+ $$.val = NewStringf("(%s) %s", SwigType_str($lhs.val,0), $rhs.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ }
+ }
+ | LPAREN expr[lhs] LAND RPAREN expr[rhs] %prec CAST {
+ $$ = $rhs;
+ $$.unary_arg_type = 0;
+ if ($rhs.type != T_STRING) {
+ SwigType_add_rvalue_reference($lhs.val);
+ $$.val = NewStringf("(%s) %s", SwigType_str($lhs.val,0), $rhs.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ }
+ }
+ | LPAREN expr[lhs] pointer AND RPAREN expr[rhs] %prec CAST {
+ $$ = $rhs;
+ $$.unary_arg_type = 0;
+ if ($rhs.type != T_STRING) {
+ SwigType_push($lhs.val,$pointer);
+ SwigType_add_reference($lhs.val);
+ $$.val = NewStringf("(%s) %s", SwigType_str($lhs.val,0), $rhs.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ }
+ }
+ | LPAREN expr[lhs] pointer LAND RPAREN expr[rhs] %prec CAST {
+ $$ = $rhs;
+ $$.unary_arg_type = 0;
+ if ($rhs.type != T_STRING) {
+ SwigType_push($lhs.val,$pointer);
+ SwigType_add_rvalue_reference($lhs.val);
+ $$.val = NewStringf("(%s) %s", SwigType_str($lhs.val,0), $rhs.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ }
+ }
+ | AND expr {
+ $$ = $expr;
+ $$.val = NewStringf("&%s", $expr.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)&7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $expr.type;
+ switch ($$.type) {
+ case T_CHAR:
+ $$.type = T_STRING;
+ break;
+ case T_WCHAR:
+ $$.type = T_WSTRING;
+ break;
+ default:
+ $$.type = T_POINTER;
+ }
+ }
+ | STAR expr {
+ $$ = $expr;
+ $$.val = NewStringf("*%s", $expr.val);
+ $$.stringval = 0;
+ $$.numval = 0;
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)*7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $expr.type;
+ switch ($$.type) {
+ case T_STRING:
+ $$.type = T_CHAR;
+ break;
+ case T_WSTRING:
+ $$.type = T_WCHAR;
+ break;
+ default:
+ $$.type = T_UNKNOWN;
+ }
+ }
+ ;
+
+exprnum : NUM_INT
+ | NUM_DOUBLE
+ | NUM_FLOAT
+ | NUM_LONGDOUBLE
+ | NUM_UNSIGNED
+ | NUM_LONG
+ | NUM_ULONG
+ | NUM_LONGLONG
+ | NUM_ULONGLONG
+ | NUM_BOOL
+ ;
+
+exprcompound : expr[lhs] PLUS expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s+%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] MINUS expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s-%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] STAR expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s*%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] SLASH expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s/%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] MODULO expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s%%%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] AND expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s&%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] OR expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s|%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] XOR expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s^%s", $lhs.val, $rhs.val);
+ $$.type = promote($lhs.type,$rhs.type);
+ }
+ | expr[lhs] LSHIFT expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s << %s", $lhs.val, $rhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] RSHIFT expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s >> %s", $lhs.val, $rhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] LAND expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s&&%s", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] LOR expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s||%s", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] EQUALTO expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s==%s", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] NOTEQUALTO expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s!=%s", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ /* Trying to parse `>` in the general case results in conflicts
+ * in the parser, but all user-reported cases are actually inside
+ * parentheses and we can handle that case.
+ */
+ | LPAREN expr[lhs] GREATERTHAN expr[rhs] RPAREN {
+ $$ = default_dtype;
+ $$.val = NewStringf("(%s > %s)", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+
+ /* Similarly for `<` except trying to handle exprcompound on the
+ * left side gives a shift/reduce conflict, so also restrict
+ * handling to non-compound subexpressions there. Again this
+ * covers all user-reported cases.
+ */
+ | LPAREN exprsimple[lhs] LESSTHAN expr[rhs] RPAREN {
+ $$ = default_dtype;
+ $$.val = NewStringf("(%s < %s)", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] GREATERTHANOREQUALTO expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s >= %s", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] LESSTHANOREQUALTO expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s <= %s", $lhs.val, $rhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+
+ // C++17 fold expressions.
+ //
+ // We don't handle unary left fold currently, since the obvious
+ // approach introduces shift/reduce conflicts. (Binary folds
+ // should be handled by composition of expressions.)
+ //
+ // Fold expressions using the following operators are not
+ // currently handled (because we don't actually seem to handle
+ // these operators in expressions at all!):
+ //
+ // = += -= *= /= %= ^= &= |= <<= >>= , .* ->*.
+ | expr[lhs] PLUS ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s+...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] MINUS ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s-...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] STAR ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s*...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] SLASH ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s/...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] MODULO ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s%%...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] AND ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s&...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] OR ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s|...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] XOR ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s^...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] LSHIFT ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s << ...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] RSHIFT ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s >> ...", $lhs.val);
+ $$.type = promote_type($lhs.type);
+ }
+ | expr[lhs] LAND ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s&&...", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] LOR ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s||...", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] EQUALTO ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s==...", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] NOTEQUALTO ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s!=...", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ /* Trying to parse `>` in the general case results in conflicts
+ * in the parser, but all user-reported cases are actually inside
+ * parentheses and we can handle that case.
+ */
+ | LPAREN expr[lhs] GREATERTHAN ELLIPSIS RPAREN {
+ $$ = default_dtype;
+ $$.val = NewStringf("(%s > ...)", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ /* Similarly for `<` except trying to handle exprcompound on the
+ * left side gives a shift/reduce conflict, so also restrict
+ * handling to non-compound subexpressions there. Again this
+ * covers all user-reported cases.
+ */
+ | LPAREN exprsimple[lhs] LESSTHAN ELLIPSIS RPAREN {
+ $$ = default_dtype;
+ $$.val = NewStringf("(%s < %s)", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] GREATERTHANOREQUALTO ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s >= ...", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | expr[lhs] LESSTHANOREQUALTO ELLIPSIS {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s <= ...", $lhs.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+
+ | expr[lhs] LESSEQUALGREATER expr[rhs] {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s <=> %s", $lhs.val, $rhs.val);
+ /* `<=>` returns one of `std::strong_ordering`,
+ * `std::partial_ordering` or `std::weak_ordering`. The main
+ * thing to do with the return value in this context is to
+ * compare it with another ordering of the same type or
+ * with a literal 0. We set .type = T_USER here which does
+ * what we want for the comparison operators, and also means
+ * that deduce_type() won't deduce a type for this (which is
+ * better than it deducing the wrong type).
+ */
+ $$.type = T_USER;
+ $$.unary_arg_type = 0;
+ }
+ | expr[expr1] QUESTIONMARK expr[expr2] COLON expr[expr3] %prec QUESTIONMARK {
+ $$ = default_dtype;
+ $$.val = NewStringf("%s?%s:%s", $expr1.val, $expr2.val, $expr3.val);
+ /* This may not be exactly right, but is probably good enough
+ * for the purposes of parsing constant expressions. */
+ $$.type = promote($expr2.type, $expr3.type);
+ }
+ | MINUS expr[in] %prec UMINUS {
+ $$ = default_dtype;
+ $$.val = NewStringf("-%s",$in.val);
+ if ($in.numval) {
+ switch ($in.type) {
+ case T_CHAR: // Unsigned on some architectures.
+ case T_UCHAR:
+ case T_USHORT:
+ case T_UINT:
+ case T_ULONG:
+ case T_ULONGLONG:
+ // Avoid negative numval with an unsigned type.
+ break;
+ default:
+ $$.numval = NewStringf("-%s", $in.numval);
+ break;
+ }
+ Delete($in.numval);
+ }
+ $$.type = promote_type($in.type);
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)-7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $in.type;
+ }
+ | PLUS expr[in] %prec UMINUS {
+ $$ = default_dtype;
+ $$.val = NewStringf("+%s",$in.val);
+ $$.numval = $in.numval;
+ $$.type = promote_type($in.type);
+ /* Record the type code for expr so we can properly handle
+ * cases such as (6)+7 which get parsed using this rule then
+ * the rule for a C-style cast.
+ */
+ $$.unary_arg_type = $in.type;
+ }
+ | NOT expr[in] {
+ $$ = default_dtype;
+ $$.val = NewStringf("~%s",$in.val);
+ $$.type = promote_type($in.type);
+ }
+ | LNOT expr[in] {
+ $$ = default_dtype;
+ $$.val = NewStringf("!%s", $in.val);
+ $$.type = cparse_cplusplus ? T_BOOL : T_INT;
+ }
+ | type LPAREN {
+ $$ = default_dtype;
+ String *qty;
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
+ qty = Swig_symbol_type_qualify($type,0);
+ if (SwigType_istemplate(qty)) {
+ String *nstr = SwigType_namestr(qty);
+ Delete(qty);
+ qty = nstr;
+ }
+ $$.val = NewStringf("%s%s",qty,scanner_ccode);
+ Clear(scanner_ccode);
+ /* Try to deduce the type - this could be a C++ "constructor
+ * cast" such as `double(4)` or a function call such as
+ * `some_func()`. In the latter case we get T_USER, but that
+ * is wrong so we map it to T_UNKNOWN until we can actually
+ * deduce the return type of a function call (which is
+ * complicated because the return type can vary between
+ * overloaded forms).
+ */
+ $$.type = SwigType_type(qty);
+ if ($$.type == T_USER) $$.type = T_UNKNOWN;
+ $$.unary_arg_type = 0;
+ Delete(qty);
+ }
+ ;
+
+variadic_opt : ELLIPSIS {
+ $$ = 1;
+ }
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+inherit : raw_inherit
+ ;
+
+raw_inherit : COLON { inherit_list = 1; } base_list { $$ = $base_list; inherit_list = 0; }
+ | %empty { $$ = 0; }
+ ;
+
+base_list : base_specifier {
+ Hash *list = NewHash();
+ Node *base = $base_specifier;
+ Node *name = Getattr(base,"name");
+ List *lpublic = NewList();
+ List *lprotected = NewList();
+ List *lprivate = NewList();
+ Setattr(list,"public",lpublic);
+ Setattr(list,"protected",lprotected);
+ Setattr(list,"private",lprivate);
+ Delete(lpublic);
+ Delete(lprotected);
+ Delete(lprivate);
+ Append(Getattr(list,Getattr(base,"access")),name);
+ $$ = list;
+ }
+
+ | base_list[in] COMMA base_specifier {
+ Hash *list = $in;
+ Node *base = $base_specifier;
+ Node *name = Getattr(base,"name");
+ Append(Getattr(list,Getattr(base,"access")),name);
+ $$ = list;
+ }
+ ;
+
+base_specifier : opt_virtual <intvalue>{
+ $$ = cparse_line;
+ }[line] idcolon variadic_opt {
+ $$ = NewHash();
+ Setfile($$, cparse_file);
+ Setline($$, $line);
+ Setattr($$, "name", $idcolon);
+ Setfile($idcolon, cparse_file);
+ Setline($idcolon, $line);
+ if (last_cpptype && (Strcmp(last_cpptype,"struct") != 0)) {
+ Setattr($$,"access","private");
+ Swig_warning(WARN_PARSE_NO_ACCESS, Getfile($$), Getline($$), "No access specifier given for base class '%s' (ignored).\n", SwigType_namestr($idcolon));
+ } else {
+ Setattr($$,"access","public");
+ }
+ if ($variadic_opt) {
+ SwigType_add_variadic(Getattr($$, "name"));
+ }
+ }
+ | opt_virtual access_specifier <intvalue>{
+ $$ = cparse_line;
+ }[line] opt_virtual idcolon variadic_opt {
+ $$ = NewHash();
+ Setfile($$, cparse_file);
+ Setline($$, $line);
+ Setattr($$, "name", $idcolon);
+ Setfile($idcolon, cparse_file);
+ Setline($idcolon, $line);
+ Setattr($$, "access", $access_specifier);
+ if (Strcmp($access_specifier, "public") != 0) {
+ Swig_warning(WARN_PARSE_PRIVATE_INHERIT, Getfile($$), Getline($$), "%s inheritance from base '%s' (ignored).\n", $access_specifier, SwigType_namestr($idcolon));
+ }
+ if ($variadic_opt) {
+ SwigType_add_variadic(Getattr($$, "name"));
+ }
+ }
+ ;
+
+access_specifier : PUBLIC { $$ = "public"; }
+ | PRIVATE { $$ = "private"; }
+ | PROTECTED { $$ = "protected"; }
+ ;
+
+templcpptype : CLASS variadic_opt {
+ $$ = NewString("class");
+ if (!inherit_list) last_cpptype = $$;
+ if ($variadic_opt) SwigType_add_variadic($$);
+ }
+ | TYPENAME variadic_opt {
+ $$ = NewString("typename");
+ if (!inherit_list) last_cpptype = $$;
+ if ($variadic_opt) SwigType_add_variadic($$);
+ }
+ ;
+
+cpptype : templcpptype
+ | STRUCT {
+ $$ = NewString("struct");
+ if (!inherit_list) last_cpptype = $$;
+ }
+ | UNION {
+ $$ = NewString("union");
+ if (!inherit_list) last_cpptype = $$;
+ }
+ ;
+
+classkey : CLASS {
+ if (!inherit_list) last_cpptype = NewString("class");
+ }
+ | STRUCT {
+ if (!inherit_list) last_cpptype = NewString("struct");
+ }
+ | UNION {
+ if (!inherit_list) last_cpptype = NewString("union");
+ }
+ ;
+
+classkeyopt : classkey
+ | %empty
+ ;
+
+opt_virtual : VIRTUAL
+ | %empty
+ ;
+
+virt_specifier_seq : OVERRIDE {
+ $$ = 0;
+ }
+ | FINAL {
+ $$ = NewString("1");
+ }
+ | FINAL OVERRIDE {
+ $$ = NewString("1");
+ }
+ | OVERRIDE FINAL {
+ $$ = NewString("1");
+ }
+ ;
+
+virt_specifier_seq_opt : virt_specifier_seq
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+class_virt_specifier_opt : FINAL {
+ $$ = NewString("1");
+ }
+ | %empty {
+ $$ = 0;
+ }
+ ;
+
+exception_specification : THROW LPAREN parms RPAREN {
+ $$ = default_dtype;
+ $$.throws = $parms;
+ $$.throwf = NewString("1");
+ }
+ | NOEXCEPT {
+ $$ = default_dtype;
+ $$.nexcept = NewString("true");
+ }
+ | virt_specifier_seq {
+ $$ = default_dtype;
+ $$.final = $virt_specifier_seq;
+ }
+ | THROW LPAREN parms RPAREN virt_specifier_seq {
+ $$ = default_dtype;
+ $$.throws = $parms;
+ $$.throwf = NewString("1");
+ $$.final = $virt_specifier_seq;
+ }
+ | NOEXCEPT virt_specifier_seq {
+ $$ = default_dtype;
+ $$.nexcept = NewString("true");
+ $$.final = $virt_specifier_seq;
+ }
+ | NOEXCEPT LPAREN expr RPAREN {
+ $$ = default_dtype;
+ $$.nexcept = $expr.val;
+ }
+ ;
+
+qualifiers_exception_specification : cv_ref_qualifier {
+ $$ = default_dtype;
+ $$.qualifier = $cv_ref_qualifier.qualifier;
+ $$.refqualifier = $cv_ref_qualifier.refqualifier;
+ }
+ | exception_specification {
+ $$ = $exception_specification;
+ }
+ | cv_ref_qualifier exception_specification {
+ $$ = $exception_specification;
+ $$.qualifier = $cv_ref_qualifier.qualifier;
+ $$.refqualifier = $cv_ref_qualifier.refqualifier;
+ }
+ ;
+
+cpp_const : qualifiers_exception_specification
+ | %empty {
+ $$ = default_dtype;
+ }
+ ;
+
+ctor_end : cpp_const ctor_initializer SEMI {
+ Clear(scanner_ccode);
+ $$ = default_decl;
+ $$.throws = $cpp_const.throws;
+ $$.throwf = $cpp_const.throwf;
+ $$.nexcept = $cpp_const.nexcept;
+ $$.final = $cpp_const.final;
+ if ($cpp_const.qualifier)
+ Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
+ }
+ | cpp_const ctor_initializer LBRACE {
+ if ($cpp_const.qualifier)
+ Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = default_decl;
+ $$.throws = $cpp_const.throws;
+ $$.throwf = $cpp_const.throwf;
+ $$.nexcept = $cpp_const.nexcept;
+ $$.final = $cpp_const.final;
+ }
+ | LPAREN parms RPAREN SEMI {
+ Clear(scanner_ccode);
+ $$ = default_decl;
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ | LPAREN parms RPAREN LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = default_decl;
+ $$.parms = $parms;
+ $$.have_parms = 1;
+ }
+ | EQUAL definetype SEMI {
+ $$ = default_decl;
+ $$.defarg = $definetype.val;
+ $$.stringdefarg = $definetype.stringval;
+ $$.numdefarg = $definetype.numval;
+ }
+ | exception_specification EQUAL default_delete SEMI {
+ $$ = default_decl;
+ $$.defarg = $default_delete.val;
+ $$.stringdefarg = $default_delete.stringval;
+ $$.numdefarg = $default_delete.numval;
+ $$.throws = $exception_specification.throws;
+ $$.throwf = $exception_specification.throwf;
+ $$.nexcept = $exception_specification.nexcept;
+ $$.final = $exception_specification.final;
+ if ($exception_specification.qualifier)
+ Swig_error(cparse_file, cparse_line, "Constructor cannot have a qualifier.\n");
+ }
+ ;
+
+ctor_initializer : COLON mem_initializer_list
+ | %empty
+ ;
+
+mem_initializer_list : mem_initializer
+ | mem_initializer_list COMMA mem_initializer
+ | mem_initializer ELLIPSIS
+ | mem_initializer_list COMMA mem_initializer ELLIPSIS
+ ;
+
+mem_initializer : idcolon LPAREN {
+ if (skip_balanced('(',')') < 0) Exit(EXIT_FAILURE);
+ Clear(scanner_ccode);
+ }
+ /* Uniform initialization in C++11.
+ Example:
+ struct MyStruct {
+ MyStruct(int x, double y) : x_{x}, y_{y} {}
+ int x_;
+ double y_;
+ };
+ */
+ | idcolon LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ Clear(scanner_ccode);
+ }
+ ;
+
+less_valparms_greater : LESSTHAN valparms GREATERTHAN {
+ String *s = NewStringEmpty();
+ SwigType_add_template(s,$valparms);
+ $$ = s;
+ scanner_last_id(1);
+ }
+ ;
+
+/* Identifiers including the C++11 identifiers with special meaning */
+identifier : ID
+ | OVERRIDE { $$ = Swig_copy_string("override"); }
+ | FINAL { $$ = Swig_copy_string("final"); }
+ ;
+
+idstring : identifier
+ | default_delete { $$ = Char($default_delete.val); }
+ | string { $$ = Char($string); }
+ ;
+
+idstringopt : idstring
+ | %empty { $$ = 0; }
+ ;
+
+idcolon : idtemplate idcolontail {
+ $$ = NewStringf("%s%s", $idtemplate, $idcolontail);
+ Delete($idcolontail);
+ }
+ | NONID DCOLON idtemplatetemplate idcolontail {
+ $$ = NewStringf("::%s%s",$idtemplatetemplate,$idcolontail);
+ Delete($idcolontail);
+ }
+ | idtemplate {
+ $$ = NewString($idtemplate);
+ }
+ | NONID DCOLON idtemplatetemplate {
+ $$ = NewStringf("::%s",$idtemplatetemplate);
+ }
+ | OPERATOR %expect 1 {
+ $$ = $OPERATOR;
+ }
+ | OPERATOR less_valparms_greater {
+ $$ = $OPERATOR;
+ Append($$, $less_valparms_greater);
+ Delete($less_valparms_greater);
+ }
+ | NONID DCOLON OPERATOR {
+ $$ = $OPERATOR;
+ Insert($$, 0, "::");
+ }
+ ;
+
+idcolontail : DCOLON idtemplatetemplate idcolontail[in] {
+ $$ = NewStringf("::%s%s",$idtemplatetemplate,$in);
+ Delete($in);
+ }
+ | DCOLON idtemplatetemplate {
+ $$ = NewStringf("::%s",$idtemplatetemplate);
+ }
+ | DCOLON OPERATOR {
+ $$ = $OPERATOR;
+ Insert($$, 0, "::");
+ }
+ | DCNOT idtemplate {
+ $$ = NewStringf("::~%s",$idtemplate);
+ }
+ ;
+
+
+idtemplate : identifier {
+ $$ = NewString($identifier);
+ }
+ | identifier less_valparms_greater {
+ $$ = NewString($identifier);
+ Append($$, $less_valparms_greater);
+ Delete($less_valparms_greater);
+ }
+ ;
+
+idtemplatetemplate : idtemplate
+ | TEMPLATE identifier less_valparms_greater {
+ $$ = NewString($identifier);
+ Append($$, $less_valparms_greater);
+ Delete($less_valparms_greater);
+ }
+ ;
+
+/* Identifier, but no templates */
+idcolonnt : identifier idcolontailnt {
+ $$ = NewStringf("%s%s", $identifier, $idcolontailnt);
+ Delete($idcolontailnt);
+ }
+ | NONID DCOLON identifier idcolontailnt {
+ $$ = NewStringf("::%s%s",$identifier,$idcolontailnt);
+ Delete($idcolontailnt);
+ }
+ | identifier {
+ $$ = NewString($identifier);
+ }
+ | NONID DCOLON identifier {
+ $$ = NewStringf("::%s",$identifier);
+ }
+ | OPERATOR {
+ $$ = $OPERATOR;
+ }
+ | NONID DCOLON OPERATOR {
+ $$ = $OPERATOR;
+ Insert($$, 0, "::");
+ }
+ ;
+
+idcolontailnt : DCOLON identifier idcolontailnt[in] {
+ $$ = NewStringf("::%s%s",$identifier,$in);
+ Delete($in);
+ }
+ | DCOLON identifier {
+ $$ = NewStringf("::%s",$identifier);
+ }
+ | DCOLON OPERATOR {
+ $$ = $OPERATOR;
+ Insert($$, 0, "::");
+ }
+ | DCNOT identifier {
+ $$ = NewStringf("::~%s",$identifier);
+ }
+ ;
+
+/* Concatenated strings */
+string : string[in] STRING {
+ $$ = $in;
+ Append($$, $STRING);
+ Delete($STRING);
+ }
+ | STRING
+ ;
+wstring : wstring[in] WSTRING {
+ // Concatenated wide strings: L"str1" L"str2"
+ $$ = $in;
+ Append($$, $WSTRING);
+ Delete($WSTRING);
+ }
+ | wstring[in] STRING {
+ // Concatenated wide string and normal string literal: L"str1" "str2" (C++11).
+ $$ = $in;
+ Append($$, $STRING);
+ Delete($STRING);
+ }
+ | string[in] WSTRING {
+ // Concatenated normal string and wide string literal: "str1" L"str2" (C++11).
+ $$ = $in;
+ Append($$, $WSTRING);
+ Delete($WSTRING);
+ }
+ | WSTRING
+ ;
+
+stringbrace : string
+ | LBRACE {
+ if (skip_balanced('{','}') < 0) Exit(EXIT_FAILURE);
+ $$ = NewString(scanner_ccode);
+ }
+ | HBLOCK
+ ;
+
+options : LPAREN kwargs RPAREN {
+ Hash *n;
+ $$ = NewHash();
+ n = $kwargs;
+ while(n) {
+ String *name, *value;
+ name = Getattr(n,"name");
+ value = Getattr(n,"value");
+ if (!value) value = (String *) "1";
+ Setattr($$,name, value);
+ n = nextSibling(n);
+ }
+ }
+ | %empty { $$ = 0; };
+
+
+/* Keyword arguments */
+kwargs : kwargs_builder {
+ $$ = $kwargs_builder.node;
+ }
+ ;
+
+kwargs_builder : idstring EQUAL stringnum {
+ Node *n = NewHash();
+ Setattr(n, "name", $idstring);
+ Setattr(n, "value", $stringnum);
+ Delete($stringnum);
+ $$.node = $$.last = n;
+ }
+ | kwargs_builder[in] COMMA idstring EQUAL stringnum {
+ $$ = $in;
+ Node *n = NewHash();
+ Setattr(n, "name", $idstring);
+ Setattr(n, "value", $stringnum);
+ Delete($stringnum);
+ set_nextSibling($$.last, n);
+ $$.last = n;
+ }
+ | idstring {
+ Node *n = NewHash();
+ Setattr(n, "name", $idstring);
+ $$.node = $$.last = n;
+ }
+ | kwargs_builder[in] COMMA idstring {
+ $$ = $in;
+ Node *n = NewHash();
+ Setattr(n, "name", $idstring);
+ set_nextSibling($$.last, n);
+ $$.last = n;
+ }
+ | idstring EQUAL stringtype {
+ Node *n = $stringtype;
+ Setattr(n, "name", $idstring);
+ $$.node = $$.last = n;
+ }
+ | kwargs_builder[in] COMMA idstring EQUAL stringtype {
+ $$ = $in;
+ Node *n = $stringtype;
+ Setattr(n, "name", $idstring);
+ set_nextSibling($$.last, n);
+ $$.last = n;
+ }
+ ;
+
+stringnum : string
+ | exprnum {
+ $$ = $exprnum.val;
+ }
+ ;
+
+%%
+
+SwigType *Swig_cparse_type(String *s) {
+ String *ns;
+ ns = NewString(s);
+ Seek(ns,0,SEEK_SET);
+ scanner_file(ns);
+ top = 0;
+ scanner_next_token(PARSETYPE);
+ if (yyparse() == 2) {
+ Swig_error(cparse_file, cparse_line, "Parser exceeded stack depth or ran out of memory\n");
+ Exit(EXIT_FAILURE);
+ }
+ /* Printf(stdout,"typeparse: '%s' ---> '%s'\n", s, top); */
+ return (SwigType *)top;
+}
+
+
+Parm *Swig_cparse_parm(String *s) {
+ String *ns;
+ ns = NewString(s);
+ Seek(ns,0,SEEK_SET);
+ scanner_file(ns);
+ top = 0;
+ scanner_next_token(PARSEPARM);
+ if (yyparse() == 2) {
+ Swig_error(cparse_file, cparse_line, "Parser exceeded stack depth or ran out of memory\n");
+ Exit(EXIT_FAILURE);
+ }
+ /* Printf(stdout,"parmparse: '%s' ---> '%s'\n", s, top); */
+ Delete(ns);
+ return (Parm *)top;
+}
+
+
+ParmList *Swig_cparse_parms(String *s, Node *file_line_node) {
+ String *ns;
+ char *cs = Char(s);
+ if (cs && cs[0] != '(') {
+ ns = NewStringf("(%s)",s);
+ } else {
+ ns = NewString(s);
+ }
+ Setfile(ns, Getfile(file_line_node));
+ Setline(ns, Getline(file_line_node));
+ Seek(ns,0,SEEK_SET);
+ scanner_file(ns);
+ top = 0;
+ scanner_next_token(PARSEPARMS);
+ if (yyparse() == 2) {
+ Swig_error(cparse_file, cparse_line, "Parser exceeded stack depth or ran out of memory\n");
+ Exit(EXIT_FAILURE);
+ }
+ /* Printf(stdout,"parmsparse: '%s' ---> '%s'\n", s, top); */
+ return (ParmList *)top;
+}
+
diff --git a/contrib/tools/swig/Source/CParse/templ.c b/contrib/tools/swig/Source/CParse/templ.c
new file mode 100644
index 00000000000..253797b7f0b
--- /dev/null
+++ b/contrib/tools/swig/Source/CParse/templ.c
@@ -0,0 +1,1424 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * templ.c
+ *
+ * Expands a template into a specialized version.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+static int template_debug = 0;
+
+
+const char *baselists[3];
+
+void SwigType_template_init(void) {
+ baselists[0] = "baselist";
+ baselists[1] = "protectedbaselist";
+ baselists[2] = "privatebaselist";
+}
+
+void Swig_cparse_debug_templates(int x) {
+ template_debug = x;
+}
+
+/* -----------------------------------------------------------------------------
+ * add_parms()
+ *
+ * Add the value and type of each parameter into patchlist and typelist
+ * (List of String/SwigType) for later template parameter substitutions.
+ * ----------------------------------------------------------------------------- */
+
+static void add_parms(ParmList *p, List *patchlist, List *typelist, int is_pattern) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ SwigType *val = Getattr(p, "value");
+ Append(typelist, ty);
+ if (is_pattern) {
+ /* Typemap patterns are not simple parameter lists.
+ * Output style ("out", "ret" etc) typemap names can be
+ * qualified names and so may need template expansion */
+ SwigType *name = Getattr(p, "name");
+ Append(typelist, name);
+ }
+ Append(patchlist, val);
+ p = nextSibling(p);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * expand_variadic_parms()
+ *
+ * Expand variadic parameter in the parameter list stored as attribute in n. For example:
+ * template <typename... T> struct X : { X(T&... tt); }
+ * %template(XABC) X<A,B,C>;
+ * inputs for the constructor parameter list will be for attribute = "parms":
+ * Getattr(n, attribute) : v.r.T tt
+ * unexpanded_variadic_parm: v.typename T
+ * expanded_variadic_parms : A,B,C
+ * results in:
+ * Getattr(n, attribute) : r.A,r.B,r.C
+ * that is, template is expanded as: struct XABC : { X(A&,B&,C&); }
+ * Note that there are no parameter names are in the expanded parameter list.
+ * Nothing happens if the parameter list has no variadic parameters.
+ * ----------------------------------------------------------------------------- */
+
+static void expand_variadic_parms(Node *n, const char *attribute, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms) {
+ ParmList *p = Getattr(n, attribute);
+ if (unexpanded_variadic_parm) {
+ Parm *variadic = ParmList_variadic_parm(p);
+ if (variadic) {
+ SwigType *type = Getattr(variadic, "type");
+ String *name = Getattr(variadic, "name");
+ String *unexpanded_name = Getattr(unexpanded_variadic_parm, "name");
+ ParmList *expanded = CopyParmList(expanded_variadic_parms);
+ Parm *ep = expanded;
+ int i = 0;
+ while (ep) {
+ SwigType *newtype = Copy(type);
+ SwigType_del_variadic(newtype);
+ Replaceid(newtype, unexpanded_name, Getattr(ep, "type"));
+ Setattr(ep, "type", newtype);
+ Setattr(ep, "name", name ? NewStringf("%s%d", name, ++i) : 0);
+ ep = nextSibling(ep);
+ }
+ expanded = ParmList_replace_last(p, expanded);
+ Setattr(n, attribute, expanded);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * expand_parms()
+ *
+ * Expand variadic parameters in parameter lists and add parameters to patchlist
+ * and typelist for later template parameter substitutions.
+ * ----------------------------------------------------------------------------- */
+
+static void expand_parms(Node *n, const char *attribute, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms, List *patchlist, List *typelist, int is_pattern) {
+ ParmList *p;
+ expand_variadic_parms(n, attribute, unexpanded_variadic_parm, expanded_variadic_parms);
+ p = Getattr(n, attribute);
+ add_parms(p, patchlist, typelist, is_pattern);
+}
+
+/* -----------------------------------------------------------------------------
+ * cparse_template_expand()
+ *
+ * Expands a template node into a specialized version. This is done by
+ * patching typenames and other aspects of the node according to a list of
+ * template parameters
+ * ----------------------------------------------------------------------------- */
+
+static void cparse_template_expand(Node *templnode, Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms) {
+ static int expanded = 0;
+ String *nodeType;
+ if (!n)
+ return;
+ nodeType = nodeType(n);
+ if (Getattr(n, "error"))
+ return;
+
+ if (Equal(nodeType, "template")) {
+ /* Change the node type back to normal */
+ if (!expanded) {
+ expanded = 1;
+ set_nodeType(n, Getattr(n, "templatetype"));
+ cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms);
+ expanded = 0;
+ return;
+ } else {
+ /* Called when template appears inside another template */
+ /* Member templates */
+
+ set_nodeType(n, Getattr(n, "templatetype"));
+ cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms);
+ set_nodeType(n, "template");
+ return;
+ }
+ } else if (Equal(nodeType, "cdecl")) {
+ /* A simple C declaration */
+ SwigType *t, *v, *d;
+ String *code;
+ t = Getattr(n, "type");
+ v = Getattr(n, "value");
+ d = Getattr(n, "decl");
+
+ code = Getattr(n, "code");
+
+ Append(typelist, t);
+ Append(typelist, d);
+ Append(patchlist, v);
+ Append(cpatchlist, code);
+
+ if (Getattr(n, "conversion_operator")) {
+ /* conversion operator "name" and "sym:name" attributes are unusual as they contain c++ types, so treat as code for patching */
+ Append(cpatchlist, Getattr(n, "name"));
+ if (Getattr(n, "sym:name")) {
+ Append(cpatchlist, Getattr(n, "sym:name"));
+ }
+ }
+ if (Strstr(Getattr(n, "storage"), "friend")) {
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ String *stripped_name = SwigType_templateprefix(symname);
+ Setattr(n, "sym:name", stripped_name);
+ Delete(stripped_name);
+ }
+ Append(typelist, Getattr(n, "name"));
+ }
+
+ expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+ expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+
+ } else if (Equal(nodeType, "class")) {
+ /* Patch base classes */
+ {
+ int b = 0;
+ for (b = 0; b < 3; ++b) {
+ List *bases = Getattr(n, baselists[b]);
+ if (bases) {
+ int i;
+ int ilen = Len(bases);
+ for (i = 0; i < ilen; i++) {
+ String *name = Copy(Getitem(bases, i));
+ if (SwigType_isvariadic(name)) {
+ Parm *parm = NewParmWithoutFileLineInfo(name, 0);
+ Node *temp_parm_node = NewHash();
+ Setattr(temp_parm_node, "variadicbaseparms", parm);
+ assert(i == ilen - 1);
+ Delitem(bases, i);
+ expand_variadic_parms(temp_parm_node, "variadicbaseparms", unexpanded_variadic_parm, expanded_variadic_parms);
+ {
+ Parm *vp = Getattr(temp_parm_node, "variadicbaseparms");
+ while (vp) {
+ String *name = Copy(Getattr(vp, "type"));
+ Append(bases, name);
+ Append(typelist, name);
+ vp = nextSibling(vp);
+ }
+ }
+ Delete(temp_parm_node);
+ } else {
+ Setitem(bases, i, name);
+ Append(typelist, name);
+ }
+ }
+ }
+ }
+ }
+ /* Patch children */
+ {
+ Node *cn = firstChild(n);
+ while (cn) {
+ cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms);
+ cn = nextSibling(cn);
+ }
+ }
+ } else if (Equal(nodeType, "classforward")) {
+ /* Nothing to expand */
+ } else if (Equal(nodeType, "constructor")) {
+ if (!(Getattr(n, "templatetype"))) {
+ String *symname = Getattr(n, "sym:name");
+ String *name;
+ if (symname) {
+ String *stripped_name = SwigType_templateprefix(symname);
+ if (Strstr(tname, stripped_name)) {
+ Replaceid(symname, stripped_name, tname);
+ }
+ Delete(stripped_name);
+ }
+ name = Getattr(n, "sym:name");
+ if (name) {
+ if (strchr(Char(name), '<')) {
+ Clear(name);
+ Append(name, rname);
+ } else {
+ String *tmp = Copy(name);
+ Replace(tmp, tname, rname, DOH_REPLACE_ANY);
+ Clear(name);
+ Append(name, tmp);
+ Delete(tmp);
+ }
+ }
+ }
+ Append(cpatchlist, Getattr(n, "code"));
+ Append(typelist, Getattr(n, "decl"));
+ expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+ expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+ } else if (Equal(nodeType, "destructor")) {
+ /* We only need to patch the dtor of the template itself, not the destructors of any nested classes, so check that the parent of this node is the root
+ * template node, with the special exception for %extend which adds its methods under an intermediate node. */
+ Node* parent = parentNode(n);
+ if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) {
+ String *symname = Getattr(n, "sym:name");
+ if (symname)
+ Replace(symname, tname, rname, DOH_REPLACE_ANY);
+ Append(cpatchlist, Getattr(n, "code"));
+ }
+ } else if (Equal(nodeType, "using")) {
+ String *name = Getattr(n, "name");
+ String *uname = Getattr(n, "uname");
+ if (uname && strchr(Char(uname), '<')) {
+ Append(patchlist, uname);
+ }
+ if (!(Getattr(n, "templatetype"))) {
+ /* Copied from handling "constructor" .. not sure if all this is needed */
+ String *symname;
+ String *stripped_name = SwigType_templateprefix(name);
+ if (Strstr(tname, stripped_name)) {
+ Replaceid(name, stripped_name, tname);
+ }
+ Delete(stripped_name);
+ symname = Getattr(n, "sym:name");
+ if (symname) {
+ stripped_name = SwigType_templateprefix(symname);
+ if (Strstr(tname, stripped_name)) {
+ Replaceid(symname, stripped_name, tname);
+ }
+ Delete(stripped_name);
+ }
+ if (strchr(Char(name), '<')) {
+ Append(patchlist, Getattr(n, "name"));
+ }
+ name = Getattr(n, "sym:name");
+ if (name) {
+ if (strchr(Char(name), '<')) {
+ Clear(name);
+ Append(name, rname);
+ } else {
+ String *tmp = Copy(name);
+ Replace(tmp, tname, rname, DOH_REPLACE_ANY);
+ Clear(name);
+ Append(name, tmp);
+ Delete(tmp);
+ }
+ }
+ }
+
+ if (Getattr(n, "namespace")) {
+ /* Namespace link. This is nasty. Is other namespace defined? */
+
+ }
+ } else {
+ /* Look for obvious parameters */
+ Node *cn;
+ Append(cpatchlist, Getattr(n, "code"));
+ Append(typelist, Getattr(n, "type"));
+ Append(typelist, Getattr(n, "decl"));
+ expand_parms(n, "parms", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+ expand_parms(n, "kwargs", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+ expand_parms(n, "pattern", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 1);
+ expand_parms(n, "throws", unexpanded_variadic_parm, expanded_variadic_parms, cpatchlist, typelist, 0);
+ cn = firstChild(n);
+ while (cn) {
+ cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms);
+ cn = nextSibling(cn);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * cparse_fix_function_decl()
+ *
+ * Move the prefix of the "type" attribute (excluding any trailing qualifier)
+ * to the end of the "decl" attribute.
+ * Examples:
+ * decl="f().", type="p.q(const).char" => decl="f().p.", type="q(const).char"
+ * decl="f().p.", type="p.SomeClass" => decl="f().p.p.", type="SomeClass"
+ * decl="f().", type="r.q(const).p.int" => decl="f().r.q(const).p.", type="int"
+ * ----------------------------------------------------------------------------- */
+
+static void cparse_fix_function_decl(String *name, SwigType *decl, SwigType *type) {
+ String *prefix;
+ int prefixLen;
+ SwigType *last;
+
+ /* The type's prefix is what potentially has to be moved to the end of 'decl' */
+ prefix = SwigType_prefix(type);
+
+ /* First some parts (qualifier and array) have to be removed from prefix
+ in order to remain in the 'type' attribute. */
+ last = SwigType_last(prefix);
+ while (last) {
+ if (SwigType_isqualifier(last) || SwigType_isarray(last)) {
+ /* Keep this part in the 'type' */
+ Delslice(prefix, Len(prefix) - Len(last), DOH_END);
+ Delete(last);
+ last = SwigType_last(prefix);
+ } else {
+ /* Done with processing prefix */
+ Delete(last);
+ last = 0;
+ }
+ }
+
+ /* Transfer prefix from the 'type' to the 'decl' attribute */
+ prefixLen = Len(prefix);
+ if (prefixLen > 0) {
+ Append(decl, prefix);
+ Delslice(type, 0, prefixLen);
+ if (template_debug) {
+ Printf(stdout, " change function '%s' to type='%s', decl='%s'\n", name, type, decl);
+ }
+ }
+
+ Delete(prefix);
+}
+
+/* -----------------------------------------------------------------------------
+ * cparse_postprocess_expanded_template()
+ *
+ * This function postprocesses the given node after template expansion.
+ * Currently the only task to perform is fixing function decl and type attributes.
+ * ----------------------------------------------------------------------------- */
+
+static void cparse_postprocess_expanded_template(Node *n) {
+ String *nodeType;
+ if (!n)
+ return;
+ nodeType = nodeType(n);
+ if (Getattr(n, "error"))
+ return;
+
+ if (Equal(nodeType, "cdecl")) {
+ /* A simple C declaration */
+ SwigType *d = Getattr(n, "decl");
+ if (d && SwigType_isfunction(d)) {
+ /* A function node */
+ SwigType *t = Getattr(n, "type");
+ if (t) {
+ String *name = Getattr(n, "name");
+ cparse_fix_function_decl(name, d, t);
+ }
+ }
+ } else {
+ /* Look for any children */
+ Node *cn = firstChild(n);
+ while (cn) {
+ cparse_postprocess_expanded_template(cn);
+ cn = nextSibling(cn);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * partial_arg()
+ *
+ * Return a parameter with type that matches the specialized template argument.
+ * If the input has no partial type, the name is not set in the returned parameter.
+ *
+ * type: an instantiated template parameter type, for example: Vect<(int)>
+ * partialtype: type from specialized template where parameter name has been
+ * replaced by a $ variable, for example: Vect<($1)>
+ *
+ * Returns a parameter of type 'int' and name $1 for the two example parameters above.
+ * ----------------------------------------------------------------------------- */
+
+static Parm *partial_arg(const SwigType *type, const SwigType *partialtype) {
+ SwigType *parmtype;
+ String *parmname = 0;
+ const char *cp = Char(partialtype);
+ const char *c = strchr(cp, '$');
+
+ if (c) {
+ int suffix_length;
+ int prefix_length = (int)(c - cp);
+ int type_length = Len(type);
+ const char *suffix = c;
+ String *prefix = NewStringWithSize(cp, prefix_length);
+ while (++suffix) {
+ if (!isdigit((int)*suffix))
+ break;
+ }
+ parmname = NewStringWithSize(c, (int)(suffix - c)); /* $1, $2 etc */
+ suffix_length = (int)strlen(suffix);
+ assert(Strstr(type, prefix) == Char(type)); /* check that the start of both types match */
+ assert(strcmp(Char(type) + type_length - suffix_length, suffix) == 0); /* check that the end of both types match */
+ parmtype = NewStringWithSize(Char(type) + prefix_length, type_length - suffix_length - prefix_length);
+ Delete(prefix);
+ } else {
+ parmtype = Copy(type);
+ }
+ return NewParmWithoutFileLineInfo(parmtype, parmname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_template_expand()
+ * ----------------------------------------------------------------------------- */
+
+int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope) {
+ List *patchlist, *cpatchlist, *typelist;
+ String *templateargs;
+ String *tname;
+ String *name_with_templateargs = 0;
+ String *tbase;
+ Parm *unexpanded_variadic_parm = 0;
+ ParmList *expanded_variadic_parms = 0;
+ ParmList *templateparms = Getattr(n, "templateparms");
+ ParmList *templateparmsraw = 0;
+ patchlist = NewList(); /* List of String * ("name" and "value" attributes) */
+ cpatchlist = NewList(); /* List of String * (code) */
+ typelist = NewList(); /* List of SwigType * types */
+
+ templateargs = NewStringEmpty();
+ SwigType_add_template(templateargs, tparms);
+
+ tname = Copy(Getattr(n, "name"));
+ tbase = Swig_scopename_last(tname);
+
+ if (Getattr(n, "partialargs")) {
+ /* Partial specialization */
+ Parm *p, *tp;
+ ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n);
+ p = ptargs;
+ tp = tparms;
+ /* Adjust templateparms so that the type is expanded, eg typename => int */
+ while (p && tp) {
+ SwigType *ptype;
+ SwigType *tptype;
+ SwigType *partial_type;
+ ptype = Getattr(p, "type");
+ tptype = Getattr(tp, "type");
+ if (ptype && tptype) {
+ SwigType *ty = Swig_symbol_typedef_reduce(tptype, tscope);
+ Parm *partial_parm = partial_arg(ty, ptype);
+ String *partial_name = Getattr(partial_parm, "name");
+ partial_type = Copy(Getattr(partial_parm, "type"));
+ /* Printf(stdout,"partial '%s' '%s' ---> '%s'\n", tptype, ptype, partial_type); */
+ if (partial_name && strchr(Char(partial_name), '$') == Char(partial_name)) {
+ int index = atoi(Char(partial_name) + 1) - 1;
+ Parm *parm;
+ assert(index >= 0);
+ parm = ParmList_nth_parm(templateparms, index);
+ assert(parm);
+ if (parm) {
+ Setattr(parm, "type", partial_type);
+ }
+ }
+ Delete(partial_parm);
+ Delete(partial_type);
+ Delete(ty);
+ }
+ p = nextSibling(p);
+ tp = nextSibling(tp);
+ }
+ Delete(ptargs);
+ } else {
+ Setattr(n, "templateparmsraw", Getattr(n, "templateparms"));
+ templateparms = CopyParmList(tparms);
+ Setattr(n, "templateparms", templateparms);
+ }
+
+ /* TODO: variadic parms for partially specialized templates */
+ templateparmsraw = Getattr(n, "templateparmsraw");
+ unexpanded_variadic_parm = ParmList_variadic_parm(templateparmsraw);
+ if (unexpanded_variadic_parm)
+ expanded_variadic_parms = ParmList_nth_parm(templateparms, ParmList_len(templateparmsraw) - 1);
+
+ /* Printf(stdout,"targs = '%s'\n", templateargs);
+ Printf(stdout,"rname = '%s'\n", rname);
+ Printf(stdout,"tname = '%s'\n", tname); */
+ cparse_template_expand(n, n, tname, rname, templateargs, patchlist, typelist, cpatchlist, unexpanded_variadic_parm, expanded_variadic_parms);
+
+ /* Set the name */
+ {
+ String *name = Getattr(n, "name");
+ if (name) {
+ String *nodeType = nodeType(n);
+ name_with_templateargs = NewStringf("%s%s", name, templateargs);
+ if (!(Equal(nodeType, "constructor") || Equal(nodeType, "destructor"))) {
+ Setattr(n, "name", name_with_templateargs);
+ }
+ }
+ }
+
+ /* Patch all of the types */
+ {
+ Parm *tp = Getattr(n, "templateparms");
+ /* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
+
+ if (tp) {
+ Symtab *tsdecl = Getattr(n, "sym:symtab");
+ String *tsname = Getattr(n, "sym:name");
+ while (tp) {
+ String *name, *value, *valuestr, *tmp, *tmpr;
+ int sz, i;
+ String *dvalue = 0;
+ String *qvalue = 0;
+
+ name = Getattr(tp, "name");
+ value = Getattr(tp, "value");
+
+ if (name) {
+ if (!value)
+ value = Getattr(tp, "type");
+ qvalue = Swig_symbol_typedef_reduce(value, tsdecl);
+ dvalue = Swig_symbol_type_qualify(qvalue, tsdecl);
+ if (SwigType_istemplate(dvalue)) {
+ String *ty = Swig_symbol_template_deftype(dvalue, tscope);
+ Delete(dvalue);
+ dvalue = ty;
+ }
+
+ assert(dvalue);
+ valuestr = SwigType_str(dvalue, 0);
+ sz = Len(patchlist);
+ for (i = 0; i < sz; i++) {
+ /* Patch String or SwigType with SwigType, eg T => int in Foo<(T)>, or TT => Hello<(int)> in X<(TT)>::meth */
+ String *s = Getitem(patchlist, i);
+ Replace(s, name, dvalue, DOH_REPLACE_ID);
+ }
+
+ sz = Len(typelist);
+ for (i = 0; i < sz; i++) {
+ SwigType *s = Getitem(typelist, i);
+ Node *tynode;
+ String *tyname;
+
+ SwigType_variadic_replace(s, unexpanded_variadic_parm, expanded_variadic_parms);
+
+ /*
+ The approach of 'trivially' replacing template arguments is kind of fragile.
+ In particular if types with similar name in different namespaces appear.
+ We will not replace template args if a type/class exists with the same
+ name which is not a template.
+ */
+ tynode = Swig_symbol_clookup(s, 0);
+ tyname = tynode ? Getattr(tynode, "sym:name") : 0;
+ /*
+ Printf(stdout, " replacing %s with %s to %s or %s to %s\n", s, name, dvalue, tbase, name_with_templateargs);
+ Printf(stdout, " %d %s to %s\n", tp == unexpanded_variadic_parm, name, ParmList_str_defaultargs(expanded_variadic_parms));
+ */
+ if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) {
+ SwigType_typename_replace(s, name, dvalue);
+ SwigType_typename_replace(s, tbase, name_with_templateargs);
+ }
+ }
+
+ tmp = NewStringf("#%s", name);
+ tmpr = NewStringf("\"%s\"", valuestr);
+
+ sz = Len(cpatchlist);
+ for (i = 0; i < sz; i++) {
+ /* Patch String with C++ String type, eg T => int in Foo< T >, or TT => Hello< int > in X< TT >::meth */
+ String *s = Getitem(cpatchlist, i);
+ /* Stringising that ought to be done in the preprocessor really, eg #T => "int" */
+ Replace(s, tmp, tmpr, DOH_REPLACE_ID);
+ Replace(s, name, valuestr, DOH_REPLACE_ID);
+ }
+ Delete(tmp);
+ Delete(tmpr);
+ Delete(valuestr);
+ Delete(dvalue);
+ Delete(qvalue);
+ }
+ tp = nextSibling(tp);
+ }
+ } else {
+ /* No template parameters at all. This could be a specialization */
+ int i, sz;
+ sz = Len(typelist);
+ for (i = 0; i < sz; i++) {
+ String *s = Getitem(typelist, i);
+ SwigType_variadic_replace(s, unexpanded_variadic_parm, expanded_variadic_parms);
+ SwigType_typename_replace(s, tbase, name_with_templateargs);
+ }
+ }
+ }
+ cparse_postprocess_expanded_template(n);
+
+ /* Patch bases */
+ {
+ List *bases = Getattr(n, "baselist");
+ if (bases) {
+ Iterator b;
+ for (b = First(bases); b.item; b = Next(b)) {
+ String *qn = Swig_symbol_type_qualify(b.item, tscope);
+ Clear(b.item);
+ Append(b.item, qn);
+ Delete(qn);
+ }
+ }
+ }
+ Delete(name_with_templateargs);
+ Delete(patchlist);
+ Delete(cpatchlist);
+ Delete(typelist);
+ Delete(tbase);
+ Delete(tname);
+ Delete(templateargs);
+
+ return 0;
+}
+
+typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpecializedMatch = 1, ExactMatch = 2 } EMatch;
+
+/* -----------------------------------------------------------------------------
+ * is_exact_partial_type()
+ *
+ * Return 1 if parm matches $1, $2, $3 etc exactly without any other prefixes or
+ * suffixes. Return 0 otherwise.
+ * ----------------------------------------------------------------------------- */
+
+static int is_exact_partial_type(const SwigType *type) {
+ const char *c = Char(type);
+ int is_exact = 0;
+ if (*c == '$' && isdigit((int)*(c + 1))) {
+ const char *suffix = c + 1;
+ while (++suffix) {
+ if (!isdigit((int)*suffix))
+ break;
+ }
+ is_exact = (*suffix == 0);
+ }
+ return is_exact;
+}
+
+/* -----------------------------------------------------------------------------
+ * does_parm_match()
+ *
+ * Template argument deduction - check if a template type matches a partially specialized
+ * template parameter type. Typedef reduce 'partial_parm_type' to see if it matches 'type'.
+ *
+ * type - template parameter type to match against
+ * partial_parm_type - specialized template type, for example, r.$1 (partially specialized) or r.int (fully specialized)
+ * tscope - template scope
+ * specialization_priority - (output) contains a value indicating how good the match is
+ * (higher is better) only set if return is set to PartiallySpecializedMatch or ExactMatch.
+ * ----------------------------------------------------------------------------- */
+
+static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, Symtab *tscope, int *specialization_priority) {
+ static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */
+ static const int TEMPLATE_MATCH_PRIORITY = 1000; /* a priority added for each nested template, assumes max length of any prefix, such as r.q(const). , is less than this number */
+ SwigType *ty = Swig_symbol_typedef_reduce(type, tscope);
+ SwigType *pp_prefix = SwigType_prefix(partial_parm_type);
+ int pp_len = Len(pp_prefix);
+ EMatch match = Strchr(partial_parm_type, '$') == 0 ? ExactNoMatch : PartiallySpecializedNoMatch;
+ *specialization_priority = -1;
+
+ if (Equal(ty, partial_parm_type)) {
+ match = ExactMatch;
+ *specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */
+ } else if (match == PartiallySpecializedNoMatch) {
+ if ((pp_len > 0 && Strncmp(ty, pp_prefix, pp_len) == 0)) {
+ /*
+ Type starts with pp_prefix, so it is a partial specialization type match, for example,
+ all of the following could match the type in the %template:
+ template <typename T> struct XX {};
+ template <typename T> struct XX<T &> {}; // r.$1
+ template <typename T> struct XX<T const&> {}; // r.q(const).$1
+ template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
+ %template(XXX) XX<int *const&>; // r.q(const).p.int
+ where type="r.q(const).p.int" will match either of pp_prefix="r.", pp_prefix="r.q(const)." pp_prefix="r.q(const).p."
+ */
+ match = PartiallySpecializedMatch;
+ *specialization_priority = pp_len;
+ } else if (pp_len == 0 && is_exact_partial_type(partial_parm_type)) {
+ /*
+ Type without a prefix match, as in $1 for int
+ template <typename T, typename U> struct XX {};
+ template <typename T, typename U> struct XX<T, U &> {}; // $1,r.$2
+ %template(XXX) XX<int, double&>; // int,r.double
+ */
+ match = PartiallySpecializedMatch;
+ *specialization_priority = pp_len;
+ } else {
+ /*
+ Check for template types that are templates such as
+ template<typename V> struct Vect {};
+ template<typename T> class XX {};
+ template<class TT> class XX<Vect<TT>> {};
+ %template(XXVectInt) XX<Vect<int>>;
+ matches type="Vect<(int)>" and partial_parm_type="Vect<($1)>"
+ */
+ if (SwigType_istemplate(partial_parm_type) && SwigType_istemplate(ty)) {
+
+ SwigType *qt = Swig_symbol_typedef_reduce(ty, tscope);
+ String *tsuffix = SwigType_templatesuffix(qt);
+
+ SwigType *pp_qt = Swig_symbol_typedef_reduce(partial_parm_type, tscope);
+ String *pp_tsuffix = SwigType_templatesuffix(pp_qt);
+
+ if (Equal(tsuffix, pp_tsuffix) && Len(tsuffix) == 0) {
+ String *tprefix = SwigType_templateprefix(qt);
+ String *qprefix = SwigType_typedef_qualified(tprefix);
+
+ String *pp_tprefix = SwigType_templateprefix(pp_qt);
+ String *pp_qprefix = SwigType_typedef_qualified(pp_tprefix);
+
+ if (Equal(qprefix, pp_qprefix)) {
+ String *templateargs = SwigType_templateargs(qt);
+ List *parms = SwigType_parmlist(templateargs);
+ Iterator pi = First(parms);
+ Parm *p = pi.item;
+
+ String *pp_templateargs = SwigType_templateargs(pp_qt);
+ List *pp_parms = SwigType_parmlist(pp_templateargs);
+ Iterator pp_pi = First(pp_parms);
+ Parm *pp = pp_pi.item;
+
+ if (p && pp) {
+ /* Implementation is limited to matching single parameter templates only for now */
+ int priority;
+ match = does_parm_match(p, pp, tscope, &priority);
+ if (match <= PartiallySpecializedNoMatch) {
+ *specialization_priority = priority;
+ } else {
+ *specialization_priority = priority + TEMPLATE_MATCH_PRIORITY;
+ }
+ }
+
+ Delete(pp_parms);
+ Delete(pp_templateargs);
+ Delete(parms);
+ Delete(templateargs);
+ }
+
+ Delete(pp_qprefix);
+ Delete(pp_tprefix);
+ Delete(qprefix);
+ Delete(tprefix);
+ }
+
+ Delete(pp_tsuffix);
+ Delete(pp_qt);
+ Delete(tsuffix);
+ Delete(qt);
+ }
+ }
+ }
+ /*
+ Printf(stdout, " does_parm_match %2d %5d [%s] [%s]\n", match, *specialization_priority, type, partial_parm_type);
+ */
+ Delete(ty);
+ return match;
+}
+
+/* -----------------------------------------------------------------------------
+ * template_locate()
+ *
+ * Search for a template that matches name with given parameters.
+ * ----------------------------------------------------------------------------- */
+
+static Node *template_locate(String *name, Parm *instantiated_parms, String *symname, Symtab *tscope) {
+ Node *n = 0;
+ String *tname = 0;
+ Node *templ;
+ Symtab *primary_scope = 0;
+ List *possiblepartials = 0;
+ Parm *p;
+ Parm *parms = 0;
+ Parm *targs;
+ ParmList *expandedparms;
+ int *priorities_matrix = 0;
+ int max_possible_partials = 0;
+ int posslen = 0;
+
+ if (template_debug) {
+ tname = Copy(name);
+ SwigType_add_template(tname, instantiated_parms);
+ Printf(stdout, "\n");
+ if (symname)
+ Swig_diagnostic(cparse_file, cparse_line, "Template debug: Searching for match to: '%s' for instantiation of template named '%s'\n", tname, symname);
+ else
+ Swig_diagnostic(cparse_file, cparse_line, "Template debug: Searching for match to: '%s' for instantiation of empty template\n", tname);
+ Delete(tname);
+ tname = 0;
+ }
+
+ /* Search for primary (unspecialized) template */
+ templ = Swig_symbol_clookup(name, 0);
+
+ if (templ) {
+ /* TODO: check that this is not a specialization (might be a user error specializing a template before a primary template), but note https://stackoverflow.com/questions/9757642/wrapping-specialised-c-template-class-with-swig */
+ if (template_debug) {
+ Printf(stdout, " found primary template <%s> '%s'\n", ParmList_str_defaultargs(Getattr(templ, "templateparms")), Getattr(templ, "name"));
+ }
+
+ tname = Copy(name);
+ parms = CopyParmList(instantiated_parms);
+
+ /* All template specializations must be in the primary template's scope, store the symbol table for this scope for specialization lookups */
+ primary_scope = Getattr(templ, "sym:symtab");
+
+ /* Add default values from primary template */
+ targs = Getattr(templ, "templateparms");
+ expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, primary_scope);
+
+ /* Qualify template parameters */
+ p = expandedparms;
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ if (ty) {
+ SwigType *nt = Swig_symbol_type_qualify(ty, tscope);
+ Setattr(p, "type", nt);
+ Delete(nt);
+ }
+ p = nextSibling(p);
+ }
+ SwigType_add_template(tname, expandedparms);
+
+ /* Search for an explicit (exact) specialization. Example: template<> class name<int> { ... } */
+ {
+ if (template_debug) {
+ Printf(stdout, " searching for : '%s' (explicit specialization)\n", tname);
+ }
+ n = Swig_symbol_clookup_local(tname, primary_scope);
+ if (!n) {
+ SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope);
+ if (!Equal(rname, tname)) {
+ if (template_debug) {
+ Printf(stdout, " searching for : '%s' (explicit specialization with typedef reduction)\n", rname);
+ }
+ n = Swig_symbol_clookup_local(rname, primary_scope);
+ }
+ Delete(rname);
+ }
+ if (n) {
+ Node *tn;
+ String *nodeType = nodeType(n);
+ if (Equal(nodeType, "template")) {
+ if (template_debug) {
+ Printf(stdout, " explicit specialization found: '%s'\n", Getattr(n, "name"));
+ }
+ goto success;
+ }
+ tn = Getattr(n, "template");
+ if (tn) {
+ /* Previously wrapped by a template instantiation */
+ Node *previous_named_instantiation = GetFlag(n, "hidden") ? Getattr(n, "csym:nextSibling") : n; /* "hidden" is set when "sym:name" is a __dummy_ name */
+ if (!symname) {
+ /* Quietly ignore empty template instantiations if there is a previous (empty or non-empty) template instantiation */
+ if (template_debug) {
+ if (previous_named_instantiation)
+ Printf(stdout, " previous instantiation with name '%s' found: '%s' - duplicate empty template instantiation ignored\n", Getattr(previous_named_instantiation, "sym:name"), Getattr(n, "name"));
+ else
+ Printf(stdout, " previous empty template instantiation found: '%s' - duplicate empty template instantiation ignored\n", Getattr(n, "name"));
+ }
+ return 0;
+ }
+ /* Accept a second instantiation only if previous template instantiation is empty */
+ if (previous_named_instantiation) {
+ String *previous_name = Getattr(previous_named_instantiation, "name");
+ String *previous_symname = Getattr(previous_named_instantiation, "sym:name");
+ String *unprocessed_tname = Copy(name);
+ SwigType_add_template(unprocessed_tname, instantiated_parms);
+
+ if (template_debug)
+ Printf(stdout, " previous instantiation with name '%s' found: '%s' - duplicate instantiation ignored\n", previous_symname, Getattr(n, "name"));
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_TYPE_REDEFINED, cparse_file, cparse_line, "Duplicate template instantiation of '%s' with name '%s' ignored,\n", SwigType_namestr(unprocessed_tname), symname);
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "previous instantiation of '%s' with name '%s'.\n", SwigType_namestr(previous_name), previous_symname);
+ SWIG_WARN_NODE_END(n);
+
+ Delete(unprocessed_tname);
+ return 0;
+ }
+ if (template_debug)
+ Printf(stdout, " previous empty template instantiation found: '%s' - using as duplicate instantiation overrides empty template instantiation\n", Getattr(n, "name"));
+ n = tn;
+ goto success;
+ }
+ Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
+ Delete(tname);
+ Delete(parms);
+ return 0; /* Found a match, but it's not a template of any kind. */
+ }
+ }
+
+ /* Search for partial specializations.
+ * Example: template<typename T> class name<T *> { ... }
+
+ * There are 3 types of template arguments:
+ * (1) Template type arguments
+ * (2) Template non type arguments
+ * (3) Template template arguments
+ * only (1) is really supported for partial specializations
+ */
+
+ /* Rank each template parameter against the desired template parameters then build a matrix of best matches */
+ possiblepartials = NewList();
+ {
+ List *partials;
+
+ partials = Getattr(templ, "partials"); /* note that these partial specializations do not include explicit specializations */
+ if (partials) {
+ Iterator pi;
+ int parms_len = ParmList_len(parms); /* max parameters including defaulted parameters from primary template (ie max parameters) */
+ int *priorities_row;
+ max_possible_partials = Len(partials);
+ priorities_matrix = (int *)Malloc(sizeof(int) * max_possible_partials * parms_len); /* slightly wasteful allocation for max possible matches */
+ priorities_row = priorities_matrix;
+ for (pi = First(partials); pi.item; pi = Next(pi)) {
+ Parm *p = parms;
+ int i = 1;
+ Parm *partialparms = Getattr(pi.item, "partialparms");
+ Parm *pp = partialparms;
+ String *templcsymname = Getattr(pi.item, "templcsymname");
+ if (template_debug) {
+ Printf(stdout, " checking match: '%s' (partial specialization)\n", templcsymname);
+ }
+ if (ParmList_len(partialparms) == parms_len) {
+ int all_parameters_match = 1;
+ while (p && pp) {
+ SwigType *t;
+ t = Getattr(p, "type");
+ if (!t)
+ t = Getattr(p, "value");
+ if (t) {
+ EMatch match = does_parm_match(t, Getattr(pp, "type"), tscope, priorities_row + i - 1);
+ if (match < (int)PartiallySpecializedMatch) {
+ all_parameters_match = 0;
+ break;
+ }
+ }
+ i++;
+ p = nextSibling(p);
+ pp = nextSibling(pp);
+ }
+ if (all_parameters_match) {
+ Append(possiblepartials, pi.item);
+ priorities_row += parms_len;
+ }
+ }
+ }
+ }
+ }
+
+ posslen = Len(possiblepartials);
+ if (template_debug) {
+ int i;
+ if (posslen == 0)
+ Printf(stdout, " matched partials: NONE\n");
+ else if (posslen == 1)
+ Printf(stdout, " chosen partial: '%s'\n", Getattr(Getitem(possiblepartials, 0), "templcsymname"));
+ else {
+ Printf(stdout, " possibly matched partials:\n");
+ for (i = 0; i < posslen; i++) {
+ Printf(stdout, " '%s'\n", Getattr(Getitem(possiblepartials, i), "templcsymname"));
+ }
+ }
+ }
+
+ if (posslen > 1) {
+ /* Now go through all the possibly matched partial specialization templates and look for a non-ambiguous match.
+ * Exact matches rank the highest and deduced parameters are ranked by how specialized they are, eg looking for
+ * a match to const int *, the following rank (highest to lowest):
+ * const int * (exact match)
+ * const T *
+ * T *
+ * T
+ *
+ * An ambiguous example when attempting to match as either specialization could match: %template() X<int *, double *>;
+ * template<typename T1, typename T2> class X {}; // primary template
+ * template<typename T1> class X<T1, double *> {}; // specialization (1)
+ * template<typename T2> class X<int *, T2> {}; // specialization (2)
+ *
+ */
+ if (template_debug) {
+ int row, col;
+ int parms_len = ParmList_len(parms);
+ Printf(stdout, " parameter priorities matrix (%d parms):\n", parms_len);
+ for (row = 0; row < posslen; row++) {
+ int *priorities_row = priorities_matrix + row*parms_len;
+ Printf(stdout, " ");
+ for (col = 0; col < parms_len; col++) {
+ Printf(stdout, "%5d ", priorities_row[col]);
+ }
+ Printf(stdout, "\n");
+ }
+ }
+ {
+ int row, col;
+ int parms_len = ParmList_len(parms);
+ /* Printf(stdout, " parameter priorities inverse matrix (%d parms):\n", parms_len); */
+ for (col = 0; col < parms_len; col++) {
+ int *priorities_col = priorities_matrix + col;
+ int maxpriority = -1;
+ /*
+ Printf(stdout, "max_possible_partials: %d col:%d\n", max_possible_partials, col);
+ Printf(stdout, " ");
+ */
+ /* determine the highest rank for this nth parameter */
+ for (row = 0; row < posslen; row++) {
+ int *element_ptr = priorities_col + row*parms_len;
+ int priority = *element_ptr;
+ if (priority > maxpriority)
+ maxpriority = priority;
+ /* Printf(stdout, "%5d ", priority); */
+ }
+ /* Printf(stdout, "\n"); */
+ /* flag all the parameters which equal the highest rank */
+ for (row = 0; row < posslen; row++) {
+ int *element_ptr = priorities_col + row*parms_len;
+ int priority = *element_ptr;
+ *element_ptr = (priority >= maxpriority) ? 1 : 0;
+ }
+ }
+ }
+ {
+ int row, col;
+ int parms_len = ParmList_len(parms);
+ Iterator pi = First(possiblepartials);
+ Node *chosenpartials = NewList();
+ if (template_debug)
+ Printf(stdout, " priority flags matrix:\n");
+ for (row = 0; row < posslen; row++) {
+ int *priorities_row = priorities_matrix + row*parms_len;
+ int highest_count = 0; /* count of highest priority parameters */
+ for (col = 0; col < parms_len; col++) {
+ highest_count += priorities_row[col];
+ }
+ if (template_debug) {
+ Printf(stdout, " ");
+ for (col = 0; col < parms_len; col++) {
+ Printf(stdout, "%5d ", priorities_row[col]);
+ }
+ Printf(stdout, "\n");
+ }
+ if (highest_count == parms_len) {
+ Append(chosenpartials, pi.item);
+ }
+ pi = Next(pi);
+ }
+ if (Len(chosenpartials) > 0) {
+ /* one or more best match found */
+ Delete(possiblepartials);
+ possiblepartials = chosenpartials;
+ posslen = Len(possiblepartials);
+ } else {
+ /* no best match found */
+ Delete(chosenpartials);
+ }
+ }
+ }
+
+ if (posslen > 0) {
+ String *s = Getattr(Getitem(possiblepartials, 0), "templcsymname");
+ n = Swig_symbol_clookup_local(s, primary_scope);
+ if (posslen > 1) {
+ int i;
+ if (n) {
+ Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname));
+ Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' used,\n", SwigType_namestr(Getattr(n, "name")));
+ }
+ for (i = 1; i < posslen; i++) {
+ String *templcsymname = Getattr(Getitem(possiblepartials, i), "templcsymname");
+ Node *ignored_node = Swig_symbol_clookup_local(templcsymname, primary_scope);
+ assert(ignored_node);
+ Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(ignored_node), Getline(ignored_node), " instantiation '%s' ignored.\n", SwigType_namestr(Getattr(ignored_node, "name")));
+ }
+ }
+ }
+
+ if (!n) {
+ if (template_debug) {
+ Printf(stdout, " chosen primary template: '%s'\n", Getattr(templ, "name"));
+ }
+ n = templ;
+ }
+ } else {
+ if (template_debug) {
+ Printf(stdout, " primary template not found\n");
+ }
+ /* Give up if primary (unspecialized) template not found as specializations will only exist if there is a primary template */
+ n = 0;
+ }
+
+ if (!n) {
+ Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
+ } else if (n) {
+ String *nodeType = nodeType(n);
+ if (!Equal(nodeType, "template")) {
+ Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType);
+ n = 0;
+ }
+ }
+success:
+ Delete(tname);
+ Delete(possiblepartials);
+ if ((template_debug) && (n)) {
+ /*
+ Printf(stdout, "Node: %p\n", n);
+ Swig_print_node(n);
+ */
+ Printf(stdout, " chosen template:'%s'\n", Getattr(n, "name"));
+ }
+ Delete(parms);
+ Free(priorities_matrix);
+ return n;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_template_locate()
+ *
+ * Search for a template that matches name with given parameters and mark it for instantiation.
+ * For class templates marks the specialized template should there be one.
+ * For function templates marks all the unspecialized templates even if specialized
+ * templates exists.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_cparse_template_locate(String *name, Parm *instantiated_parms, String *symname, Symtab *tscope) {
+ Node *match = 0;
+ Node *n = template_locate(name, instantiated_parms, symname, tscope); /* this function does what we want for class templates */
+
+ if (n) {
+ String *nodeType = nodeType(n);
+ assert(Equal(nodeType, "template"));
+ String *templatetype = Getattr(n, "templatetype");
+
+ if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
+ Node *primary = Getattr(n, "primarytemplate");
+ Parm *tparmsfound = Getattr(primary ? primary : n, "templateparms");
+ int specialized = !tparmsfound; /* fully specialized (an explicit specialization) */
+ int variadic = ParmList_variadic_parm(tparmsfound) != 0;
+ match = n;
+ if (!specialized) {
+ if (!variadic && (ParmList_len(instantiated_parms) > ParmList_len(tparmsfound))) {
+ Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparmsfound));
+ match = 0;
+ } else if (ParmList_len(instantiated_parms) < ParmList_numrequired(tparmsfound) - (variadic ? 1 : 0)) { /* Variadic parameter is optional */
+ Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. Minimum of %d required.\n", (ParmList_numrequired(tparmsfound) - (variadic ? 1 : 0)) );
+ match = 0;
+ }
+ }
+ if (match)
+ SetFlag(n, "instantiate");
+ } else {
+ Node *firstn = 0;
+ /* If not a class template we must have a function template.
+ The template found is not necessarily the one we want when dealing with templated
+ functions. We don't want any specialized function templates as they won't have
+ the default parameters. Let's look for the unspecialized template. Also make sure
+ the number of template parameters is correct as it is possible to overload a
+ function template with different numbers of template parameters. */
+
+ if (template_debug) {
+ Printf(stdout, " Not a class template, seeking all appropriate primary function templates\n");
+ }
+
+ firstn = Swig_symbol_clookup_local(name, 0);
+ n = firstn;
+ /* First look for all overloaded functions (non-variadic) template matches.
+ * Looking for all template parameter matches only (not function parameter matches)
+ * as %template instantiation uses template parameters without any function parameters. */
+ while (n) {
+ if (Strcmp(nodeType(n), "template") == 0) {
+ Parm *tparmsfound = Getattr(n, "templateparms");
+ if (!ParmList_variadic_parm(tparmsfound)) {
+ if (ParmList_len(instantiated_parms) == ParmList_len(tparmsfound)) {
+ /* successful match */
+ if (template_debug) {
+ Printf(stdout, " found: template <%s> '%s' (%s)\n", ParmList_str_defaultargs(Getattr(n, "templateparms")), name, ParmList_str_defaultargs(Getattr(n, "parms")));
+ }
+ SetFlag(n, "instantiate");
+ if (!match)
+ match = n; /* first match */
+ }
+ }
+ }
+ /* repeat to find all matches with correct number of templated parameters */
+ n = Getattr(n, "sym:nextSibling");
+ }
+
+ /* Only consider variadic templates if there are no non-variadic template matches */
+ if (!match) {
+ n = firstn;
+ while (n) {
+ if (Strcmp(nodeType(n), "template") == 0) {
+ Parm *tparmsfound = Getattr(n, "templateparms");
+ if (ParmList_variadic_parm(tparmsfound)) {
+ if (ParmList_len(instantiated_parms) >= ParmList_len(tparmsfound) - 1) {
+ /* successful variadic match */
+ if (template_debug) {
+ Printf(stdout, " found: template <%s> '%s' (%s)\n", ParmList_str_defaultargs(Getattr(n, "templateparms")), name, ParmList_str_defaultargs(Getattr(n, "parms")));
+ }
+ SetFlag(n, "instantiate");
+ if (!match)
+ match = n; /* first match */
+ }
+ }
+ }
+ /* repeat to find all matches with correct number of templated parameters */
+ n = Getattr(n, "sym:nextSibling");
+ }
+ }
+
+ if (!match) {
+ Swig_error(cparse_file, cparse_line, "No matching function template '%s' found.\n", name);
+ }
+ }
+ }
+
+ return match;
+}
+
+/* -----------------------------------------------------------------------------
+ * merge_parameters()
+ *
+ * expanded_templateparms are the template parameters passed to %template.
+ * This function adds missing parameter name and type attributes from the chosen
+ * template (templateparms).
+ *
+ * Grab the parameter names from templateparms.
+ * Non-type template parameters have no type information in expanded_templateparms.
+ * Grab them from templateparms.
+ *
+ * Return 1 if there are variadic template parameters, 0 otherwise.
+ * ----------------------------------------------------------------------------- */
+
+static int merge_parameters(ParmList *expanded_templateparms, ParmList *templateparms) {
+ Parm *p = expanded_templateparms;
+ Parm *tp = templateparms;
+ while (p && tp) {
+ Setattr(p, "name", Getattr(tp, "name"));
+ if (!Getattr(p, "type"))
+ Setattr(p, "type", Getattr(tp, "type"));
+ p = nextSibling(p);
+ tp = nextSibling(tp);
+ }
+ return ParmList_variadic_parm(templateparms) ? 1 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * use_mark_defaults()
+ *
+ * Mark and use all the template parameters that are expanded from a default value
+ * ----------------------------------------------------------------------------- */
+
+static void use_mark_defaults(ParmList *defaults) {
+ Parm *tp = defaults;
+ while (tp) {
+ Setattr(tp, "default", "1");
+ Setattr(tp, "type", Getattr(tp, "value"));
+ tp = nextSibling(tp);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * use_mark_specialized_defaults()
+ *
+ * Modify extra defaulted parameters ready for adding to specialized template parameters list
+ * ----------------------------------------------------------------------------- */
+
+static void use_mark_specialized_defaults(ParmList *defaults) {
+ Parm *tp = defaults;
+ while (tp) {
+ Setattr(tp, "default", "1");
+ Setattr(tp, "type", Getattr(tp, "value"));
+ Delattr(tp, "name");
+ tp = nextSibling(tp);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * expand_defaults()
+ *
+ * Replace parameter types in default argument values, example:
+ * input: int K,int T,class C=Less<(K)>
+ * output: int K,int T,class C=Less<(int)>
+ * ----------------------------------------------------------------------------- */
+
+static void expand_defaults(ParmList *expanded_templateparms) {
+ Parm *tp = expanded_templateparms;
+ while (tp) {
+ Parm *p = expanded_templateparms;
+ String *tv = Getattr(tp, "value");
+ if (!tv)
+ tv = Getattr(tp, "type");
+ while(p) {
+ String *name = Getattr(p, "name");
+ String *value = Getattr(p, "value");
+ if (!value)
+ value = Getattr(p, "type");
+ if (name)
+ Replaceid(tv, name, value);
+ p = nextSibling(p);
+ }
+ tp = nextSibling(tp);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_template_parms_expand()
+ *
+ * instantiated_parms: template parameters passed to %template
+ * primary: primary template node
+ *
+ * Expand the instantiated_parms and return a parameter list with default
+ * arguments filled in where necessary.
+ * ----------------------------------------------------------------------------- */
+
+ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary, Node *templ) {
+ ParmList *expanded_templateparms = CopyParmList(instantiated_parms);
+ String *templatetype = Getattr(primary, "templatetype");
+
+ if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
+ /* Class template */
+ ParmList *templateparms = Getattr(primary, "templateparms");
+ int variadic = merge_parameters(expanded_templateparms, templateparms);
+ /* Add default arguments from primary template */
+ if (!variadic) {
+ ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parms));
+ if (defaults_start) {
+ ParmList *defaults = CopyParmList(defaults_start);
+ use_mark_defaults(defaults);
+ expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
+ expand_defaults(expanded_templateparms);
+ }
+ }
+ } else {
+ /* Function template */
+ /* TODO: Default template parameters support was only added in C++11 */
+ ParmList *templateparms = Getattr(templ, "templateparms");
+ merge_parameters(expanded_templateparms, templateparms);
+ }
+
+ return expanded_templateparms;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_template_partialargs_expand()
+ *
+ * partially_specialized_parms: partially specialized template parameters
+ * primary: primary template node
+ * templateparms: primary template parameters (providing the defaults)
+ *
+ * Expand the partially_specialized_parms and return a parameter list with default
+ * arguments filled in where necessary.
+ * ----------------------------------------------------------------------------- */
+
+ParmList *Swig_cparse_template_partialargs_expand(ParmList *partially_specialized_parms, Node *primary, ParmList *templateparms) {
+ ParmList *expanded_templateparms = CopyParmList(partially_specialized_parms);
+ String *templatetype = Getattr(primary, "templatetype");
+
+ if (Equal(templatetype, "class") || Equal(templatetype, "classforward")) {
+ /* Class template */
+ int variadic = ParmList_variadic_parm(templateparms) ? 1 : 0;
+ /* Add default arguments from primary template */
+ if (!variadic) {
+ ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(partially_specialized_parms));
+ if (defaults_start) {
+ ParmList *defaults = CopyParmList(defaults_start);
+ use_mark_specialized_defaults(defaults);
+ expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
+ expand_defaults(expanded_templateparms);
+ }
+ }
+ } else {
+ /* Function template */
+ /* TODO: Default template parameters support was only added in C++11 */
+ }
+
+ return expanded_templateparms;
+}
diff --git a/contrib/tools/swig/Source/CParse/util.c b/contrib/tools/swig/Source/CParse/util.c
new file mode 100644
index 00000000000..00863c03577
--- /dev/null
+++ b/contrib/tools/swig/Source/CParse/util.c
@@ -0,0 +1,126 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * util.c
+ *
+ * Parsing utilities.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_replace_descriptor()
+ *
+ * Replaces type descriptor string $descriptor() with the SWIG type descriptor
+ * string.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_cparse_replace_descriptor(String *s) {
+ char tmp[512];
+ String *arg = 0;
+ SwigType *t;
+ char *c = 0;
+
+ while ((c = strstr(Char(s), "$descriptor("))) {
+ char *d = tmp;
+ int level = 0;
+ while (*c) {
+ if (*c == '(')
+ level++;
+ if (*c == ')') {
+ level--;
+ if (level == 0) {
+ break;
+ }
+ }
+ *d = *c;
+ d++;
+ c++;
+ }
+ *d = 0;
+ arg = NewString(tmp + 12);
+ t = Swig_cparse_type(arg);
+ Delete(arg);
+ arg = 0;
+
+ if (t) {
+ String *mangle;
+ String *descriptor;
+
+ mangle = SwigType_manglestr(t);
+ descriptor = NewStringf("SWIGTYPE%s", mangle);
+ SwigType_remember(t);
+ *d = ')';
+ d++;
+ *d = 0;
+ Replace(s, tmp, descriptor, DOH_REPLACE_ANY);
+ Delete(mangle);
+ Delete(descriptor);
+ Delete(t);
+ } else {
+ Swig_error(Getfile(s), Getline(s), "Bad $descriptor() macro.\n");
+ break;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_smartptr()
+ *
+ * Parse the type in smartptr feature and convert into a SwigType.
+ * Error out if the parsing fails as this is like a parser syntax error.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_cparse_smartptr(Node *n) {
+ SwigType *smart = 0;
+ String *smartptr = Getattr(n, "feature:smartptr");
+ if (smartptr) {
+ SwigType *cpt = Swig_cparse_type(smartptr);
+ if (cpt) {
+ smart = SwigType_typedef_resolve_all(cpt);
+ Delete(cpt);
+ } else {
+ Swig_error(Getfile(n), Getline(n), "Invalid type (%s) in 'smartptr' feature for class %s.\n", smartptr, SwigType_namestr(Getattr(n, "name")));
+ }
+ }
+ return smart;
+}
+
+/* -----------------------------------------------------------------------------
+ * cparse_normalize_void()
+ *
+ * This function is used to replace arguments of the form (void) with empty
+ * arguments in C++
+ * ----------------------------------------------------------------------------- */
+
+void cparse_normalize_void(Node *n) {
+ String *decl = Getattr(n, "decl");
+ Parm *parms = Getattr(n, "parms");
+
+ if (SwigType_isfunction(decl)) {
+ if ((ParmList_len(parms) == 1) && (SwigType_type(Getattr(parms, "type")) == T_VOID)) {
+ Replaceall(decl, "f(void).", "f().");
+ Delattr(n, "parms");
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparse_new_node()
+ *
+ * Create an empty parse node, setting file and line number information
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_cparse_new_node(const_String_or_char_ptr tag) {
+ Node *n = NewHash();
+ set_nodeType(n,tag);
+ Setfile(n,cparse_file);
+ Setline(n,cparse_line);
+ return n;
+}
diff --git a/contrib/tools/swig/Source/DOH/README b/contrib/tools/swig/Source/DOH/README
new file mode 100644
index 00000000000..be90f25b46e
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/README
@@ -0,0 +1,124 @@
+DOH (Dave's Object Hack)
+
+Overview:
+---------
+DOH is a small C library that provides a number of simple yet powerful
+data structures. The data structures are built around a dynamic typing
+model in which any given object is allowed to support one or more
+classes of operations. Furthermore, a simple garbage collection
+scheme and a variety of interesting library methods are available.
+All and all, the operation of DOH makes massive abuse of the C type
+system and would probably make the language purists scream and
+performance addicts run away in horror. However, I really don't
+care--so there! However, for the rest of us, DOH is actually kind of
+fun to use. This is only a short description of the methods and is no
+way meant to be exhaustive.
+
+Common Operations (for all types)
+---------------------------------
+Delete(obj) Decrease the reference count and destroy if zero
+Copy(obj) Make a copy of an object.
+Clear(obj) Clear an object.
+Setscope(obj) Set scope of an object (guru's only)
+Str(obj) Create a string representation of obj.
+Data(obj) Return pointer to raw data in an object
+Char(obj) Convert to a char *
+Len(obj) Length of an object
+Hash(obj) Hash value (used for mapping)
+Cmp(obj1,obj2) Compare two objects.
+Name(obj) Return the object name
+First(obj) Return first object (iterator)
+Next(obj) Return next object
+Dump(obj,out) Serialize on out
+Load(in) Unserialize from in
+First(obj) Iterator
+Next(iter) Next iterator
+
+Mapping Operations (for hash table behavior)
+--------------------------------------------
+Getattr(hash,key) Get an attribute
+Setattr(hash,key,value) Set an attribute
+Delattr(hash,key) Delete an attribute
+First(hash) Get first object (iterator)
+Next(hash) Get next object
+GetInt(hash,key) Get attribute as an 'int'
+SetInt(hash,key,ivalue) Set attribute as an 'int'
+GetDouble(hash,key) Get attribute as a 'double'
+SetDouble(hash,key,dvalue) Set Attribute as a 'double'
+GetChar(hash,key) Get attribute as a 'char *'
+
+Sequence Operations
+-------------------
+Getitem(list,index) Get an item
+Setitem(list,index,val) Set an item
+Delitem(list,index) Delete an item
+Insert(list,index,val) Insert an item
+Append(list,val) Append to end
+Push(list,val) Insert at beginning
+
+File Operations
+---------------
+Read(obj,buffer,len) Read data
+Write(obj,buffer,len) Write data
+Getc(obj) Get a character
+Putc(ch,obj) Put a character
+Ungetc(ch,obj) Put character back on input stream
+Seek(obj,offset,whence) Seek
+Tell(obj) Return file pointer
+Delete(obj) Decrease the reference count, close file if zero
+
+String Operations
+-----------------
+Replace(obj, orig, rep, flags) Replace occurrences of orig with rep.
+Chop(obj) Remove trailing whitespace
+
+flags is one of the following:
+ DOH_REPLACE_ID
+ DOH_REPLACE_ID_BEGIN
+ DOH_REPLACE_ID_END
+ DOH_REPLACE_NUMBER_END
+
+and can be combined with one or more of the following:
+ DOH_REPLACE_ANY
+ DOH_REPLACE_NOQUOTE
+ DOH_REPLACE_NOCOMMENT
+ DOH_REPLACE_FIRST
+
+Callable Operations
+-------------------
+Call(obj, args) Perform a function call with arguments args.
+
+Miscellaneous library functions
+-------------------------------
+NewScope() Create a new scope
+DelScope(s) Delete scope s
+Readline(in) Read a line of input from in
+Printf(out,fmt,...) Formatted output
+DohEncoding(name, fn) Register a format encoding for Printf
+
+Currently Available datatypes
+------------------------------
+NewString(char *initial) Strings
+NewHash() Hash
+NewList() List
+NewVoid(void *ptr, void (*del)(void *)) Void
+NewFile(char *filename, char *mode, List *newfiles) File
+NewCallable(DOH *(*func)(DOH *, DOH *)) Callable object
+
+
+Odds and ends:
+
+ 1. All objects are of type 'DOH *'
+ 2. When in doubt, see rule (1)
+ 3. In certain cases, DOH performs implicit conversions
+ of 'char *' to an appropriate DOH string representation.
+ For operations involving files, DOH works with many
+ kinds of objects including FILE *, DOH File objects,
+ and DOH strings. Don't even ask how this works.
+
+ 4. More complete documentation is forthcoming.
+
+
+
+
+
diff --git a/contrib/tools/swig/Source/DOH/base.c b/contrib/tools/swig/Source/DOH/base.c
new file mode 100644
index 00000000000..b9272937ae6
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/base.c
@@ -0,0 +1,938 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * base.c
+ *
+ * This file contains the function entry points for dispatching methods on
+ * DOH objects. A number of small utility functions are also included.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+/* -----------------------------------------------------------------------------
+ * DohDelete()
+ * ----------------------------------------------------------------------------- */
+
+void DohDelete(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+
+ if (!obj)
+ return;
+ if (!DohCheck(b)) {
+ fputs("Fatal internal error: Attempt to delete a non-DOH object.\n", stderr);
+ Exit(EXIT_FAILURE);
+ }
+ if (b->flag_intern)
+ return;
+ assert(b->refcount > 0);
+ b->refcount--;
+ if (b->refcount <= 0) {
+ objinfo = b->type;
+ if (objinfo->doh_del) {
+ (objinfo->doh_del) (b);
+ } else {
+ if (b->data)
+ DohFree(b->data);
+ }
+ DohObjFree(b);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCopy()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohCopy(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+
+ if (!obj)
+ return 0;
+ if (!DohCheck(b)) {
+ fputs("Fatal internal error: Attempt to copy a non-DOH object.\n", stderr);
+ Exit(EXIT_FAILURE);
+ }
+ objinfo = b->type;
+ if (objinfo->doh_copy) {
+ DohBase *bc = (DohBase *) (objinfo->doh_copy) (b);
+ if ((bc) && b->meta) {
+ bc->meta = Copy(b->meta);
+ }
+ return (DOH *) bc;
+ }
+ return 0;
+}
+
+void DohIncref(DOH *obj) {
+ Incref(obj);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohClear()
+ * ----------------------------------------------------------------------------- */
+
+void DohClear(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_clear)
+ (objinfo->doh_clear) (b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohStr()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohStr(const DOH *obj) {
+ char buffer[512];
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(b)) {
+ objinfo = b->type;
+ if (objinfo->doh_str) {
+ return (objinfo->doh_str) (b);
+ }
+ sprintf(buffer, "<Object '%s' at %p>", objinfo->objname, (void *) b);
+ return NewString(buffer);
+ } else {
+ return NewString(obj);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDump()
+ * ----------------------------------------------------------------------------- */
+
+int DohDump(const DOH *obj, DOH *out) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_dump) {
+ return (objinfo->doh_dump) (b, out);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohLen() - Defaults to strlen() if not a DOH object
+ * ----------------------------------------------------------------------------- */
+int DohLen(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!b)
+ return 0;
+ if (DohCheck(b)) {
+ objinfo = b->type;
+ if (objinfo->doh_len) {
+ return (objinfo->doh_len) (b);
+ }
+ return 0;
+ } else {
+ return (int)strlen((char *) obj);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohHashVal()
+ * ----------------------------------------------------------------------------- */
+
+int DohHashval(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ /* obj is already checked and/or converted into DohBase* */
+ /* if (DohCheck(b)) */
+ {
+ objinfo = b->type;
+ if (objinfo->doh_hashval) {
+ return (objinfo->doh_hashval) (b);
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohData()
+ * ----------------------------------------------------------------------------- */
+
+void *DohData(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_data) {
+ return (objinfo->doh_data) (b);
+ }
+ return 0;
+ }
+ return (void *) obj;
+}
+
+/* -----------------------------------------------------------------------------
+ * RawData()
+ * ----------------------------------------------------------------------------- */
+
+static void *RawData(DohBase *b) {
+ DohObjInfo *objinfo = b->type;
+ return (objinfo->doh_data) ? (objinfo->doh_data) (b) : 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohCmp()
+ * ----------------------------------------------------------------------------- */
+
+int DohCmp(const DOH *obj1, const DOH *obj2) {
+ DohBase *b1, *b2;
+ DohObjInfo *b1info, *b2info;
+ int c1, c2;
+ b1 = (DohBase *) obj1;
+ b2 = (DohBase *) obj2;
+ c1 = DohCheck(b1);
+ c2 = DohCheck(b2);
+ /* most of the times, obj2 is a plain c string */
+ if (!c1 || !c2) {
+ if ((b1 == 0) && (b2 == 0))
+ return 0;
+ if (b1 && !b2)
+ return 1;
+ if (!b1 && b2)
+ return -1;
+ return strcmp((char *) (c1 ? RawData(b1) : (void *) obj1), (char *) (c2 ? RawData(b2) : (void *) obj2));
+ }
+ b1info = b1->type;
+ b2info = b2->type;
+ if ((b1info == b2info) && (b1info->doh_cmp))
+ return (b1info->doh_cmp) (b1, b2);
+ /* finally compare pointers */
+ return b1 < b2 ? -1 : b1 == b2 ? 0 : 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohEqual()
+ * ----------------------------------------------------------------------------- */
+
+int DohEqual(const DOH *obj1, const DOH *obj2) {
+ DohBase *b1 = (DohBase *) obj1;
+ DohBase *b2 = (DohBase *) obj2;
+ if (!b1) {
+ return !b2;
+ } else if (!b2) {
+ return 0;
+ } else {
+ DohObjInfo *b1info = 0;
+ DohObjInfo *b2info = 0;
+ if (DohCheck(b1)) {
+ b1info = b1->type;
+ if (DohCheck(b2)) {
+ b2info = b2->type;
+ } else {
+ int len = (b1info->doh_len) (b1);
+ char *cobj = (char *) obj2;
+ return len == (int) strlen(cobj) ? (memcmp(RawData(b1), cobj, len) == 0) : 0;
+ }
+ } else if (DohCheck(b2)) {
+ int len = (b2->type->doh_len) (b2);
+ char *cobj = (char *) obj1;
+ return len == (int) strlen(cobj) ? (memcmp(RawData(b2), cobj, len) == 0) : 0;
+ } else {
+ return strcmp((char *) obj1, (char *) obj2) == 0;
+ }
+
+ if (!b1info) {
+ return obj1 == obj2;
+ } else if (b1info == b2info) {
+ return b1info->doh_equal ? (b1info->doh_equal) (b1, b2) : (b1info->doh_cmp ? (b1info->doh_cmp) (b1, b2) == 0 : (b1 == b2));
+ } else {
+ return 0;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohFirst()
+ * ----------------------------------------------------------------------------- */
+
+DohIterator DohFirst(DOH *obj) {
+ DohIterator iter;
+ DohBase *b;
+ DohObjInfo *binfo;
+
+ b = (DohBase *) obj;
+ if (DohCheck(b)) {
+ binfo = b->type;
+ if (binfo->doh_first) {
+ return (binfo->doh_first) (b);
+ }
+ }
+ iter.object = 0;
+ iter.item = 0;
+ iter.key = 0;
+ iter._current = 0;
+ iter._index = 0;
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohNext()
+ * ----------------------------------------------------------------------------- */
+
+DohIterator DohNext(DohIterator iter) {
+ DohIterator niter;
+
+ if (iter.object) {
+ DohBase *b;
+ DohObjInfo *binfo;
+
+ b = (DohBase *) iter.object;
+ binfo = b->type;
+ if (binfo->doh_next) {
+ return (binfo->doh_next) (iter);
+ }
+ }
+ niter = iter;
+ return niter;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsMapping()
+ * ----------------------------------------------------------------------------- */
+int DohIsMapping(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_hash)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetattr()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohGetattr(DOH *obj, const DOH *name) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_hash && objinfo->doh_hash->doh_getattr) {
+ DOH *r = (objinfo->doh_hash->doh_getattr) (b, (DOH *) name);
+ return (r == DohNone) ? 0 : r;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetattr()
+ * ----------------------------------------------------------------------------- */
+
+int DohSetattr(DOH *obj, const DOH *name, const DOH *value) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_hash && objinfo->doh_hash->doh_setattr) {
+ return (objinfo->doh_hash->doh_setattr) (b, (DOH *) name, (DOH *) value);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDelattr()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelattr(DOH *obj, const DOH *name) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_hash && objinfo->doh_hash->doh_delattr) {
+ return (objinfo->doh_hash->doh_delattr) (b, (DOH *) name);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCheckattr()
+ * ----------------------------------------------------------------------------- */
+
+int DohCheckattr(DOH *obj, const DOH *name, const DOH *value) {
+ DOH *attr = Getattr(obj,name);
+ if (!attr) return 0;
+ return DohEqual(attr,value);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohKeys()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohKeys(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo && objinfo->doh_hash->doh_keys) {
+ return (objinfo->doh_hash->doh_keys) (b);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSortedKeys()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohSortedKeys(DOH *obj, int (*cmp) (const DOH *, const DOH *)) {
+ DOHList *keys = DohKeys(obj);
+ if (keys) {
+ DohSortList(keys, cmp);
+ }
+ return keys;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetInt()
+ * ----------------------------------------------------------------------------- */
+
+int DohGetInt(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ if (DohIsString(val)) {
+ return atoi((char *) Data(val));
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetDouble()
+ * ----------------------------------------------------------------------------- */
+
+double DohGetDouble(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ if (DohIsString(val)) {
+ return atof((char *) Data(val));
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetChar()
+ * ----------------------------------------------------------------------------- */
+
+char *DohGetChar(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ if (DohIsString(val)) {
+ return (char *) Data(val);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetFlagAttr() / DohGetFlag()
+ * A flag is unset if the attribute (name) does not exist on the node (obj),
+ * or it is set to "0". If the attribute is set to any other value,
+ * the flag is set.
+ *
+ * DohGetFlag() returns if the flag is set or not
+ * DohGetFlagAttr() returns the flag value if is set, NULL otherwise
+ * ----------------------------------------------------------------------------- */
+
+
+DOH *DohGetFlagAttr(DOH *obj, const DOH *name) {
+ DOH *val = Getattr(obj, (DOH *) name);
+ if (!val) {
+ return NULL;
+ } else {
+ const char *cval = Char(val);
+ if (!cval)
+ return val;
+ return (strcmp(cval, "0") != 0) ? val : NULL;
+ }
+}
+
+int DohGetFlag(DOH *obj, const DOH *name) {
+ return DohGetFlagAttr(obj, name) ? 1 : 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohGetVoid()
+ * ----------------------------------------------------------------------------- */
+
+void *DohGetVoid(DOH *obj, const DOH *name) {
+ DOH *val;
+ val = Getattr(obj, (DOH *) name);
+ if (!val)
+ return 0;
+ return (void *) Data(val);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetInt()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetInt(DOH *obj, const DOH *name, int value) {
+ DOH *temp;
+ temp = NewStringEmpty();
+ Printf(temp, "%d", value);
+ Setattr(obj, (DOH *) name, temp);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetDouble()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetDouble(DOH *obj, const DOH *name, double value) {
+ DOH *temp;
+ temp = NewStringEmpty();
+ Printf(temp, "%0.17f", value);
+ Setattr(obj, (DOH *) name, temp);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetChar()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetChar(DOH *obj, const DOH *name, char *value) {
+ Setattr(obj, (DOH *) name, NewString(value));
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetFlag()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetFlagAttr(DOH *obj, const DOH *name, const DOH *attr) {
+ Setattr(obj, (DOH *) name, attr ? attr : NewString("0"));
+}
+
+void DohSetFlag(DOH *obj, const DOH *name) {
+ Setattr(obj, (DOH *) name, NewString("1"));
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetVoid()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetVoid(DOH *obj, const DOH *name, void *value) {
+ Setattr(obj, (DOH *) name, NewVoid(value, 0));
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsSequence()
+ * ----------------------------------------------------------------------------- */
+
+int DohIsSequence(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_list)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetitem()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohGetitem(DOH *obj, int index) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_getitem) {
+ return (objinfo->doh_list->doh_getitem) (b, index);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetitem()
+ * ----------------------------------------------------------------------------- */
+
+int DohSetitem(DOH *obj, int index, const DOH *value) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_setitem) {
+ return (objinfo->doh_list->doh_setitem) (b, index, (DOH *) value);
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDelitem()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelitem(DOH *obj, int index) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_delitem) {
+ return (objinfo->doh_list->doh_delitem) (b, index);
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohInsertitem()
+ * ----------------------------------------------------------------------------- */
+
+int DohInsertitem(DOH *obj, int index, const DOH *value) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_insitem) {
+ return (objinfo->doh_list->doh_insitem) (b, index, (DOH *) value);
+ }
+ return -1;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohDelslice()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelslice(DOH *obj, int sindex, int eindex) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo = b->type;
+ if (objinfo->doh_list && objinfo->doh_list->doh_delslice) {
+ return (objinfo->doh_list->doh_delslice) (b, sindex, eindex);
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsFile()
+ * ----------------------------------------------------------------------------- */
+
+int DohIsFile(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_file)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohRead()
+ * ----------------------------------------------------------------------------- */
+
+int DohRead(DOH *obj, void *buffer, int length) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_read)) {
+ return (objinfo->doh_file->doh_read) (b, buffer, length);
+ }
+ return -1;
+ }
+ /* Hmmm. Not a file. Maybe it's a real FILE */
+ return (int)fread(buffer, 1, length, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohWrite()
+ * ----------------------------------------------------------------------------- */
+
+int DohWrite(DOH *obj, const void *buffer, int length) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_write)) {
+ return (objinfo->doh_file->doh_write) (b, buffer, length);
+ }
+ return -1;
+ }
+ /* Hmmm. Not a file. Maybe it's a real FILE */
+ return (int)fwrite(buffer, 1, length, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSeek()
+ * ----------------------------------------------------------------------------- */
+
+int DohSeek(DOH *obj, long offset, int whence) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_seek)) {
+ return (objinfo->doh_file->doh_seek) (b, offset, whence);
+ }
+ return -1;
+ }
+ return fseek((FILE *) b, offset, whence);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohTell()
+ * ----------------------------------------------------------------------------- */
+
+long DohTell(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if ((objinfo->doh_file) && (objinfo->doh_file->doh_tell)) {
+ return (objinfo->doh_file->doh_tell) (b);
+ }
+ return -1;
+ }
+ return ftell((FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetc()
+ * ----------------------------------------------------------------------------- */
+
+int DohGetc(DOH *obj) {
+ static DOH *lastdoh = 0;
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (obj == lastdoh) {
+ objinfo = b->type;
+ return (objinfo->doh_file->doh_getc) (b);
+ }
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_getc) {
+ lastdoh = obj;
+ return (objinfo->doh_file->doh_getc) (b);
+ }
+ return EOF;
+ }
+ return fgetc((FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPutc()
+ * ----------------------------------------------------------------------------- */
+
+int DohPutc(int ch, DOH *obj) {
+ static DOH *lastdoh = 0;
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+
+ if (obj == lastdoh) {
+ objinfo = b->type;
+ return (objinfo->doh_file->doh_putc) (b, ch);
+ }
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_putc) {
+ lastdoh = obj;
+ return (objinfo->doh_file->doh_putc) (b, ch);
+ }
+ return EOF;
+ }
+ return fputc(ch, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohUngetc()
+ * ----------------------------------------------------------------------------- */
+
+int DohUngetc(int ch, DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (DohCheck(obj)) {
+ objinfo = b->type;
+ if (objinfo->doh_file->doh_ungetc) {
+ return (objinfo->doh_file->doh_ungetc) (b, ch);
+ }
+ return EOF;
+ }
+ return ungetc(ch, (FILE *) b);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIsString()
+ * ----------------------------------------------------------------------------- */
+
+int DohIsString(const DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ DohObjInfo *objinfo;
+ if (!DohCheck(b))
+ return 0;
+ objinfo = b->type;
+ if (objinfo->doh_string)
+ return 1;
+ else
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohReplace()
+ * ----------------------------------------------------------------------------- */
+
+int DohReplace(DOH *src, const DOH *token, const DOH *rep, int flags) {
+ DohBase *b = (DohBase *) src;
+ DohObjInfo *objinfo;
+ if (!token)
+ return 0;
+ if (!rep)
+ rep = "";
+ if (DohIsString(src)) {
+ objinfo = b->type;
+ if (objinfo->doh_string->doh_replace) {
+ return (objinfo->doh_string->doh_replace) (b, (DOH *) token, (DOH *) rep, flags);
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohChop()
+ * ----------------------------------------------------------------------------- */
+
+void DohChop(DOH *src) {
+ DohBase *b = (DohBase *) src;
+ DohObjInfo *objinfo;
+ if (DohIsString(src)) {
+ objinfo = b->type;
+ if (objinfo->doh_string->doh_chop) {
+ (objinfo->doh_string->doh_chop) (b);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetFile()
+ * ----------------------------------------------------------------------------- */
+void DohSetfile(DOH *ho, DOH *file) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return;
+ objinfo = h->type;
+ if (objinfo->doh_setfile)
+ (objinfo->doh_setfile) (h, file);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetFile()
+ * ----------------------------------------------------------------------------- */
+DOH *DohGetfile(const DOH *ho) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return 0;
+ objinfo = h->type;
+ if (objinfo->doh_getfile)
+ return (objinfo->doh_getfile) (h);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetLine()
+ * ----------------------------------------------------------------------------- */
+void DohSetline(DOH *ho, int l) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return;
+ objinfo = h->type;
+ if (objinfo->doh_setline)
+ (objinfo->doh_setline) (h, l);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetLine()
+ * ----------------------------------------------------------------------------- */
+int DohGetline(const DOH *ho) {
+ DohBase *h = (DohBase *) ho;
+ DohObjInfo *objinfo;
+ if (!h)
+ return 0;
+ objinfo = h->type;
+ if (objinfo->doh_getline)
+ return (objinfo->doh_getline) (h);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetmeta()
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohGetmeta(DOH *ho, const DOH *name) {
+ DohBase *h = (DohBase *) ho;
+ if (!DohCheck(ho))
+ return 0;
+ if (!h->meta)
+ return 0;
+ return DohGetattr(h->meta, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetmeta()
+ * ----------------------------------------------------------------------------- */
+
+int DohSetmeta(DOH *ho, const DOH *name, const DOH *value) {
+ DohBase *h = (DohBase *) ho;
+ if (!DohCheck(ho))
+ return 0;
+ if (!h->meta)
+ h->meta = NewHash();
+ return DohSetattr(h->meta, name, value);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohDelmeta()
+ * ----------------------------------------------------------------------------- */
+
+int DohDelmeta(DOH *ho, const DOH *name) {
+ DohBase *h = (DohBase *) ho;
+ if (!DohCheck(ho))
+ return 0;
+ if (!h->meta)
+ return 0;
+ return DohDelattr(h->meta, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetmark()
+ * ----------------------------------------------------------------------------- */
+
+void DohSetmark(DOH *ho, int x) {
+ DohBase *h = (DohBase *) ho;
+ h->flag_usermark = x;
+}
+
+int DohGetmark(DOH *ho) {
+ DohBase *h = (DohBase *) ho;
+ return h->flag_usermark;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCall()
+ *
+ * Invokes a function via DOH. A Function is represented by a hash table with
+ * the following attributes:
+ *
+ * "builtin" - Pointer to built-in function (if any)
+ *
+ * (Additional attributes may be added later)
+ *
+ * Returns a DOH object with result on success. Returns NULL on error
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohCall(DOH *func, DOH *args) {
+ DOH *result;
+ DohFuncPtr_t builtin;
+
+ builtin.p = GetVoid(func, "builtin");
+
+ if (!builtin.p)
+ return 0;
+ result = (*builtin.func) (args);
+ return result;
+}
diff --git a/contrib/tools/swig/Source/DOH/doh.h b/contrib/tools/swig/Source/DOH/doh.h
new file mode 100644
index 00000000000..45a1f7fc892
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/doh.h
@@ -0,0 +1,507 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doh.h
+ *
+ * This file describes of the externally visible functions in DOH.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DOH_H
+#define SWIG_DOH_H
+
+#include "swigconfig.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Set the namespace prefix for DOH API functions. This can be used to control
+ visibility of the functions in libraries */
+
+/* Set this macro if you want to change DOH linkage. You would do this if you
+ wanted to hide DOH in a library using a different set of names. Note: simply
+ change "Doh" to a new name. */
+
+/*
+#define DOH_NAMESPACE(x) Doh ## x
+*/
+
+#ifdef DOH_NAMESPACE
+
+/* Namespace control. These macros define all of the public API names in DOH */
+
+#define DohCheck DOH_NAMESPACE(Check)
+#define DohIntern DOH_NAMESPACE(Intern)
+#define DohDelete DOH_NAMESPACE(Delete)
+#define DohCopy DOH_NAMESPACE(Copy)
+#define DohClear DOH_NAMESPACE(Clear)
+#define DohStr DOH_NAMESPACE(Str)
+#define DohData DOH_NAMESPACE(Data)
+#define DohDump DOH_NAMESPACE(Dump)
+#define DohLen DOH_NAMESPACE(Len)
+#define DohHashval DOH_NAMESPACE(Hashval)
+#define DohCmp DOH_NAMESPACE(Cmp)
+#define DohEqual DOH_NAMESPACE(Equal)
+#define DohIncref DOH_NAMESPACE(Incref)
+#define DohCheckattr DOH_NAMESPACE(Checkattr)
+#define DohSetattr DOH_NAMESPACE(Setattr)
+#define DohDelattr DOH_NAMESPACE(Delattr)
+#define DohKeys DOH_NAMESPACE(Keys)
+#define DohSortedKeys DOH_NAMESPACE(SortedKeys)
+#define DohGetInt DOH_NAMESPACE(GetInt)
+#define DohGetDouble DOH_NAMESPACE(GetDouble)
+#define DohGetChar DOH_NAMESPACE(GetChar)
+#define DohSetChar DOH_NAMESPACE(SetChar)
+#define DohSetInt DOH_NAMESPACE(SetInt)
+#define DohSetDouble DOH_NAMESPACE(SetDouble)
+#define DohSetVoid DOH_NAMESPACE(SetVoid)
+#define DohGetVoid DOH_NAMESPACE(GetVoid)
+#define DohGetitem DOH_NAMESPACE(Getitem)
+#define DohSetitem DOH_NAMESPACE(Setitem)
+#define DohDelitem DOH_NAMESPACE(Delitem)
+#define DohInsertitem DOH_NAMESPACE(Insertitem)
+#define DohDelslice DOH_NAMESPACE(Delslice)
+#define DohWrite DOH_NAMESPACE(Write)
+#define DohRead DOH_NAMESPACE(Read)
+#define DohSeek DOH_NAMESPACE(Seek)
+#define DohTell DOH_NAMESPACE(Tell)
+#define DohGetc DOH_NAMESPACE(Getc)
+#define DohPutc DOH_NAMESPACE(Putc)
+#define DohUngetc DOH_NAMESPACE(Ungetc)
+#define DohGetline DOH_NAMESPACE(Getline)
+#define DohSetline DOH_NAMESPACE(Setline)
+#define DohGetfile DOH_NAMESPACE(Getfile)
+#define DohSetfile DOH_NAMESPACE(Setfile)
+#define DohReplace DOH_NAMESPACE(Replace)
+#define DohChop DOH_NAMESPACE(Chop)
+#define DohGetmeta DOH_NAMESPACE(Getmeta)
+#define DohSetmeta DOH_NAMESPACE(Setmeta)
+#define DohDelmeta DOH_NAMESPACE(Delmeta)
+#define DohEncoding DOH_NAMESPACE(Encoding)
+#define DohPrintf DOH_NAMESPACE(Printf)
+#define DohvPrintf DOH_NAMESPACE(vPrintf)
+#define DohPrintv DOH_NAMESPACE(Printv)
+#define DohReadline DOH_NAMESPACE(Readline)
+#define DohIsMapping DOH_NAMESPACE(IsMapping)
+#define DohIsSequence DOH_NAMESPACE(IsSequence)
+#define DohIsString DOH_NAMESPACE(IsString)
+#define DohIsFile DOH_NAMESPACE(IsFile)
+#define DohNewString DOH_NAMESPACE(NewString)
+#define DohNewStringEmpty DOH_NAMESPACE(NewStringEmpty)
+#define DohNewStringWithSize DOH_NAMESPACE(NewStringWithSize)
+#define DohNewStringf DOH_NAMESPACE(NewStringf)
+#define DohStrcmp DOH_NAMESPACE(Strcmp)
+#define DohStrncmp DOH_NAMESPACE(Strncmp)
+#define DohStrstr DOH_NAMESPACE(Strstr)
+#define DohStrchr DOH_NAMESPACE(Strchr)
+#define DohNewFile DOH_NAMESPACE(NewFile)
+#define DohNewFileFromFile DOH_NAMESPACE(NewFileFromFile)
+#define DohNewFileFromFd DOH_NAMESPACE(NewFileFromFd)
+#define DohFileErrorDisplay DOH_NAMESPACE(FileErrorDisplay)
+#define DohCopyto DOH_NAMESPACE(Copyto)
+#define DohNewList DOH_NAMESPACE(NewList)
+#define DohNewHash DOH_NAMESPACE(NewHash)
+#define DohNewVoid DOH_NAMESPACE(NewVoid)
+#define DohSplit DOH_NAMESPACE(Split)
+#define DohSplitLines DOH_NAMESPACE(SplitLines)
+#define DohNone DOH_NAMESPACE(None)
+#define DohCall DOH_NAMESPACE(Call)
+#define DohObjMalloc DOH_NAMESPACE(ObjMalloc)
+#define DohObjFree DOH_NAMESPACE(ObjFree)
+#define DohMemoryDebug DOH_NAMESPACE(MemoryDebug)
+#define DohStringType DOH_NAMESPACE(StringType)
+#define DohListType DOH_NAMESPACE(ListType)
+#define DohHashType DOH_NAMESPACE(HashType)
+#define DohFileType DOH_NAMESPACE(FileType)
+#define DohVoidType DOH_NAMESPACE(VoidType)
+#define DohIterator DOH_NAMESPACE(Iterator)
+#define DohFirst DOH_NAMESPACE(First)
+#define DohNext DOH_NAMESPACE(Next)
+#define DohMalloc DOH_NAMESPACE(Malloc)
+#define DohRealloc DOH_NAMESPACE(Realloc)
+#define DohCalloc DOH_NAMESPACE(Calloc)
+#define DohFree DOH_NAMESPACE(Free)
+#define DohSetExitHandler DOH_NAMESPACE(SetExitHandler)
+#define DohExit DOH_NAMESPACE(Exit)
+#endif
+
+#define DOH_MAJOR_VERSION 0
+#define DOH_MINOR_VERSION 1
+
+typedef void DOH;
+
+/*
+ * With dynamic typing, all DOH objects are technically of type 'void *'.
+ * However, to clarify the reading of source code, the following symbolic
+ * names are used.
+ */
+
+#define DOHString DOH
+#define DOHList DOH
+#define DOHHash DOH
+#define DOHFile DOH
+#define DOHVoid DOH
+#define DOHString_or_char DOH
+#define DOHObj_or_char DOH
+
+typedef const DOHString_or_char * const_String_or_char_ptr;
+typedef const DOHString_or_char * DOHconst_String_or_char_ptr;
+
+#define DOH_BEGIN -1
+#define DOH_END -2
+#define DOH_CUR -3
+#define DOH_CURRENT -3
+
+/* Iterator objects */
+
+typedef struct {
+ void *key; /* Current key (if any) */
+ void *item; /* Current item */
+ void *object; /* Object being iterated over */
+ void *_current; /* Internal use */
+ int _index; /* Internal use */
+} DohIterator;
+
+/* Memory management */
+
+/* Wrappers around malloc(), realloc() and calloc() which never return NULL. */
+extern void *DohMalloc(size_t size);
+extern void *DohRealloc(void *ptr, size_t size);
+extern void *DohCalloc(size_t n, size_t size);
+
+#ifndef DohFree
+#define DohFree free
+#endif
+
+extern int DohCheck(const DOH *ptr); /* Check if a DOH object */
+extern void DohIntern(DOH *); /* Intern an object */
+
+/* Basic object methods. Common to most objects */
+
+extern void DohDelete(DOH *obj); /* Delete an object */
+extern DOH *DohCopy(const DOH *obj);
+extern void DohClear(DOH *obj);
+extern DOHString *DohStr(const DOH *obj);
+extern void *DohData(const DOH *obj);
+extern int DohDump(const DOH *obj, DOHFile * out);
+extern int DohLen(const DOH *obj);
+extern int DohHashval(const DOH *obj);
+extern int DohCmp(const DOH *obj1, const DOH *obj2);
+extern int DohEqual(const DOH *obj1, const DOH *obj2);
+extern void DohIncref(DOH *obj);
+
+/* Mapping methods */
+
+extern DOH *DohGetattr(DOH *obj, const DOHString_or_char *name);
+extern int DohSetattr(DOH *obj, const DOHString_or_char *name, const DOHObj_or_char * value);
+extern int DohDelattr(DOH *obj, const DOHString_or_char *name);
+extern int DohCheckattr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *value);
+extern DOH *DohKeys(DOH *obj);
+extern DOH *DohSortedKeys(DOH *obj, int (*cmp) (const DOH *, const DOH *));
+extern int DohGetInt(DOH *obj, const DOHString_or_char *name);
+extern void DohSetInt(DOH *obj, const DOHString_or_char *name, int);
+extern double DohGetDouble(DOH *obj, const DOHString_or_char *name);
+extern void DohSetDouble(DOH *obj, const DOHString_or_char *name, double);
+extern char *DohGetChar(DOH *obj, const DOHString_or_char *name);
+extern void DohSetChar(DOH *obj, const DOH *name, char *value);
+extern void *DohGetFlagAttr(DOH *obj, const DOHString_or_char *name);
+extern int DohGetFlag(DOH *obj, const DOHString_or_char *name);
+extern void DohSetFlagAttr(DOH *obj, const DOHString_or_char *name, const DOHString_or_char *attr);
+extern void DohSetFlag(DOH *obj, const DOHString_or_char *name);
+extern void *DohGetVoid(DOH *obj, const DOHString_or_char *name);
+extern void DohSetVoid(DOH *obj, const DOHString_or_char *name, void *value);
+
+/* Sequence methods */
+
+extern DOH *DohGetitem(DOH *obj, int index);
+extern int DohSetitem(DOH *obj, int index, const DOHObj_or_char * value);
+extern int DohDelitem(DOH *obj, int index);
+extern int DohInsertitem(DOH *obj, int index, const DOHObj_or_char * value);
+extern int DohDelslice(DOH *obj, int sindex, int eindex);
+
+/* File methods */
+
+extern int DohWrite(DOHFile * obj, const void *buffer, int length);
+extern int DohRead(DOHFile * obj, void *buffer, int length);
+extern int DohSeek(DOHFile * obj, long offset, int whence);
+extern long DohTell(DOHFile * obj);
+extern int DohGetc(DOHFile * obj);
+extern int DohPutc(int ch, DOHFile * obj);
+extern int DohUngetc(int ch, DOHFile * obj);
+
+
+
+/* Iterators */
+extern DohIterator DohFirst(DOH *obj);
+extern DohIterator DohNext(DohIterator x);
+
+/* Positional */
+
+extern int DohGetline(const DOH *obj);
+extern void DohSetline(DOH *obj, int line);
+extern DOH *DohGetfile(const DOH *obj);
+extern void DohSetfile(DOH *obj, DOH *file);
+
+ /* String Methods */
+
+extern int DohReplace(DOHString * src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags);
+extern void DohChop(DOHString * src);
+
+/* Meta-variables */
+extern DOH *DohGetmeta(DOH *, const DOH *);
+extern int DohSetmeta(DOH *, const DOH *, const DOH *value);
+extern int DohDelmeta(DOH *, const DOH *);
+
+ /* Utility functions */
+
+extern void DohEncoding(const char *name, DOH *(*fn) (DOH *s));
+extern int DohPrintf(DOHFile * obj, const char *format, ...);
+extern int DohvPrintf(DOHFile * obj, const char *format, va_list ap);
+extern int DohPrintv(DOHFile * obj, ...);
+extern DOH *DohReadline(DOHFile * in);
+
+ /* Miscellaneous */
+
+extern int DohIsMapping(const DOH *obj);
+extern int DohIsSequence(const DOH *obj);
+extern int DohIsString(const DOH *obj);
+extern int DohIsFile(const DOH *obj);
+
+extern void DohSetMaxHashExpand(int count);
+extern int DohGetMaxHashExpand(void);
+extern void DohSetmark(DOH *obj, int x);
+extern int DohGetmark(DOH *obj);
+
+/* Set the function for DohExit() to call instead of exit().
+ *
+ * The registered function can perform clean up, etc. It should simply
+ * return when done and then exit() will get called. Bear in mind that
+ * the handler function can be called after malloc() has failed, so it's
+ * a good idea for it to avoid allocating additional memory.
+ *
+ * The registered handler function is unregistered by DohExit() before calling
+ * it to avoid the potential for infinite loops.
+ *
+ * Note: This is sort of like C's atexit(), only for DohExit(). However
+ * only one function can be registered (setting a new function overrides the
+ * previous one) and the registered function is passed the exit status so can
+ * vary its actions based on that.
+ */
+extern void DohSetExitHandler(void (*new_handler)(int));
+extern void DohExit(int status);
+
+/* -----------------------------------------------------------------------------
+ * Strings.
+ * ----------------------------------------------------------------------------- */
+
+extern DOHString *DohNewStringEmpty(void);
+extern DOHString *DohNewString(const DOHString_or_char *c);
+extern DOHString *DohNewStringWithSize(const DOHString_or_char *c, int len);
+extern DOHString *DohNewStringf(const DOHString_or_char *fmt, ...);
+
+extern int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2);
+extern int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n);
+extern char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2);
+extern char *DohStrchr(const DOHString_or_char *s1, int ch);
+
+/* String replacement flags */
+
+#define DOH_REPLACE_ANY 0x01
+#define DOH_REPLACE_NOQUOTE 0x02
+#define DOH_REPLACE_NOCOMMENT 0x04
+#define DOH_REPLACE_ID 0x08
+#define DOH_REPLACE_FIRST 0x10
+#define DOH_REPLACE_ID_BEGIN 0x20
+#define DOH_REPLACE_ID_END 0x40
+#define DOH_REPLACE_NUMBER_END 0x80
+
+#define Replaceall(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ANY)
+#define Replaceid(s,t,r) DohReplace(s,t,r,DOH_REPLACE_ID)
+
+/* -----------------------------------------------------------------------------
+ * Files
+ * ----------------------------------------------------------------------------- */
+
+extern DOHFile *DohNewFile(DOHString *filename, const char *mode, DOHList *outfiles);
+extern DOHFile *DohNewFileFromFile(FILE *f);
+extern DOHFile *DohNewFileFromFd(int fd);
+extern void DohFileErrorDisplay(DOHString * filename);
+extern int DohCopyto(DOHFile * input, DOHFile * output);
+extern void DohCloseAllOpenFiles(void);
+
+
+/* -----------------------------------------------------------------------------
+ * List
+ * ----------------------------------------------------------------------------- */
+
+extern DOHList *DohNewList(void);
+extern void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *));
+
+/* -----------------------------------------------------------------------------
+ * Hash
+ * ----------------------------------------------------------------------------- */
+
+extern DOHHash *DohNewHash(void);
+
+/* -----------------------------------------------------------------------------
+ * Void
+ * ----------------------------------------------------------------------------- */
+
+extern DOHVoid *DohNewVoid(void *ptr, void (*del) (void *));
+extern DOHList *DohSplit(DOHFile * input, char ch, int nsplits);
+extern DOHList *DohSplitLines(DOHFile * input);
+extern DOH *DohNone;
+
+/* Helper union for converting between function and object pointers. */
+typedef union DohFuncPtr {
+ void* p;
+ DOH *(*func)(DOH *);
+} DohFuncPtr_t;
+
+extern void DohMemoryDebug(void);
+
+#ifndef DOH_LONG_NAMES
+/* Macros to invoke the above functions. Includes the location of
+ the caller to simplify debugging if something goes wrong */
+
+#define Delete DohDelete
+#define Copy DohCopy
+#define Clear DohClear
+#define Str DohStr
+#define Dump DohDump
+#define Getattr DohGetattr
+#define Setattr DohSetattr
+#define Delattr DohDelattr
+#define Checkattr DohCheckattr
+#define Hashval DohHashval
+#define Getitem DohGetitem
+#define Setitem DohSetitem
+#define Delitem DohDelitem
+#define Insert DohInsertitem
+#define Delslice DohDelslice
+#define Append(s,x) DohInsertitem(s,DOH_END,x)
+#define Push(s,x) DohInsertitem(s,DOH_BEGIN,x)
+#define Len DohLen
+#define Data DohData
+#define Char(X) ((char *) Data(X))
+#define Cmp DohCmp
+#define Equal DohEqual
+#define Setline DohSetline
+#define Getline DohGetline
+#define Setfile DohSetfile
+#define Getfile DohGetfile
+#define Write DohWrite
+#define Read DohRead
+#define Seek DohSeek
+#define Tell DohTell
+#define Printf DohPrintf
+#define Printv DohPrintv
+#define Getc DohGetc
+#define Putc DohPutc
+#define Ungetc DohUngetc
+
+/* #define StringPutc DohStringPutc */
+/* #define StringGetc DohStringGetc */
+/* #define StringUngetc DohStringUngetc */
+/* #define StringAppend Append */
+/* #define StringLen DohStringLen */
+/* #define StringChar DohStringChar */
+/* #define StringEqual DohStringEqual */
+
+#define vPrintf DohvPrintf
+#define GetInt DohGetInt
+#define GetDouble DohGetDouble
+#define GetChar DohGetChar
+#define GetVoid DohGetVoid
+#define GetFlagAttr DohGetFlagAttr
+#define GetFlag DohGetFlag
+#define SetInt DohSetInt
+#define SetDouble DohSetDouble
+#define SetChar DohSetattr
+#define SetVoid DohSetVoid
+#define SetFlagAttr DohSetFlagAttr
+#define SetFlag DohSetFlag
+#define UnsetFlag(o,n) DohSetFlagAttr(o,n,NULL)
+#define ClearFlag(o,n) DohSetFlagAttr(o,n,"")
+#define Readline DohReadline
+#define Replace DohReplace
+#define Chop DohChop
+#define Getmeta DohGetmeta
+#define Setmeta DohSetmeta
+#define Delmeta DohDelmeta
+#define NewString DohNewString
+#define NewStringEmpty DohNewStringEmpty
+#define NewStringWithSize DohNewStringWithSize
+#define NewStringf DohNewStringf
+#define NewHash DohNewHash
+#define NewList DohNewList
+#define NewFile DohNewFile
+#define NewFileFromFile DohNewFileFromFile
+#define NewFileFromFd DohNewFileFromFd
+#define FileErrorDisplay DohFileErrorDisplay
+#define NewVoid DohNewVoid
+#define Keys DohKeys
+#define SortedKeys DohSortedKeys
+#define Strcmp DohStrcmp
+#define Strncmp DohStrncmp
+#define Strstr DohStrstr
+#define Strchr DohStrchr
+#define Copyto DohCopyto
+#define CloseAllOpenFiles DohCloseAllOpenFiles
+#define Split DohSplit
+#define SplitLines DohSplitLines
+#define Setmark DohSetmark
+#define Getmark DohGetmark
+#define SetMaxHashExpand DohSetMaxHashExpand
+#define GetMaxHashExpand DohGetMaxHashExpand
+#define None DohNone
+#define Call DohCall
+#define First DohFirst
+#define Next DohNext
+#define Iterator DohIterator
+#define SortList DohSortList
+#define Malloc DohMalloc
+#define Realloc DohRealloc
+#define Calloc DohCalloc
+#define Free DohFree
+#define SetExitHandler DohSetExitHandler
+#define Exit DohExit
+#endif
+
+#ifdef NIL
+#undef NIL
+#endif
+
+#define NIL (char *) NULL
+
+/* Defines to allow use of poisoned identifiers.
+ *
+ * For DOH-internal use only!
+ */
+#define doh_internal_calloc calloc
+#define doh_internal_exit exit
+/* doh_internal_free not needed as Free() is a macro defined above. */
+#define doh_internal_malloc malloc
+#define doh_internal_realloc realloc
+
+#if defined __GNUC__ && defined DOH_POISON
+/* Use Malloc(), Realloc(), Calloc(), and Free() instead (which will exit with
+ * an error rather than return NULL).
+ */
+# ifndef DOH_NO_POISON_MALLOC_FREE
+/* This works around bison's template checking if malloc and free are defined,
+ * which triggers GCC's poison checks.
+ */
+# pragma GCC poison malloc free
+# endif
+# pragma GCC poison realloc calloc
+/* Use Exit() instead (which will remove output files on error). */
+# pragma GCC poison abort exit
+#endif
+
+#endif /* SWIG_DOH_H */
diff --git a/contrib/tools/swig/Source/DOH/dohint.h b/contrib/tools/swig/Source/DOH/dohint.h
new file mode 100644
index 00000000000..6a6cfcdaf4e
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/dohint.h
@@ -0,0 +1,131 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * dohint.h
+ *
+ * This file describes internally managed objects.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DOHINT_H
+#define SWIG_DOHINT_H
+
+#include "doh.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+/* Hash objects */
+typedef struct {
+ DOH *(*doh_getattr) (DOH *obj, DOH *name); /* Get attribute */
+ int (*doh_setattr) (DOH *obj, DOH *name, DOH *value); /* Set attribute */
+ int (*doh_delattr) (DOH *obj, DOH *name); /* Del attribute */
+ DOH *(*doh_keys) (DOH *obj); /* All keys as a list */
+} DohHashMethods;
+
+/* List objects */
+typedef struct {
+ DOH *(*doh_getitem) (DOH *obj, int index); /* Get item */
+ int (*doh_setitem) (DOH *obj, int index, DOH *value); /* Set item */
+ int (*doh_delitem) (DOH *obj, int index); /* Delete item */
+ int (*doh_insitem) (DOH *obj, int index, DOH *value); /* Insert item */
+ int (*doh_delslice) (DOH *obj, int sindex, int eindex); /* Delete slice */
+} DohListMethods;
+
+/* File methods */
+typedef struct {
+ int (*doh_read) (DOH *obj, void *buffer, int nbytes); /* Read bytes */
+ int (*doh_write) (DOH *obj, const void *buffer, int nbytes); /* Write bytes */
+ int (*doh_putc) (DOH *obj, int ch); /* Put character */
+ int (*doh_getc) (DOH *obj); /* Get character */
+ int (*doh_ungetc) (DOH *obj, int ch); /* Unget character */
+ int (*doh_seek) (DOH *obj, long offset, int whence); /* Seek */
+ long (*doh_tell) (DOH *obj); /* Tell */
+} DohFileMethods;
+
+/* String methods */
+typedef struct {
+ int (*doh_replace) (DOH *obj, const DOHString_or_char *old, const DOHString_or_char *rep, int flags);
+ void (*doh_chop) (DOH *obj);
+} DohStringMethods;
+
+/* -----------------------------------------------------------------------------
+ * DohObjInfo
+ * ----------------------------------------------------------------------------- */
+
+typedef struct DohObjInfo {
+ const char *objname; /* Object name */
+
+ /* Basic object methods */
+ void (*doh_del) (DOH *obj); /* Delete object */
+ DOH *(*doh_copy) (DOH *obj); /* Copy and object */
+ void (*doh_clear) (DOH *obj); /* Clear an object */
+
+ /* I/O methods */
+ DOH *(*doh_str) (DOH *obj); /* Make a full string */
+ void *(*doh_data) (DOH *obj); /* Return raw data */
+ int (*doh_dump) (DOH *obj, DOH *out); /* Serialize on out */
+
+ /* Length and hash values */
+ int (*doh_len) (DOH *obj);
+ int (*doh_hashval) (DOH *obj);
+
+ /* Compare */
+ int (*doh_cmp) (DOH *obj1, DOH *obj2);
+
+ /* Equal */
+ int (*doh_equal) (DOH *obj1, DOH *obj2);
+
+ /* Iterators */
+ DohIterator (*doh_first) (DOH *obj);
+ DohIterator (*doh_next) (DohIterator);
+
+ /* Positional */
+ void (*doh_setfile) (DOH *obj, DOHString_or_char *file);
+ DOH *(*doh_getfile) (DOH *obj);
+ void (*doh_setline) (DOH *obj, int line);
+ int (*doh_getline) (DOH *obj);
+
+ DohHashMethods *doh_hash; /* Hash methods */
+ DohListMethods *doh_list; /* List methods */
+ DohFileMethods *doh_file; /* File methods */
+ DohStringMethods *doh_string; /* String methods */
+ void *doh_reserved; /* Reserved */
+ void *clientdata; /* User data */
+} DohObjInfo;
+
+typedef struct {
+ void *data; /* Data pointer */
+ DohObjInfo *type;
+ void *meta; /* Meta data */
+ unsigned int flag_intern:1; /* Interned object */
+ unsigned int flag_marked:1; /* Mark flag. Used to avoid recursive loops in places */
+ unsigned int flag_user:1; /* User flag */
+ unsigned int flag_usermark:1; /* User marked */
+ unsigned int refcount:28; /* Reference count (max 256 million) */
+} DohBase;
+
+/* Macros for decrefing and increfing (safe for null objects). */
+
+#define Decref(a) if (a) ((DohBase *) a)->refcount--
+#define Incref(a) if (a) ((DohBase *) a)->refcount++
+#define Refcount(a) ((DohBase *) a)->refcount
+
+/* Macros for manipulating objects in a safe manner */
+#define ObjData(a) ((DohBase *)a)->data
+#define ObjSetMark(a,x) ((DohBase *)a)->flag_marked = x
+#define ObjGetMark(a) ((DohBase *)a)->flag_marked
+#define ObjType(a) ((DohBase *)a)->type
+
+extern DOH *DohObjMalloc(DohObjInfo *type, void *data); /* Allocate a DOH object */
+extern void DohObjFree(DOH *ptr); /* Free a DOH object */
+
+#endif /* SWIG_DOHINT_H */
diff --git a/contrib/tools/swig/Source/DOH/file.c b/contrib/tools/swig/Source/DOH/file.c
new file mode 100644
index 00000000000..4bcf5d5e1d7
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/file.c
@@ -0,0 +1,342 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * file.c
+ *
+ * This file implements a file-like object that can be built around an
+ * ordinary FILE * or integer file descriptor.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+#ifdef DOH_INTFILE
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+typedef struct {
+ FILE *filep;
+ int fd;
+ int closeondel;
+} DohFile;
+
+/* -----------------------------------------------------------------------------
+ * open_files_list_instance
+ * open_files_list_add
+ * open_files_list_remove
+ *
+ * Singleton list containing all the files that have been opened by DohNewFile.
+ * Open file pointers are held in the list as strings so as to not affect the
+ * reference count of the underlying DOH objects.
+ * ----------------------------------------------------------------------------- */
+
+static DOHList *open_files_list_instance(void) {
+ static DOHList *all_open_files = 0;
+ if (!all_open_files)
+ all_open_files = DohNewList();
+ return all_open_files;
+}
+
+static void open_files_list_add(DohFile *f) {
+ DOHList *all_open_files = open_files_list_instance();
+ DOHString *sf = NewStringf("%p", f);
+ Append(all_open_files, sf);
+ Delete(sf);
+}
+
+static void open_files_list_remove(DohFile *f) {
+ int i;
+ int removed = 0;
+ DOHList *all_open_files = open_files_list_instance();
+ DOHString *sf = NewStringf("%p", f);
+ for (i = 0; i < DohLen(all_open_files); i++) {
+ DOHString *sf_i = Getitem(all_open_files, i);
+ if (Strcmp(sf, sf_i) == 0) {
+ DohDelitem(all_open_files, i);
+ removed = 1;
+ break;
+ }
+ }
+ Delete(sf);
+ assert(removed);
+ (void)removed;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCloseAllOpenFiles()
+ *
+ * Close all opened files, to be called on program termination
+ * ----------------------------------------------------------------------------- */
+
+void DohCloseAllOpenFiles(void) {
+ int i;
+ DOHList *all_open_files = open_files_list_instance();
+ for (i = 0; i < DohLen(all_open_files); i++) {
+ DohFile *f = 0;
+ DOHString *sf = Getitem(all_open_files, i);
+ int check = sscanf(Char(sf), "%p", (void **)&f);
+ assert(check == 1);
+ (void)check;
+ if (f->closeondel) {
+ if (f->filep) {
+ check = fclose(f->filep);
+ assert(check == 0);
+ }
+ f->closeondel = 0;
+ f->filep = 0;
+ }
+ }
+ DohClear(all_open_files);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelFile()
+ * ----------------------------------------------------------------------------- */
+
+static void DelFile(DOH *fo) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->closeondel) {
+ if (f->filep) {
+ fclose(f->filep);
+ }
+#ifdef DOH_INTFILE
+ if (f->fd) {
+ close(f->fd);
+ }
+#endif
+ open_files_list_remove(f);
+ }
+ DohFree(f);
+}
+
+/* -----------------------------------------------------------------------------
+ * File_read()
+ * ----------------------------------------------------------------------------- */
+
+static int File_read(DOH *fo, void *buffer, int len) {
+ DohFile *f = (DohFile *) ObjData(fo);
+
+ if (f->filep) {
+ return (int)fread(buffer, 1, len, f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return read(f->fd, buffer, len);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_write()
+ * ----------------------------------------------------------------------------- */
+
+static int File_write(DOH *fo, const void *buffer, int len) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ int ret = (int) fwrite(buffer, 1, len, f->filep);
+ int err = (ret != len) ? ferror(f->filep) : 0;
+ return err ? -1 : ret;
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return write(f->fd, buffer, len);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_seek()
+ * ----------------------------------------------------------------------------- */
+
+static int File_seek(DOH *fo, long offset, int whence) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return fseek(f->filep, offset, whence);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return lseek(f->fd, offset, whence);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_tell()
+ * ----------------------------------------------------------------------------- */
+
+static long File_tell(DOH *fo) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return ftell(f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ return lseek(f->fd, 0, SEEK_CUR);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_putc()
+ * ----------------------------------------------------------------------------- */
+
+static int File_putc(DOH *fo, int ch) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return fputc(ch, f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ char c;
+ c = (char) ch;
+ return write(f->fd, &c, 1);
+#endif
+ }
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_getc()
+ * ----------------------------------------------------------------------------- */
+
+static int File_getc(DOH *fo) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return fgetc(f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ unsigned char c;
+ if (read(f->fd, &c, 1) < 0)
+ return EOF;
+ return c;
+#endif
+ }
+ return EOF;
+}
+
+/* -----------------------------------------------------------------------------
+ * File_ungetc()
+ *
+ * Put a character back onto the input
+ * ----------------------------------------------------------------------------- */
+
+static int File_ungetc(DOH *fo, int ch) {
+ DohFile *f = (DohFile *) ObjData(fo);
+ if (f->filep) {
+ return ungetc(ch, f->filep);
+ } else if (f->fd) {
+#ifdef DOH_INTFILE
+ /* Not implemented yet */
+#endif
+ }
+ return -1;
+}
+
+static DohFileMethods FileFileMethods = {
+ File_read,
+ File_write,
+ File_putc,
+ File_getc,
+ File_ungetc,
+ File_seek,
+ File_tell,
+};
+
+static DohObjInfo DohFileType = {
+ "DohFile", /* objname */
+ DelFile, /* doh_del */
+ 0, /* doh_copy */
+ 0, /* doh_clear */
+ 0, /* doh_str */
+ 0, /* doh_data */
+ 0, /* doh_dump */
+ 0, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ 0, /* doh_first */
+ 0, /* doh_next */
+ 0, /* doh_setfile */
+ 0, /* doh_getfile */
+ 0, /* doh_setline */
+ 0, /* doh_getline */
+ 0, /* doh_mapping */
+ 0, /* doh_sequence */
+ &FileFileMethods, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_callable */
+ 0, /* doh_position */
+};
+
+/* -----------------------------------------------------------------------------
+ * NewFile()
+ *
+ * Create a new file from a given filename and mode.
+ * If newfiles is non-zero, the filename is added to the list of new files.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewFile(DOHString *filename, const char *mode, DOHList *newfiles) {
+ DohFile *f;
+ DOH *obj;
+ FILE *file;
+ char *filen;
+
+ filen = Char(filename);
+ file = fopen(filen, mode);
+ if (!file)
+ return 0;
+
+ f = (DohFile *) DohMalloc(sizeof(DohFile));
+ if (newfiles)
+ Append(newfiles, filename);
+ f->filep = file;
+ f->fd = 0;
+ f->closeondel = 1;
+ obj = DohObjMalloc(&DohFileType, f);
+ open_files_list_add(f);
+ return obj;
+}
+
+/* -----------------------------------------------------------------------------
+ * NewFileFromFile()
+ *
+ * Create a file object from an already open FILE *.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewFileFromFile(FILE *file) {
+ DohFile *f;
+ f = (DohFile *) DohMalloc(sizeof(DohFile));
+ f->filep = file;
+ f->fd = 0;
+ f->closeondel = 0;
+ return DohObjMalloc(&DohFileType, f);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewFileFromFd()
+ *
+ * Create a file object from an already open FILE *.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewFileFromFd(int fd) {
+ DohFile *f;
+ f = (DohFile *) DohMalloc(sizeof(DohFile));
+ f->filep = 0;
+ f->fd = fd;
+ f->closeondel = 0;
+ return DohObjMalloc(&DohFileType, f);
+}
+
+/* -----------------------------------------------------------------------------
+ * FileErrorDisplay()
+ *
+ * Display cause of one of the NewFile functions failing.
+ * ----------------------------------------------------------------------------- */
+
+void DohFileErrorDisplay(DOHString * filename) {
+ Printf(stderr, "Unable to open file %s: %s\n", filename, strerror(errno));
+}
diff --git a/contrib/tools/swig/Source/DOH/fio.c b/contrib/tools/swig/Source/DOH/fio.c
new file mode 100644
index 00000000000..cafcb11f871
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/fio.c
@@ -0,0 +1,610 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * fio.c
+ *
+ * This file implements a number of standard I/O operations included
+ * formatted output, readline, and splitting.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+#define OBUFLEN 512
+
+static DOH *encodings = 0; /* Encoding hash */
+
+/* -----------------------------------------------------------------------------
+ * Writen()
+ *
+ * Writes N characters of output and retries until all characters are
+ * written. This is useful should a write operation encounter a spurious signal.
+ * ----------------------------------------------------------------------------- */
+
+static int Writen(DOH *out, void *buffer, int len) {
+ int nw = len, ret;
+ char *cb = (char *) buffer;
+ while (nw) {
+ ret = Write(out, cb, nw);
+ if (ret < 0)
+ return -1;
+ nw = nw - ret;
+ cb += ret;
+ }
+ return len;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohEncoding()
+ *
+ * Registers a new printf encoding method. An encoder function should accept
+ * two file-like objects and operate as a filter.
+ * ----------------------------------------------------------------------------- */
+
+void DohEncoding(const char *name, DOH *(*fn) (DOH *s)) {
+ DohFuncPtr_t fp;
+
+ if (!encodings)
+ encodings = NewHash();
+
+ fp.func = fn;
+ Setattr(encodings, (void *) name, NewVoid(fp.p, 0));
+}
+
+/* internal function for processing an encoding */
+static DOH *encode(char *name, DOH *s) {
+ DOH *handle, *ns;
+ DohFuncPtr_t fp;
+ long pos;
+ char *cfmt = strchr(name, ':');
+ DOH *tmp = 0;
+ if (cfmt) {
+ tmp = NewString(cfmt + 1);
+ Append(tmp, s);
+ Setfile(tmp, Getfile((DOH *) s));
+ Setline(tmp, Getline((DOH *) s));
+ *cfmt = '\0';
+ }
+ if (!encodings || !(handle = Getattr(encodings, name))) {
+ return Copy(s);
+ }
+ if (tmp)
+ s = tmp;
+ pos = Tell(s);
+ Seek(s, 0, SEEK_SET);
+
+ fp.p = Data(handle);
+ ns = (*fp.func) (s);
+ assert(pos != -1);
+ (void)Seek(s, pos, SEEK_SET);
+ if (tmp)
+ Delete(tmp);
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohvPrintf()
+ *
+ * DOH implementation of printf. Output can be directed to any file-like object
+ * including bare FILE * objects. The same formatting codes as printf are
+ * recognized with two extensions:
+ *
+ * %s - Prints a "char *" or the string representation of any
+ * DOH object. This will implicitly result in a call to
+ * Str(obj).
+ *
+ * %(encoder)* - Filters the output through an encoding function registered
+ * with DohEncoder().
+ *
+ * Note: This function is not particularly memory efficient with large strings.
+ * It's better to use Dump() or some other method instead.
+ * ----------------------------------------------------------------------------- */
+
+int DohvPrintf(DOH *so, const char *format, va_list ap) {
+ static const char *fmt_codes = "dioxXucsSfeEgGpn";
+ int state = 0;
+ const char *p = format;
+ char newformat[256];
+ char obuffer[OBUFLEN];
+ char *fmt = 0;
+ char temp[64];
+ int widthval = 0;
+ int precval = 0;
+ int maxwidth;
+ char *w = 0;
+ char *stemp;
+ int nbytes = 0;
+ char encoder[128], *ec = 0;
+ int plevel = 0;
+
+ memset(newformat, 0, sizeof(newformat));
+
+ while (*p) {
+ switch (state) {
+ case 0: /* Ordinary text */
+ if (*p != '%') {
+ Putc(*p, so);
+ nbytes++;
+ } else {
+ fmt = newformat;
+ widthval = 0;
+ precval = 0;
+ *(fmt++) = *p;
+ encoder[0] = 0;
+ state = 10;
+ }
+ break;
+ case 10: /* Look for a width and precision */
+ if (isdigit((int) *p) && (*p != '0')) {
+ w = temp;
+ *(w++) = *p;
+ *(fmt++) = *p;
+ state = 20;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ p--;
+ state = 100;
+ } else if (*p == '*') {
+ /* Width field is specified in the format list */
+ widthval = va_arg(ap, int);
+ sprintf(temp, "%d", widthval);
+ for (w = temp; *w; w++) {
+ *(fmt++) = *w;
+ }
+ state = 30;
+ } else if (*p == '%') {
+ Putc(*p, so);
+ fmt = newformat;
+ nbytes++;
+ state = 0;
+ } else if (*p == '(') {
+ ++plevel;
+ ec = encoder;
+ state = 60;
+ } else {
+ *(fmt++) = *p;
+ }
+ break;
+
+ case 20: /* Hmmm. At the start of a width field */
+ if (isdigit((int) *p)) {
+ *(w++) = *p;
+ *(fmt++) = *p;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ /* Figure out width */
+ *w = 0;
+ widthval = atoi(temp);
+ p--;
+ state = 100;
+ } else if (*p == '.') {
+ *w = 0;
+ widthval = atoi(temp);
+ w = temp;
+ *(fmt++) = *p;
+ state = 40;
+ } else {
+ /* ??? */
+ *w = 0;
+ widthval = atoi(temp);
+ state = 50;
+ }
+ break;
+
+ case 30: /* Parsed a width from an argument. Look for a . */
+ if (*p == '.') {
+ w = temp;
+ *(fmt++) = *p;
+ state = 40;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ /* Figure out width */
+ p--;
+ state = 100;
+ } else {
+ /* hmmm. Something else. */
+ state = 50;
+ }
+ break;
+
+ case 40:
+ /* Start of precision expected */
+ if (isdigit((int) *p) && (*p != '0')) {
+ *(fmt++) = *p;
+ *(w++) = *p;
+ state = 41;
+ } else if (*p == '*') {
+ /* Precision field is specified in the format list */
+ precval = va_arg(ap, int);
+ sprintf(temp, "%d", precval);
+ for (w = temp; *w; w++) {
+ *(fmt++) = *w;
+ }
+ state = 50;
+ } else if (strchr(fmt_codes, *p)) {
+ p--;
+ state = 100;
+ } else {
+ *(fmt++) = *p;
+ state = 50;
+ }
+ break;
+ case 41:
+ if (isdigit((int) *p)) {
+ *(fmt++) = *p;
+ *(w++) = *p;
+ } else if (strchr(fmt_codes, *p)) {
+ /* Got one of the formatting codes */
+ /* Figure out width */
+ *w = 0;
+ precval = atoi(temp);
+ p--;
+ state = 100;
+ } else {
+ *w = 0;
+ precval = atoi(temp);
+ *(fmt++) = *p;
+ state = 50;
+ }
+ break;
+ /* Hang out, wait for format specifier */
+ case 50:
+ if (strchr(fmt_codes, *p)) {
+ p--;
+ state = 100;
+ } else {
+ *(fmt++) = *p;
+ }
+ break;
+
+ /* Got an encoding header */
+ case 60:
+ if (*p == '(') {
+ ++plevel;
+ *ec = *p;
+ ec++;
+ } else if (*p == ')') {
+ --plevel;
+ if (plevel <= 0) {
+ *ec = 0;
+ state = 10;
+ } else {
+ *ec = *p;
+ ec++;
+ }
+ } else {
+ *ec = *p;
+ ec++;
+ }
+ break;
+ case 100:
+ /* Got a formatting code */
+ if (widthval < precval)
+ maxwidth = precval;
+ else
+ maxwidth = widthval;
+ if ((*p == 's') || (*p == 'S')) { /* Null-Terminated string */
+ DOH *doh;
+ DOH *Sval;
+ DOH *enc = 0;
+ doh = va_arg(ap, DOH *);
+ if (DohCheck(doh)) {
+ /* Is a DOH object. */
+ if (DohIsString(doh)) {
+ Sval = doh;
+ } else {
+ Sval = Str(doh);
+ }
+ if (strlen(encoder)) {
+ enc = encode(encoder, Sval);
+ maxwidth = maxwidth + (int)strlen(newformat) + Len(enc);
+ } else {
+ maxwidth = maxwidth + (int)strlen(newformat) + Len(Sval);
+ }
+ *(fmt++) = 's';
+ *fmt = 0;
+ if ((maxwidth + 1) < OBUFLEN) {
+ stemp = obuffer;
+ } else {
+ stemp = (char *) DohMalloc(maxwidth + 1);
+ }
+ if (enc) {
+ nbytes += sprintf(stemp, newformat, Data(enc));
+ } else {
+ nbytes += sprintf(stemp, newformat, Data(Sval));
+ }
+ if (Writen(so, stemp, (int)strlen(stemp)) < 0)
+ return -1;
+ if ((DOH *) Sval != doh) {
+ Delete(Sval);
+ }
+ if (enc)
+ Delete(enc);
+ if (*p == 'S') {
+ Delete(doh);
+ }
+ if (stemp != obuffer) {
+ DohFree(stemp);
+ }
+ } else {
+ if (!doh)
+ doh = (char *) "";
+
+ if (strlen(encoder)) {
+ DOH *s = NewString(doh);
+ Seek(s, 0, SEEK_SET);
+ enc = encode(encoder, s);
+ Delete(s);
+ doh = Char(enc);
+ } else {
+ enc = 0;
+ }
+ maxwidth = maxwidth + (int)strlen(newformat) + (int)strlen((char *) doh);
+ *(fmt++) = 's';
+ *fmt = 0;
+ if ((maxwidth + 1) < OBUFLEN) {
+ stemp = obuffer;
+ } else {
+ stemp = (char *) DohMalloc(maxwidth + 1);
+ }
+ nbytes += sprintf(stemp, newformat, doh);
+ if (Writen(so, stemp, (int)strlen(stemp)) < 0)
+ return -1;
+ if (stemp != obuffer) {
+ DohFree(stemp);
+ }
+ if (enc)
+ Delete(enc);
+ }
+ } else {
+ *(fmt++) = *p;
+ *fmt = 0;
+ maxwidth = maxwidth + (int)strlen(newformat) + 64;
+
+ /* Only allocate a buffer if it is too big to fit. Shouldn't have to do
+ this very often */
+
+ if (maxwidth < OBUFLEN)
+ stemp = obuffer;
+ else
+ stemp = (char *) DohMalloc(maxwidth + 1);
+ switch (*p) {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (p[-1] == 'l') {
+ if (p[-2] == 'l') {
+ long long llvalue = va_arg(ap, long long);
+ nbytes += sprintf(stemp, newformat, llvalue);
+ break;
+ }
+ long lvalue = va_arg(ap, long);
+ nbytes += sprintf(stemp, newformat, lvalue);
+ break;
+ }
+ /* FALLTHRU */
+ case 'c': {
+ int ivalue = va_arg(ap, int);
+ nbytes += sprintf(stemp, newformat, ivalue);
+ break;
+ }
+ case 'f':
+ case 'g':
+ case 'e':
+ case 'E':
+ case 'G': {
+ double dvalue = va_arg(ap, double);
+ nbytes += sprintf(stemp, newformat, dvalue);
+ break;
+ }
+ case 'p': {
+ void *pvalue = va_arg(ap, void *);
+ nbytes += sprintf(stemp, newformat, pvalue);
+ break;
+ }
+ default:
+ break;
+ }
+ if (Writen(so, stemp, (int)strlen(stemp)) < 0)
+ return -1;
+ if (stemp != obuffer)
+ DohFree(stemp);
+ }
+ state = 0;
+ break;
+ }
+ p++;
+ }
+ if (state) {
+ int r;
+ *fmt = 0;
+ r = Writen(so, fmt, (int)strlen(fmt));
+ if (r < 0)
+ return -1;
+ nbytes += r;
+ }
+ return nbytes;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPrintf()
+ *
+ * Variable length argument entry point to Printf
+ * ----------------------------------------------------------------------------- */
+
+int DohPrintf(DOH *obj, const char *format, ...) {
+ va_list ap;
+ int ret;
+ va_start(ap, format);
+ ret = DohvPrintf(obj, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohPrintv()
+ *
+ * Print a null-terminated variable length list of DOH objects
+ * ----------------------------------------------------------------------------- */
+
+int DohPrintv(DOHFile * f, ...) {
+ va_list ap;
+ int ret = 0;
+ DOH *obj;
+ va_start(ap, f);
+ while (1) {
+ obj = va_arg(ap, void *);
+ if ((!obj) || (obj == DohNone))
+ break;
+ if (DohCheck(obj)) {
+ ret += DohDump(obj, f);
+ } else {
+ ret += DohWrite(f, obj, (int)strlen((char *) obj));
+ }
+ }
+ va_end(ap);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohCopyto()
+ *
+ * Copies all of the input from an input stream to an output stream. Returns the
+ * number of bytes copied.
+ * ----------------------------------------------------------------------------- */
+
+int DohCopyto(DOH *in, DOH *out) {
+ int nbytes = 0, ret;
+ int nwrite = 0, wret;
+ char *cw;
+ char buffer[16384];
+
+ if ((!in) || (!out))
+ return 0;
+ while (1) {
+ ret = Read(in, buffer, 16384);
+ if (ret > 0) {
+ nwrite = ret;
+ cw = buffer;
+ while (nwrite) {
+ wret = Write(out, cw, nwrite);
+ if (wret < 0) {
+ nbytes = -1;
+ break;
+ }
+ nwrite = nwrite - wret;
+ cw += wret;
+ }
+ nbytes += ret;
+ } else {
+ break;
+ }
+ }
+ return nbytes;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohSplit()
+ *
+ * Split an input stream into a list of strings delimited by the specified
+ * character. Optionally accepts a maximum number of splits to perform.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohSplit(DOH *in, char ch, int nsplits) {
+ DOH *list;
+ DOH *str;
+ int c;
+
+ list = NewList();
+
+ if (DohIsString(in)) {
+ Seek(in, 0, SEEK_SET);
+ }
+
+ while (1) {
+ str = NewStringEmpty();
+ do {
+ c = Getc(in);
+ } while ((c != EOF) && (c == ch));
+ if (c != EOF) {
+ Putc(c, str);
+ while (1) {
+ c = Getc(in);
+ if ((c == EOF) || ((c == ch) && (nsplits != 0)))
+ break;
+ Putc(c, str);
+ }
+ nsplits--;
+ }
+ Append(list, str);
+ Delete(str);
+ if (c == EOF)
+ break;
+ }
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSplitLines()
+ *
+ * Split an input stream into a list of strings delimited by newline characters.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohSplitLines(DOH *in) {
+ DOH *list;
+ DOH *str;
+ int c = 0;
+
+ list = NewList();
+
+ if (DohIsString(in)) {
+ Seek(in, 0, SEEK_SET);
+ }
+
+ while (c != EOF) {
+ str = NewStringEmpty();
+ while ((c = Getc(in)) != '\n' && c != EOF) {
+ Putc(c, str);
+ }
+ Append(list, str);
+ Delete(str);
+ }
+ return list;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * DohReadline()
+ *
+ * Read a single input line and return it as a string.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohReadline(DOH *in) {
+ char c;
+ int n = 0;
+ DOH *s = NewStringEmpty();
+ while (1) {
+ if (Read(in, &c, 1) < 0) {
+ if (n == 0) {
+ Delete(s);
+ s = 0;
+ }
+ break;
+ }
+ if (c == '\n')
+ break;
+ if (c == '\r')
+ continue;
+ Putc(c, s);
+ n++;
+ }
+ return s;
+}
diff --git a/contrib/tools/swig/Source/DOH/hash.c b/contrib/tools/swig/Source/DOH/hash.c
new file mode 100644
index 00000000000..1a29b350122
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/hash.c
@@ -0,0 +1,584 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * hash.c
+ *
+ * Implements a simple hash table object.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+extern DohObjInfo DohHashType;
+
+/* Hash node */
+typedef struct HashNode {
+ DOH *key;
+ DOH *object;
+ struct HashNode *next;
+} HashNode;
+
+/* Hash object */
+typedef struct Hash {
+ DOH *file;
+ int line;
+ HashNode **hashtable;
+ int hashsize;
+ int nitems;
+} Hash;
+
+/* Key interning structure */
+typedef struct KeyValue {
+ char *cstr;
+ DOH *sstr;
+ struct KeyValue *left;
+ struct KeyValue *right;
+} KeyValue;
+
+static KeyValue *root = 0;
+static int max_expand = 1;
+
+/* Find or create a key in the interned key table */
+static DOH *find_key(DOH *doh_c) {
+ char *c = (char *) doh_c;
+ KeyValue *r, *s;
+ int d = 0;
+ /* OK, sure, we use a binary tree for maintaining interned
+ symbols. Then we use their hash values for accessing secondary
+ hash tables. */
+ r = root;
+ s = 0;
+ while (r) {
+ s = r;
+ d = strcmp(r->cstr, c);
+ if (d == 0)
+ return r->sstr;
+ if (d < 0)
+ r = r->left;
+ else
+ r = r->right;
+ }
+ /* fprintf(stderr,"Interning '%s'\n", c); */
+ r = (KeyValue *) DohMalloc(sizeof(KeyValue));
+ r->cstr = (char *) DohMalloc(strlen(c) + 1);
+ strcpy(r->cstr, c);
+ r->sstr = NewString(c);
+ DohIntern(r->sstr);
+ r->left = 0;
+ r->right = 0;
+ if (!s) {
+ root = r;
+ } else {
+ if (d < 0)
+ s->left = r;
+ else
+ s->right = r;
+ }
+ return r->sstr;
+}
+
+#define HASH_INIT_SIZE 7
+
+/* Create a new hash node */
+static HashNode *NewNode(DOH *k, void *obj) {
+ HashNode *hn = (HashNode *) DohMalloc(sizeof(HashNode));
+ hn->key = k;
+ Incref(hn->key);
+ hn->object = obj;
+ Incref(obj);
+ hn->next = 0;
+ return hn;
+}
+
+/* Delete a hash node */
+static void DelNode(HashNode *hn) {
+ Delete(hn->key);
+ Delete(hn->object);
+ DohFree(hn);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelHash()
+ *
+ * Delete a hash table.
+ * ----------------------------------------------------------------------------- */
+
+static void DelHash(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ HashNode *n, *next;
+ int i;
+
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ next = n->next;
+ DelNode(n);
+ n = next;
+ }
+ }
+ DohFree(h->hashtable);
+ h->hashtable = 0;
+ h->hashsize = 0;
+ DohFree(h);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_clear()
+ *
+ * Clear all of the entries in the hash table.
+ * File and line numbering info left unmodified.
+ * ----------------------------------------------------------------------------- */
+
+static void Hash_clear(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ HashNode *n, *next;
+ int i;
+
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ next = n->next;
+ DelNode(n);
+ n = next;
+ }
+ h->hashtable[i] = 0;
+ }
+ h->nitems = 0;
+}
+
+/* resize the hash table */
+static void resize(Hash *h) {
+ HashNode *n, *next, **table;
+ int oldsize, newsize;
+ int i, p, hv;
+
+ if (h->nitems < 2 * h->hashsize)
+ return;
+
+ /* Too big. We have to rescale everything now */
+ oldsize = h->hashsize;
+
+ /* Calculate a new size */
+ newsize = 2 * oldsize + 1;
+ p = 3;
+ while (p < (newsize >> 1)) {
+ if (((newsize / p) * p) == newsize) {
+ newsize += 2;
+ p = 3;
+ continue;
+ }
+ p = p + 2;
+ }
+
+ table = (HashNode **) DohCalloc(newsize, sizeof(HashNode *));
+
+ /* Walk down the old set of nodes and re-place */
+ h->hashsize = newsize;
+ for (i = 0; i < oldsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ hv = Hashval(n->key) % newsize;
+ next = n->next;
+ n->next = table[hv];
+ table[hv] = n;
+ n = next;
+ }
+ }
+ DohFree(h->hashtable);
+ h->hashtable = table;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_setattr()
+ *
+ * Set an attribute in the hash table. Deletes the existing entry if it already
+ * exists.
+ * ----------------------------------------------------------------------------- */
+
+static int Hash_setattr(DOH *ho, DOH *k, DOH *obj) {
+ int hv;
+ HashNode *n, *prev;
+ Hash *h = (Hash *) ObjData(ho);
+
+ if (!obj) {
+ return DohDelattr(ho, k);
+ }
+ if (!DohCheck(k))
+ k = find_key(k);
+ if (!DohCheck(obj)) {
+ obj = NewString((char *) obj);
+ Decref(obj);
+ }
+ hv = (Hashval(k)) % h->hashsize;
+ n = h->hashtable[hv];
+ prev = 0;
+ while (n) {
+ if (Cmp(n->key, k) == 0) {
+ /* Node already exists. Just replace its contents */
+ if (n->object == obj) {
+ /* Whoa. Same object. Do nothing */
+ return 1;
+ }
+ Delete(n->object);
+ n->object = obj;
+ Incref(obj);
+ return 1; /* Return 1 to indicate a replacement */
+ } else {
+ prev = n;
+ n = n->next;
+ }
+ }
+ /* Add this to the table */
+ n = NewNode(k, obj);
+ if (prev)
+ prev->next = n;
+ else
+ h->hashtable[hv] = n;
+ h->nitems++;
+ resize(h);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_getattr()
+ *
+ * Get an attribute from the hash table. Returns 0 if it doesn't exist.
+ * ----------------------------------------------------------------------------- */
+typedef int (*binop) (DOH *obj1, DOH *obj2);
+
+
+static DOH *Hash_getattr(DOH *h, DOH *k) {
+ DOH *obj = 0;
+ Hash *ho = (Hash *) ObjData(h);
+ DOH *ko = DohCheck(k) ? k : find_key(k);
+ int hv = Hashval(ko) % ho->hashsize;
+ DohObjInfo *k_type = ((DohBase*)ko)->type;
+ HashNode *n = ho->hashtable[hv];
+ if (k_type->doh_equal) {
+ binop equal = k_type->doh_equal;
+ while (n) {
+ DohBase *nk = (DohBase *)n->key;
+ if ((k_type == nk->type) && equal(ko, nk)) obj = n->object;
+ n = n->next;
+ }
+ } else {
+ binop cmp = k_type->doh_cmp;
+ while (n) {
+ DohBase *nk = (DohBase *)n->key;
+ if ((k_type == nk->type) && (cmp(ko, nk) == 0)) obj = n->object;
+ n = n->next;
+ }
+ }
+ return obj;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_delattr()
+ *
+ * Delete an object from the hash table.
+ * ----------------------------------------------------------------------------- */
+
+static int Hash_delattr(DOH *ho, DOH *k) {
+ HashNode *n, *prev;
+ int hv;
+ Hash *h = (Hash *) ObjData(ho);
+
+ if (!DohCheck(k))
+ k = find_key(k);
+ hv = Hashval(k) % h->hashsize;
+ n = h->hashtable[hv];
+ prev = 0;
+ while (n) {
+ if (Cmp(n->key, k) == 0) {
+ /* Found it, kill it */
+
+ if (prev) {
+ prev->next = n->next;
+ } else {
+ h->hashtable[hv] = n->next;
+ }
+ DelNode(n);
+ h->nitems--;
+ return 1;
+ }
+ prev = n;
+ n = n->next;
+ }
+ return 0;
+}
+
+static DohIterator Hash_firstiter(DOH *ho) {
+ DohIterator iter;
+ Hash *h = (Hash *) ObjData(ho);
+ iter.object = ho;
+ iter._current = 0;
+ iter.item = 0;
+ iter.key = 0;
+ iter._index = 0; /* Index in hash table */
+ while ((iter._index < h->hashsize) && !h->hashtable[iter._index])
+ iter._index++;
+
+ if (iter._index >= h->hashsize) {
+ return iter;
+ }
+ iter._current = h->hashtable[iter._index];
+ iter.item = ((HashNode *) iter._current)->object;
+ iter.key = ((HashNode *) iter._current)->key;
+
+ /* Actually save the next slot in the hash. This makes it possible to
+ delete the item being iterated over without trashing the universe */
+ iter._current = ((HashNode *) iter._current)->next;
+ return iter;
+}
+
+static DohIterator Hash_nextiter(DohIterator iter) {
+ Hash *h = (Hash *) ObjData(iter.object);
+ if (!iter._current) {
+ iter._index++;
+ while ((iter._index < h->hashsize) && !h->hashtable[iter._index]) {
+ iter._index++;
+ }
+ if (iter._index >= h->hashsize) {
+ iter.item = 0;
+ iter.key = 0;
+ iter._current = 0;
+ return iter;
+ }
+ iter._current = h->hashtable[iter._index];
+ }
+ iter.key = ((HashNode *) iter._current)->key;
+ iter.item = ((HashNode *) iter._current)->object;
+
+ /* Store the next node to iterator on */
+ iter._current = ((HashNode *) iter._current)->next;
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_keys()
+ *
+ * Return a list of keys
+ * ----------------------------------------------------------------------------- */
+
+static DOH *Hash_keys(DOH *so) {
+ DOH *keys;
+ Iterator i;
+
+ keys = NewList();
+ for (i = First(so); i.key; i = Next(i)) {
+ Append(keys, i.key);
+ }
+ return keys;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohSetMaxHashExpand()
+ *
+ * Controls how many Hash objects are displayed in full in Hash_str
+ * ----------------------------------------------------------------------------- */
+
+void DohSetMaxHashExpand(int count) {
+ max_expand = count;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetMaxHashExpand()
+ *
+ * Returns how many Hash objects are displayed in full in Hash_str
+ * ----------------------------------------------------------------------------- */
+
+int DohGetMaxHashExpand(void) {
+ return max_expand;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_str()
+ *
+ * Create a string representation of a hash table (mainly for debugging).
+ * ----------------------------------------------------------------------------- */
+
+static DOH *Hash_str(DOH *ho) {
+ int i, j;
+ HashNode *n;
+ DOH *s;
+ static int expanded = 0;
+ static const char *tab = " ";
+ Hash *h = (Hash *) ObjData(ho);
+
+ s = NewStringEmpty();
+ if (ObjGetMark(ho)) {
+ Printf(s, "Hash(%p)", ho);
+ return s;
+ }
+ if (expanded >= max_expand) {
+ /* replace each hash attribute with a '.' */
+ Printf(s, "Hash(%p) {", ho);
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ Putc('.', s);
+ n = n->next;
+ }
+ }
+ Putc('}', s);
+ return s;
+ }
+ ObjSetMark(ho, 1);
+ Printf(s, "Hash(%p) {\n", ho);
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ for (j = 0; j < expanded + 1; j++)
+ Printf(s, tab);
+ expanded += 1;
+ Printf(s, "'%s' : %s, \n", n->key, n->object);
+ expanded -= 1;
+ n = n->next;
+ }
+ }
+ for (j = 0; j < expanded; j++)
+ Printf(s, tab);
+ Printf(s, "}");
+ ObjSetMark(ho, 0);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash_len()
+ *
+ * Return number of entries in the hash table.
+ * ----------------------------------------------------------------------------- */
+
+static int Hash_len(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ return h->nitems;
+}
+
+/* -----------------------------------------------------------------------------
+ * CopyHash()
+ *
+ * Make a copy of a hash table. Note: this is a shallow copy.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *CopyHash(DOH *ho) {
+ Hash *h, *nh;
+ HashNode *n;
+ DOH *nho;
+
+ int i;
+ h = (Hash *) ObjData(ho);
+ nh = (Hash *) DohMalloc(sizeof(Hash));
+ nh->hashsize = h->hashsize;
+ nh->hashtable = (HashNode **) DohMalloc(nh->hashsize * sizeof(HashNode *));
+ for (i = 0; i < nh->hashsize; i++) {
+ nh->hashtable[i] = 0;
+ }
+ nh->nitems = 0;
+ nh->line = h->line;
+ nh->file = h->file;
+ if (nh->file)
+ Incref(nh->file);
+
+ nho = DohObjMalloc(&DohHashType, nh);
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ Hash_setattr(nho, n->key, n->object);
+ n = n->next;
+ }
+ }
+ return nho;
+}
+
+
+
+static void Hash_setfile(DOH *ho, DOH *file) {
+ DOH *fo;
+ Hash *h = (Hash *) ObjData(ho);
+
+ if (!DohCheck(file)) {
+ fo = NewString(file);
+ Decref(fo);
+ } else
+ fo = file;
+ Incref(fo);
+ Delete(h->file);
+ h->file = fo;
+}
+
+static DOH *Hash_getfile(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ return h->file;
+}
+
+static void Hash_setline(DOH *ho, int line) {
+ Hash *h = (Hash *) ObjData(ho);
+ h->line = line;
+}
+
+static int Hash_getline(DOH *ho) {
+ Hash *h = (Hash *) ObjData(ho);
+ return h->line;
+}
+
+/* -----------------------------------------------------------------------------
+ * type information
+ * ----------------------------------------------------------------------------- */
+
+static DohHashMethods HashHashMethods = {
+ Hash_getattr,
+ Hash_setattr,
+ Hash_delattr,
+ Hash_keys,
+};
+
+DohObjInfo DohHashType = {
+ "Hash", /* objname */
+ DelHash, /* doh_del */
+ CopyHash, /* doh_copy */
+ Hash_clear, /* doh_clear */
+ Hash_str, /* doh_str */
+ 0, /* doh_data */
+ 0, /* doh_dump */
+ Hash_len, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ Hash_firstiter, /* doh_first */
+ Hash_nextiter, /* doh_next */
+ Hash_setfile, /* doh_setfile */
+ Hash_getfile, /* doh_getfile */
+ Hash_setline, /* doh_setline */
+ Hash_getline, /* doh_getline */
+ &HashHashMethods, /* doh_mapping */
+ 0, /* doh_sequence */
+ 0, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_positional */
+ 0,
+};
+
+/* -----------------------------------------------------------------------------
+ * NewHash()
+ *
+ * Create a new hash table.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewHash(void) {
+ Hash *h;
+ int i;
+ h = (Hash *) DohMalloc(sizeof(Hash));
+ h->hashsize = HASH_INIT_SIZE;
+ h->hashtable = (HashNode **) DohMalloc(h->hashsize * sizeof(HashNode *));
+ for (i = 0; i < h->hashsize; i++) {
+ h->hashtable[i] = 0;
+ }
+ h->nitems = 0;
+ h->file = 0;
+ h->line = 0;
+ return DohObjMalloc(&DohHashType, h);
+}
diff --git a/contrib/tools/swig/Source/DOH/list.c b/contrib/tools/swig/Source/DOH/list.c
new file mode 100644
index 00000000000..f2282fe794b
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/list.c
@@ -0,0 +1,372 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * list.c
+ *
+ * Implements a simple list object.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+typedef struct List {
+ int maxitems; /* Max size */
+ int nitems; /* Num items */
+ DOH *file;
+ int line;
+ DOH **items;
+} List;
+
+extern DohObjInfo DohListType;
+
+/* Doubles amount of memory in a list */
+static
+void more(List *l) {
+ l->items = (void **) DohRealloc(l->items, l->maxitems * 2 * sizeof(void *));
+ l->maxitems *= 2;
+}
+
+/* -----------------------------------------------------------------------------
+ * CopyList()
+ *
+ * Make a shallow copy of a list.
+ * ----------------------------------------------------------------------------- */
+static DOH *CopyList(DOH *lo) {
+ List *l, *nl;
+ int i;
+ l = (List *) ObjData(lo);
+ nl = (List *) DohMalloc(sizeof(List));
+ nl->nitems = l->nitems;
+ nl->maxitems = l->maxitems;
+ nl->items = (void **) DohMalloc(l->maxitems * sizeof(void *));
+ for (i = 0; i < l->nitems; i++) {
+ nl->items[i] = l->items[i];
+ Incref(nl->items[i]);
+ }
+ nl->file = l->file;
+ if (nl->file)
+ Incref(nl->file);
+ nl->line = l->line;
+ return DohObjMalloc(&DohListType, nl);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelList()
+ *
+ * Delete a list.
+ * ----------------------------------------------------------------------------- */
+
+static void DelList(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ int i;
+ for (i = 0; i < l->nitems; i++)
+ Delete(l->items[i]);
+ DohFree(l->items);
+ DohFree(l);
+}
+
+/* -----------------------------------------------------------------------------
+ * List_clear()
+ *
+ * Remove all of the list entries, but keep the list object intact.
+ * File and line numbering info left unmodified.
+ * ----------------------------------------------------------------------------- */
+
+static void List_clear(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ int i;
+ for (i = 0; i < l->nitems; i++) {
+ Delete(l->items[i]);
+ }
+ l->nitems = 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_insert()
+ *
+ * Insert an item into the list. If the item is not a DOH object, it is assumed
+ * to be a 'char *' and is used to construct an equivalent string object.
+ * ----------------------------------------------------------------------------- */
+
+static int List_insert(DOH *lo, int pos, DOH *item) {
+ List *l = (List *) ObjData(lo);
+ int i;
+
+ if (!item)
+ return -1;
+ if (!DohCheck(item)) {
+ item = NewString(item);
+ Decref(item);
+ }
+ if (pos == DOH_END)
+ pos = l->nitems;
+ if (pos < 0)
+ pos = 0;
+ if (pos > l->nitems)
+ pos = l->nitems;
+ if (l->nitems == l->maxitems)
+ more(l);
+ for (i = l->nitems; i > pos; i--) {
+ l->items[i] = l->items[i - 1];
+ }
+ l->items[pos] = item;
+ Incref(item);
+ l->nitems++;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_remove()
+ *
+ * Remove an item from a list.
+ * ----------------------------------------------------------------------------- */
+
+static int List_remove(DOH *lo, int pos) {
+ List *l = (List *) ObjData(lo);
+ int i;
+ if (pos == DOH_END)
+ pos = l->nitems - 1;
+ if (pos == DOH_BEGIN)
+ pos = 0;
+ assert(!((pos < 0) || (pos >= l->nitems)));
+ Delete(l->items[pos]);
+ for (i = pos; i < l->nitems - 1; i++) {
+ l->items[i] = l->items[i + 1];
+ }
+ l->nitems--;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_len()
+ *
+ * Return the number of elements in the list
+ * ----------------------------------------------------------------------------- */
+
+static int List_len(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ return l->nitems;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_get()
+ *
+ * Get the nth item from the list.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *List_get(DOH *lo, int n) {
+ List *l = (List *) ObjData(lo);
+ if (n == DOH_END)
+ n = l->nitems - 1;
+ if (n == DOH_BEGIN)
+ n = 0;
+ assert(!((n < 0) || (n >= l->nitems)));
+ return l->items[n];
+}
+
+/* -----------------------------------------------------------------------------
+ * List_set()
+ *
+ * Set the nth item in the list replacing any previous item.
+ * ----------------------------------------------------------------------------- */
+
+static int List_set(DOH *lo, int n, DOH *val) {
+ List *l = (List *) ObjData(lo);
+ if (!val)
+ return -1;
+ assert(!((n < 0) || (n >= l->nitems)));
+ if (!DohCheck(val)) {
+ val = NewString(val);
+ Decref(val);
+ }
+ Delete(l->items[n]);
+ l->items[n] = val;
+ Incref(val);
+ Delete(val);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_first()
+ *
+ * Return the first item in the list.
+ * ----------------------------------------------------------------------------- */
+
+static DohIterator List_first(DOH *lo) {
+ DohIterator iter;
+ List *l = (List *) ObjData(lo);
+ iter.object = lo;
+ iter._index = 0;
+ iter._current = 0;
+ iter.key = 0;
+ if (l->nitems > 0) {
+ iter.item = l->items[0];
+ } else {
+ iter.item = 0;
+ }
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_next()
+ *
+ * Return the next item in the list.
+ * ----------------------------------------------------------------------------- */
+
+static DohIterator List_next(DohIterator iter) {
+ List *l = (List *) ObjData(iter.object);
+ iter._index = iter._index + 1;
+ if (iter._index >= l->nitems) {
+ iter.item = 0;
+ iter.key = 0;
+ } else {
+ iter.item = l->items[iter._index];
+ }
+ return iter;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_str()
+ *
+ * Create a string representation of the list.
+ * ----------------------------------------------------------------------------- */
+static DOH *List_str(DOH *lo) {
+ DOH *s;
+ int i;
+ List *l = (List *) ObjData(lo);
+ s = NewStringEmpty();
+ if (ObjGetMark(lo)) {
+ Printf(s, "List(%p)", lo);
+ return s;
+ }
+ ObjSetMark(lo, 1);
+ Printf(s, "List[ ");
+ for (i = 0; i < l->nitems; i++) {
+ Printf(s, "%s", l->items[i]);
+ if ((i + 1) < l->nitems)
+ Printf(s, ", ");
+ }
+ Printf(s, " ]");
+ ObjSetMark(lo, 0);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * List_dump()
+ *
+ * Dump the items to an output stream.
+ * ----------------------------------------------------------------------------- */
+
+static int List_dump(DOH *lo, DOH *out) {
+ int nsent = 0;
+ int i, ret;
+ List *l = (List *) ObjData(lo);
+ for (i = 0; i < l->nitems; i++) {
+ ret = Dump(l->items[i], out);
+ if (ret < 0)
+ return -1;
+ nsent += ret;
+ }
+ return nsent;
+}
+
+static void List_setfile(DOH *lo, DOH *file) {
+ DOH *fo;
+ List *l = (List *) ObjData(lo);
+
+ if (!DohCheck(file)) {
+ fo = NewString(file);
+ Decref(fo);
+ } else
+ fo = file;
+ Incref(fo);
+ Delete(l->file);
+ l->file = fo;
+}
+
+static DOH *List_getfile(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ return l->file;
+}
+
+static void List_setline(DOH *lo, int line) {
+ List *l = (List *) ObjData(lo);
+ l->line = line;
+}
+
+static int List_getline(DOH *lo) {
+ List *l = (List *) ObjData(lo);
+ return l->line;
+}
+
+static DohListMethods ListListMethods = {
+ List_get,
+ List_set,
+ List_remove,
+ List_insert,
+ 0, /* delslice */
+};
+
+DohObjInfo DohListType = {
+ "List", /* objname */
+ DelList, /* doh_del */
+ CopyList, /* doh_copy */
+ List_clear, /* doh_clear */
+ List_str, /* doh_str */
+ 0, /* doh_data */
+ List_dump, /* doh_dump */
+ List_len, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ List_first, /* doh_first */
+ List_next, /* doh_next */
+ List_setfile, /* doh_setfile */
+ List_getfile, /* doh_getfile */
+ List_setline, /* doh_setline */
+ List_getline, /* doh_getline */
+ 0, /* doh_mapping */
+ &ListListMethods, /* doh_sequence */
+ 0, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_callable */
+ 0, /* doh_position */
+};
+
+/* -----------------------------------------------------------------------------
+ * NewList()
+ *
+ * Create a new list.
+ * ----------------------------------------------------------------------------- */
+
+#define MAXLISTITEMS 8
+
+DOH *DohNewList(void) {
+ List *l = (List *) DohMalloc(sizeof(List));
+ l->nitems = 0;
+ l->maxitems = MAXLISTITEMS;
+ l->items = (void **) DohCalloc(l->maxitems, sizeof(void *));
+ l->file = 0;
+ l->line = 0;
+ return DohObjMalloc(&DohListType, l);
+}
+
+static int (*List_sort_compare_func) (const DOH *, const DOH *);
+static int List_qsort_compare(const void *a, const void *b) {
+ return List_sort_compare_func(*((DOH **) a), *((DOH **) b));
+}
+
+/* Sort a list */
+void DohSortList(DOH *lo, int (*cmp) (const DOH *, const DOH *)) {
+ List *l = (List *) ObjData(lo);
+ if (cmp) {
+ List_sort_compare_func = cmp;
+ } else {
+ List_sort_compare_func = DohCmp;
+ }
+ qsort(l->items, l->nitems, sizeof(DOH *), List_qsort_compare);
+}
diff --git a/contrib/tools/swig/Source/DOH/memory.c b/contrib/tools/swig/Source/DOH/memory.c
new file mode 100644
index 00000000000..e217f4285e2
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/memory.c
@@ -0,0 +1,284 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * memory.c
+ *
+ * This file implements all of DOH's memory management including allocation
+ * of objects and checking of objects.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef DOH_POOL_SIZE
+#define DOH_POOL_SIZE 4194304
+#endif
+
+/* Checks stale DOH object use - will use a lot more memory as pool memory is not re-used. */
+/*
+#define DOH_DEBUG_MEMORY_POOLS
+*/
+
+static int PoolSize = DOH_POOL_SIZE;
+
+DOH *DohNone = 0; /* The DOH None object */
+
+typedef struct pool {
+ DohBase *ptr; /* Start of pool */
+ int len; /* Length of pool */
+ int blen; /* Byte length of pool */
+ int current; /* Current position for next allocation */
+ char *pbeg; /* Beg of pool */
+ char *pend; /* End of pool */
+ struct pool *next; /* Next pool */
+} Pool;
+
+static DohBase *FreeList = 0; /* List of free objects */
+static Pool *Pools = 0;
+static int pools_initialized = 0;
+
+/* ----------------------------------------------------------------------
+ * CreatePool() - Create a new memory pool
+ * ---------------------------------------------------------------------- */
+
+static void CreatePool(void) {
+ Pool *p = 0;
+ p = (Pool *) DohMalloc(sizeof(Pool));
+ p->ptr = (DohBase *) DohCalloc(PoolSize, sizeof(DohBase));
+ p->len = PoolSize;
+ p->blen = PoolSize * sizeof(DohBase);
+ p->current = 0;
+ p->pbeg = ((char *) p->ptr);
+ p->pend = p->pbeg + p->blen;
+ p->next = Pools;
+ Pools = p;
+}
+
+/* ----------------------------------------------------------------------
+ * InitPools() - Initialize the memory allocator
+ * ---------------------------------------------------------------------- */
+
+static void InitPools(void) {
+ if (pools_initialized)
+ return;
+ CreatePool(); /* Create initial pool */
+ pools_initialized = 1;
+ DohNone = NewVoid(0, 0); /* Create the None object */
+ DohIntern(DohNone);
+}
+
+/* ----------------------------------------------------------------------
+ * DohCheck()
+ *
+ * Returns 1 if an arbitrary pointer is a DOH object.
+ * ---------------------------------------------------------------------- */
+
+int DohCheck(const DOH *ptr) {
+ Pool *p = Pools;
+ char *cptr = (char *) ptr;
+ while (p) {
+ if ((cptr >= p->pbeg) && (cptr < p->pend)) {
+#ifdef DOH_DEBUG_MEMORY_POOLS
+ DohBase *b = (DohBase *) ptr;
+ int DOH_object_already_deleted = b->type == 0;
+ assert(!DOH_object_already_deleted);
+#endif
+ return 1;
+ }
+ /*
+ pptr = (char *) p->ptr;
+ if ((cptr >= pptr) && (cptr < (pptr+(p->current*sizeof(DohBase))))) return 1; */
+ p = p->next;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohIntern()
+ * ----------------------------------------------------------------------------- */
+
+void DohIntern(DOH *obj) {
+ DohBase *b = (DohBase *) obj;
+ b->flag_intern = 1;
+}
+
+/* ----------------------------------------------------------------------
+ * DohObjMalloc()
+ *
+ * Allocate memory for a new object.
+ * ---------------------------------------------------------------------- */
+
+DOH *DohObjMalloc(DohObjInfo *type, void *data) {
+ DohBase *obj;
+ if (!pools_initialized)
+ InitPools();
+#ifndef DOH_DEBUG_MEMORY_POOLS
+ if (FreeList) {
+ obj = FreeList;
+ FreeList = (DohBase *) obj->data;
+ } else {
+#endif
+ while (Pools->current == Pools->len) {
+ CreatePool();
+ }
+ obj = Pools->ptr + Pools->current;
+ ++Pools->current;
+#ifndef DOH_DEBUG_MEMORY_POOLS
+ }
+#endif
+ obj->type = type;
+ obj->data = data;
+ obj->meta = 0;
+ obj->refcount = 1;
+ obj->flag_intern = 0;
+ obj->flag_marked = 0;
+ obj->flag_user = 0;
+ obj->flag_usermark = 0;
+ return (DOH *) obj;
+}
+
+/* ----------------------------------------------------------------------
+ * DohObjFree() - Free a DOH object
+ * ---------------------------------------------------------------------- */
+
+void DohObjFree(DOH *ptr) {
+ DohBase *b, *meta;
+ b = (DohBase *) ptr;
+ if (b->flag_intern)
+ return;
+ meta = (DohBase *) b->meta;
+ b->data = (void *) FreeList;
+ b->meta = 0;
+ b->type = 0;
+ b->refcount = 0;
+ FreeList = b;
+ if (meta) {
+ Delete(meta);
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * DohMemoryDebug()
+ *
+ * Display memory usage statistics
+ * ---------------------------------------------------------------------- */
+
+void DohMemoryDebug(void) {
+ extern DohObjInfo DohStringType;
+ extern DohObjInfo DohListType;
+ extern DohObjInfo DohHashType;
+
+ Pool *p;
+ int totsize = 0;
+ int totused = 0;
+ int totfree = 0;
+
+ int numstring = 0;
+ int numlist = 0;
+ int numhash = 0;
+
+ printf("Memory statistics:\n\n");
+ printf("Pools:\n");
+
+ p = Pools;
+ while (p) {
+ /* Calculate number of used, free items */
+ int i;
+ int nused = 0, nfree = 0;
+ for (i = 0; i < p->len; i++) {
+ if (p->ptr[i].refcount <= 0)
+ nfree++;
+ else {
+ nused++;
+ if (p->ptr[i].type == &DohStringType)
+ numstring++;
+ else if (p->ptr[i].type == &DohListType)
+ numlist++;
+ else if (p->ptr[i].type == &DohHashType)
+ numhash++;
+ }
+ }
+ printf(" Pool %8p: size = %10d. used = %10d. free = %10d\n", (void *) p, p->len, nused, nfree);
+ totsize += p->len;
+ totused += nused;
+ totfree += nfree;
+ p = p->next;
+ }
+ printf("\n Total: size = %10d, used = %10d, free = %10d\n", totsize, totused, totfree);
+
+ printf("\nObject types\n");
+ printf(" Strings : %d\n", numstring);
+ printf(" Lists : %d\n", numlist);
+ printf(" Hashes : %d\n", numhash);
+
+#if 0
+ p = Pools;
+ while (p) {
+ int i;
+ for (i = 0; i < p->len; i++) {
+ if (p->ptr[i].refcount > 0) {
+ if (p->ptr[i].type == &DohStringType) {
+ Printf(stdout, "%s\n", p->ptr + i);
+ }
+ }
+ }
+ p = p->next;
+ }
+#endif
+
+}
+
+/* Function to call instead of exit(). */
+static void (*doh_exit_handler)(int) = NULL;
+
+void DohSetExitHandler(void (*new_handler)(int)) {
+ doh_exit_handler = new_handler;
+}
+
+void DohExit(int status) {
+ if (doh_exit_handler) {
+ void (*handler)(int) = doh_exit_handler;
+ /* Unset the handler to avoid infinite loops if it tries to do something
+ * which calls DohExit() (e.g. calling Malloc() and that failing).
+ */
+ doh_exit_handler = NULL;
+ handler(status);
+ }
+ doh_internal_exit(status);
+}
+
+static void allocation_failed(size_t n, size_t size) {
+ /* Report and exit as directly as possible to try to avoid further issues due
+ * to lack of memory. */
+ if (n == 1) {
+ fprintf(stderr, "Failed to allocate %llu bytes\n", (unsigned long long)size);
+ } else {
+ fprintf(stderr, "Failed to allocate %llu*%llu bytes\n", (unsigned long long)n, (unsigned long long)size);
+ }
+ DohExit(EXIT_FAILURE);
+}
+
+void *DohMalloc(size_t size) {
+ void *p = doh_internal_malloc(size);
+ if (!p) allocation_failed(1, size);
+ return p;
+}
+
+void *DohRealloc(void *ptr, size_t size) {
+ void *p = doh_internal_realloc(ptr, size);
+ if (!p) allocation_failed(1, size);
+ return p;
+}
+
+void *DohCalloc(size_t n, size_t size) {
+ void *p = doh_internal_calloc(n, size);
+ if (!p) allocation_failed(n, size);
+ return p;
+}
diff --git a/contrib/tools/swig/Source/DOH/string.c b/contrib/tools/swig/Source/DOH/string.c
new file mode 100644
index 00000000000..7ac9b9231a3
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/string.c
@@ -0,0 +1,1287 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * string.c
+ *
+ * Implements a string object that supports both sequence operations and
+ * file semantics.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+extern DohObjInfo DohStringType;
+
+typedef struct String {
+ DOH *file;
+ int line;
+ int maxsize; /* Max size allocated */
+ int len; /* Current length */
+ int hashkey; /* Hash key value */
+ int sp; /* Current position */
+ char *str; /* String data */
+} String;
+
+/* -----------------------------------------------------------------------------
+ * String_data() - Return as a 'void *'
+ * ----------------------------------------------------------------------------- */
+
+static void *String_data(DOH *so) {
+ String *s = (String *) ObjData(so);
+ s->str[s->len] = 0;
+ return (void *) s->str;
+}
+
+/* static char *String_char(DOH *so) {
+ return (char *) String_data(so);
+}
+*/
+
+/* -----------------------------------------------------------------------------
+ * String_dump() - Serialize a string onto out
+ * ----------------------------------------------------------------------------- */
+
+static int String_dump(DOH *so, DOH *out) {
+ int nsent;
+ int ret;
+ String *s = (String *) ObjData(so);
+ nsent = 0;
+ while (nsent < s->len) {
+ ret = Write(out, s->str + nsent, (s->len - nsent));
+ if (ret < 0)
+ return ret;
+ nsent += ret;
+ }
+ return nsent;
+}
+
+/* -----------------------------------------------------------------------------
+ * CopyString() - Copy a string
+ * ----------------------------------------------------------------------------- */
+
+static DOH *CopyString(DOH *so) {
+ String *str;
+ String *s = (String *) ObjData(so);
+ str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = s->hashkey;
+ str->sp = s->sp;
+ str->line = s->line;
+ str->file = s->file;
+ if (str->file)
+ Incref(str->file);
+ str->str = (char *) DohMalloc(s->len + 1);
+ memcpy(str->str, s->str, s->len);
+ str->maxsize = s->len;
+ str->len = s->len;
+ str->str[str->len] = 0;
+
+ return DohObjMalloc(&DohStringType, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * DelString() - Delete a string
+ * ----------------------------------------------------------------------------- */
+
+static void DelString(DOH *so) {
+ String *s = (String *) ObjData(so);
+ DohFree(s->str);
+ DohFree(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * DohString_len() - Length of a string
+ * ----------------------------------------------------------------------------- */
+
+static int String_len(DOH *so) {
+ String *s = (String *) ObjData(so);
+ return s->len;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * String_cmp() - Compare two strings
+ * ----------------------------------------------------------------------------- */
+
+static int String_cmp(DOH *so1, DOH *so2) {
+ String *s1, *s2;
+ char *c1, *c2;
+ int maxlen, i;
+ s1 = (String *) ObjData(so1);
+ s2 = (String *) ObjData(so2);
+ maxlen = s1->len;
+ if (s2->len < maxlen)
+ maxlen = s2->len;
+ c1 = s1->str;
+ c2 = s2->str;
+ for (i = maxlen; i; --i, c1++, c2++) {
+ if (*c1 != *c2)
+ break;
+ }
+ if (i != 0) {
+ if (*c1 < *c2)
+ return -1;
+ else
+ return 1;
+ }
+ if (s1->len == s2->len)
+ return 0;
+ if (s1->len > s2->len)
+ return 1;
+ return -1;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_equal() - Say if two string are equal
+ * ----------------------------------------------------------------------------- */
+
+static int String_equal(DOH *so1, DOH *so2) {
+ String *s1 = (String *) ObjData(so1);
+ String *s2 = (String *) ObjData(so2);
+ int len = s1->len;
+ if (len != s2->len) {
+ return 0;
+ } else {
+ char *c1 = s1->str;
+ char *c2 = s2->str;
+#if 0
+ int mlen = len >> 2;
+ int i = mlen;
+ for (; i; --i) {
+ if (*(c1++) != *(c2++))
+ return 0;
+ if (*(c1++) != *(c2++))
+ return 0;
+ if (*(c1++) != *(c2++))
+ return 0;
+ if (*(c1++) != *(c2++))
+ return 0;
+ }
+ for (i = len - (mlen << 2); i; --i) {
+ if (*(c1++) != *(c2++))
+ return 0;
+ }
+ return 1;
+#else
+ return memcmp(c1, c2, len) == 0;
+#endif
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * String_hash() - Compute string hash value
+ * ----------------------------------------------------------------------------- */
+
+static int String_hash(DOH *so) {
+ String *s = (String *) ObjData(so);
+ if (s->hashkey >= 0) {
+ return s->hashkey;
+ } else {
+ /* We use the djb2 hash function: https://theartincode.stanis.me/008-djb2/
+ *
+ * One difference is we use initial seed 0. It seems the usual seed value
+ * is intended to help spread out hash values, which is beneficial if
+ * linear probing is used but DOH Hash uses a chain of buckets instead, and
+ * grouped hash values are probably more cache friendly. In tests using
+ * 0 seems slightly faster anyway.
+ */
+ const char *c = s->str;
+ unsigned int len = s->len > 50 ? 50 : s->len;
+ unsigned int h = 0;
+ unsigned int mlen = len >> 2;
+ unsigned int i = mlen;
+ for (; i; --i) {
+ h = h + (h << 5) + *(c++);
+ h = h + (h << 5) + *(c++);
+ h = h + (h << 5) + *(c++);
+ h = h + (h << 5) + *(c++);
+ }
+ for (i = len - (mlen << 2); i; --i) {
+ h = h + (h << 5) + *(c++);
+ }
+ h &= 0x7fffffff;
+ s->hashkey = (int)h;
+ return h;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * DohString_append() - Append to s
+ * ----------------------------------------------------------------------------- */
+
+static void DohString_append(DOH *so, const DOHString_or_char *str) {
+ int oldlen, newlen, newmaxsize, l, sp;
+ char *tc;
+ String *s = (String *) ObjData(so);
+ char *newstr = 0;
+
+ if (DohCheck(str)) {
+ String *ss = (String *) ObjData(str);
+ newstr = (char *) String_data((DOH *) str);
+ l = ss->len;
+ } else {
+ newstr = (char *) (str);
+ l = (int) strlen(newstr);
+ }
+ if (!newstr)
+ return;
+ s->hashkey = -1;
+
+ oldlen = s->len;
+ newlen = oldlen + l + 1;
+ if (newlen >= s->maxsize - 1) {
+ newmaxsize = 2 * s->maxsize;
+ if (newlen >= newmaxsize - 1)
+ newmaxsize = newlen + 1;
+ s->str = (char *) DohRealloc(s->str, newmaxsize);
+ s->maxsize = newmaxsize;
+ }
+ tc = s->str;
+ memcpy(tc + oldlen, newstr, l + 1);
+ sp = s->sp;
+ if (sp >= oldlen) {
+ int i = oldlen + l - sp;
+ tc += sp;
+ for (; i; --i) {
+ if (*(tc++) == '\n')
+ s->line++;
+ }
+ s->sp = oldlen + l;
+ }
+ s->len += l;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * String_clear() - Clear string contents
+ *
+ * File and line numbering info left unmodified.
+ * ----------------------------------------------------------------------------- */
+
+static void String_clear(DOH *so) {
+ String *s = (String *) ObjData(so);
+ s->hashkey = -1;
+ s->len = 0;
+ *(s->str) = 0;
+ s->sp = 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_insert() - Insert a string
+ * ----------------------------------------------------------------------------- */
+
+static int String_insert(DOH *so, int pos, DOH *str) {
+ String *s;
+ int len;
+ char *data;
+
+ if (pos == DOH_END) {
+ DohString_append(so, str);
+ return 0;
+ }
+
+
+ s = (String *) ObjData(so);
+ s->hashkey = -1;
+ if (DohCheck(str)) {
+ String *ss = (String *) ObjData(str);
+ data = (char *) String_data(str);
+ len = ss->len;
+ } else {
+ data = (char *) (str);
+ len = (int) strlen(data);
+ }
+
+ if (pos < 0)
+ pos = 0;
+ else if (pos > s->len)
+ pos = s->len;
+
+ /* See if there is room to insert the new data */
+ while (s->maxsize <= s->len + len) {
+ int newsize = 2 * s->maxsize;
+ s->str = (char *) DohRealloc(s->str, newsize);
+ s->maxsize = newsize;
+ }
+ memmove(s->str + pos + len, s->str + pos, (s->len - pos));
+ memcpy(s->str + pos, data, len);
+ if (s->sp >= pos) {
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (data[i] == '\n')
+ s->line++;
+ }
+ s->sp += len;
+ }
+ s->len += len;
+ s->str[s->len] = 0;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_delitem() - Delete a character
+ * ----------------------------------------------------------------------------- */
+
+static int String_delitem(DOH *so, int pos) {
+ String *s = (String *) ObjData(so);
+ s->hashkey = -1;
+ if (pos == DOH_END)
+ pos = s->len - 1;
+ if (pos == DOH_BEGIN)
+ pos = 0;
+ if (s->len == 0)
+ return 0;
+
+ if (s->sp > pos) {
+ s->sp--;
+ assert(s->sp >= 0);
+ if (s->str[pos] == '\n')
+ s->line--;
+ }
+ memmove(s->str + pos, s->str + pos + 1, ((s->len - 1) - pos));
+ s->len--;
+ s->str[s->len] = 0;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_delslice() - Delete a range
+ * ----------------------------------------------------------------------------- */
+
+static int String_delslice(DOH *so, int sindex, int eindex) {
+ String *s = (String *) ObjData(so);
+ int size;
+ if (s->len == 0)
+ return 0;
+ s->hashkey = -1;
+ if (eindex == DOH_END)
+ eindex = s->len;
+ if (sindex == DOH_BEGIN)
+ sindex = 0;
+
+ size = eindex - sindex;
+ if (s->sp > sindex) {
+ /* Adjust the file pointer and line count */
+ int i, end;
+ if (s->sp > eindex) {
+ end = eindex;
+ s->sp -= size;
+ } else {
+ end = s->sp;
+ s->sp = sindex;
+ }
+ for (i = sindex; i < end; i++) {
+ if (s->str[i] == '\n')
+ s->line--;
+ }
+ assert(s->sp >= 0);
+ }
+ memmove(s->str + sindex, s->str + eindex, s->len - eindex);
+ s->len -= size;
+ s->str[s->len] = 0;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_str() - Returns a string (used by printing commands)
+ * ----------------------------------------------------------------------------- */
+
+static DOH *String_str(DOH *so) {
+ String *s = (String *) ObjData(so);
+ s->str[s->len] = 0;
+ return NewString(s->str);
+}
+
+/* -----------------------------------------------------------------------------
+ * String_read() - Read data from a string
+ * ----------------------------------------------------------------------------- */
+
+static int String_read(DOH *so, void *buffer, int len) {
+ int reallen, retlen;
+ char *cb;
+ String *s = (String *) ObjData(so);
+ if ((s->sp + len) > s->len)
+ reallen = (s->len - s->sp);
+ else
+ reallen = len;
+
+ cb = (char *) buffer;
+ retlen = reallen;
+
+ if (reallen > 0) {
+ memmove(cb, s->str + s->sp, reallen);
+ s->sp += reallen;
+ }
+ return retlen;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_write() - Write data to a string
+ * ----------------------------------------------------------------------------- */
+static int String_write(DOH *so, const void *buffer, int len) {
+ int newlen;
+ String *s = (String *) ObjData(so);
+ s->hashkey = -1;
+ if (s->sp > s->len)
+ s->sp = s->len;
+ newlen = s->sp + len + 1;
+ if (newlen > s->maxsize) {
+ s->str = (char *) DohRealloc(s->str, newlen);
+ s->maxsize = newlen;
+ s->len = s->sp + len;
+ }
+ if ((s->sp + len) > s->len)
+ s->len = s->sp + len;
+ memmove(s->str + s->sp, buffer, len);
+ s->sp += len;
+ s->str[s->len] = 0;
+ return len;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_seek() - Seek to a new position
+ * ----------------------------------------------------------------------------- */
+
+static int String_seek(DOH *so, long offset, int whence) {
+ int pos, nsp, inc;
+ String *s = (String *) ObjData(so);
+ if (whence == SEEK_SET)
+ pos = 0;
+ else if (whence == SEEK_CUR)
+ pos = s->sp;
+ else if (whence == SEEK_END) {
+ pos = s->len;
+ offset = -offset;
+ } else
+ pos = s->sp;
+
+ nsp = pos + offset;
+ if (nsp < 0)
+ nsp = 0;
+ if (s->len > 0 && nsp > s->len)
+ nsp = s->len;
+
+ inc = (nsp > s->sp) ? 1 : -1;
+
+ {
+#if 0
+ int sp = s->sp;
+ char *tc = s->str;
+ int len = s->len;
+ while (sp != nsp) {
+ int prev = sp + inc;
+ if (prev >= 0 && prev <= len && tc[prev] == '\n')
+ s->line += inc;
+ sp += inc;
+ }
+#else
+ int sp = s->sp;
+ char *tc = s->str;
+ if (inc > 0) {
+ while (sp != nsp) {
+ if (tc[++sp] == '\n')
+ ++s->line;
+ }
+ } else {
+ while (sp != nsp) {
+ if (tc[--sp] == '\n')
+ --s->line;
+ }
+ }
+#endif
+ s->sp = sp;
+ }
+ assert(s->sp >= 0);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_tell() - Return current position
+ * ----------------------------------------------------------------------------- */
+
+static long String_tell(DOH *so) {
+ String *s = (String *) ObjData(so);
+ return (long) (s->sp);
+}
+
+/* -----------------------------------------------------------------------------
+ * String_putc()
+ * ----------------------------------------------------------------------------- */
+
+static int String_putc(DOH *so, int ch) {
+ String *s = (String *) ObjData(so);
+ int len = s->len;
+ int sp = s->sp;
+ s->hashkey = -1;
+ if (sp >= len) {
+ int maxsize = s->maxsize;
+ char *tc = s->str;
+ if (len > (maxsize - 2)) {
+ maxsize *= 2;
+ tc = (char *) DohRealloc(tc, maxsize);
+ s->maxsize = (int) maxsize;
+ s->str = tc;
+ }
+ tc += sp;
+ *tc = (char) ch;
+ *(++tc) = 0;
+ s->len = s->sp = sp + 1;
+ } else {
+ s->str[s->sp++] = (char) ch;
+ }
+ if (ch == '\n')
+ s->line++;
+ return ch;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_getc()
+ * ----------------------------------------------------------------------------- */
+
+static int String_getc(DOH *so) {
+ int c;
+ String *s = (String *) ObjData(so);
+ if (s->sp >= s->len)
+ c = EOF;
+ else
+ c = (int)(unsigned char) s->str[s->sp++];
+ if (c == '\n')
+ s->line++;
+ return c;
+}
+
+/* -----------------------------------------------------------------------------
+ * String_ungetc()
+ * ----------------------------------------------------------------------------- */
+
+static int String_ungetc(DOH *so, int ch) {
+ String *s = (String *) ObjData(so);
+ if (ch == EOF)
+ return ch;
+ if (s->sp <= 0)
+ return EOF;
+ s->sp--;
+ if (ch == '\n')
+ s->line--;
+ return ch;
+}
+
+static char *end_quote(char *s) {
+ char *qs;
+ char qc;
+ char *q;
+ char *nl;
+ qc = *s;
+ qs = s;
+ while (1) {
+ q = strpbrk(s + 1, "\"\'");
+ nl = strchr(s + 1, '\n');
+ if (nl && (nl < q)) {
+ /* A new line appears before the end of the string */
+ if (*(nl - 1) == '\\') {
+ s = nl + 1;
+ continue;
+ }
+ /* String was terminated by a newline. Wing it */
+ return qs;
+ }
+ if (!q && nl) {
+ return qs;
+ }
+ if (!q)
+ return 0;
+ if ((*q == qc) && (*(q - 1) != '\\'))
+ return q;
+ s = q;
+ }
+}
+
+static char *end_comment(char *s) {
+ char *substring = strstr(s, "*/");
+ if (substring)
+ ++substring;
+ return substring;
+}
+
+static char *match_simple(char *base, char *s, char *token, int tokenlen) {
+ (void) base;
+ (void) tokenlen;
+ return strstr(s, token);
+}
+
+static char *match_identifier(char *base, char *s, char *token, int tokenlen) {
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
+ /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */
+ ++s;
+ continue;
+ }
+ if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
+ /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */
+ ++s;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+
+static char *match_identifier_begin(char *base, char *s, char *token, int tokenlen) {
+ (void)tokenlen;
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if ((s > base) && (isalnum((int) *(s - 1)) || (*(s - 1) == '_'))) {
+ /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */
+ ++s;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+static char *match_identifier_end(char *base, char *s, char *token, int tokenlen) {
+ (void) base;
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if (isalnum((int) *(s + tokenlen)) || (*(s + tokenlen) == '_')) {
+ /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */
+ ++s;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+static char *match_number_end(char *base, char *s, char *token, int tokenlen) {
+ (void) base;
+ while (s) {
+ s = strstr(s, token);
+ if (!s)
+ return 0;
+ if (isdigit((int) *(s + tokenlen))) {
+ /* We could advance by tokenlen if strstr(s, token) matches can't overlap. */
+ ++s;
+ continue;
+ }
+ return s;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * replace_simple()
+ *
+ * Replaces count non-overlapping occurrences of token with rep in a string.
+ * ----------------------------------------------------------------------------- */
+
+static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) {
+ int tokenlen; /* Length of the token */
+ int replen; /* Length of the replacement */
+ int delta, expand = 0;
+ int ic;
+ int rcount = 0;
+ int noquote = 0;
+ int nocomment = 0;
+ char *c, *s, *t, *first;
+ char *q, *q2;
+ char *base;
+ int i;
+
+ /* Figure out if anything gets replaced */
+ if (!strlen(token))
+ return 0;
+
+ base = str->str;
+ tokenlen = (int)strlen(token);
+ s = (*match) (base, base, token, tokenlen);
+
+ if (!s)
+ return 0; /* No matches. Who cares */
+
+ str->hashkey = -1;
+
+ if (flags & DOH_REPLACE_NOQUOTE)
+ noquote = 1;
+
+ if (flags & DOH_REPLACE_NOCOMMENT)
+ nocomment = 1;
+
+ assert(!(noquote && nocomment)); /* quote and comment combination not implemented */
+
+ /* If we are not replacing inside quotes, we need to do a little extra work */
+ if (noquote) {
+ q = strpbrk(base, "\"\'");
+ if (!q) {
+ noquote = 0; /* Well, no quotes to worry about. Oh well */
+ } else {
+ while (q && (q < s)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ return 0;
+ }
+ if (q2 > s) {
+ /* Find next match */
+ s = (*match) (base, q2 + 1, token, tokenlen);
+ }
+ if (!s)
+ return 0; /* Oh well, no matches */
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0; /* No more quotes */
+ }
+ }
+ }
+
+ /* If we are not replacing inside comments, we need to do a little extra work */
+ if (nocomment) {
+ q = strstr(base, "/*");
+ if (!q) {
+ nocomment = 0; /* Well, no comments to worry about. Oh well */
+ } else {
+ while (q && (q < s)) {
+ /* First match was found inside a comment. Try to find another match */
+ q2 = end_comment(q);
+ if (!q2) {
+ return 0;
+ }
+ if (q2 > s) {
+ /* Find next match */
+ s = (*match) (base, q2 + 1, token, tokenlen);
+ }
+ if (!s)
+ return 0; /* Oh well, no matches */
+ q = strstr(q2 + 1, "/*");
+ if (!q)
+ nocomment = 0; /* No more comments */
+ }
+ }
+ }
+
+ first = s;
+ replen = (int)strlen(rep);
+
+ delta = (replen - tokenlen);
+
+ if (delta <= 0) {
+ /* String is either shrinking or staying the same size */
+ /* In this case, we do the replacement in place without memory reallocation */
+ ic = count;
+ t = s; /* Target of memory copies */
+ while (ic && s) {
+ if (replen) {
+ memcpy(t, rep, replen);
+ t += replen;
+ }
+ rcount++;
+ expand += delta;
+ /* Find the next location */
+ s += tokenlen;
+ if (ic == 1)
+ break;
+ c = (*match) (base, s, token, tokenlen);
+
+ if (noquote) {
+ q = strpbrk(s, "\"\'");
+ if (!q) {
+ noquote = 0;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c)
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0; /* No more quotes */
+ }
+ }
+ }
+ if (nocomment) {
+ q = strstr(s, "/*");
+ if (!q) {
+ nocomment = 0;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a comment. Try to find another match */
+ q2 = end_comment(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c)
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ q = strstr(q2 + 1, "/*");
+ if (!q)
+ nocomment = 0; /* No more comments */
+ }
+ }
+ }
+ if (delta) {
+ if (c) {
+ memmove(t, s, c - s);
+ t += (c - s);
+ } else {
+ memmove(t, s, (str->str + str->len) - s + 1);
+ }
+ } else {
+ if (c) {
+ t += (c - s);
+ }
+ }
+ s = c;
+ ic--;
+ }
+ if (s && delta) {
+ memmove(t, s, (str->str + str->len) - s + 1);
+ }
+ str->len += expand;
+ str->str[str->len] = 0;
+ if (str->sp >= str->len)
+ str->sp += expand; /* Fix the end of file pointer */
+ return rcount;
+ }
+ /* The string is expanding as a result of the replacement */
+ /* Figure out how much expansion is going to occur and allocate a new string */
+ {
+ char *ns;
+ int newsize;
+
+ rcount++;
+ ic = count - 1;
+ s += tokenlen;
+ while (ic && (c = (*match) (base, s, token, tokenlen))) {
+ if (noquote) {
+ q = strpbrk(s, "\"\'");
+ if (!q) {
+ break;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c) {
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ }
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0;
+ }
+ }
+ }
+ if (nocomment) {
+ q = strstr(s, "/*");
+ if (!q) {
+ break;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a comment. Try to find another match */
+ q2 = end_comment(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c) {
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ }
+ q = strstr(q2 + 1, "/*");
+ if (!q)
+ nocomment = 0;
+ }
+ }
+ }
+ if (c) {
+ rcount++;
+ ic--;
+ s = c + tokenlen;
+ } else {
+ break;
+ }
+ }
+
+ expand = delta * rcount; /* Total amount of expansion for the replacement */
+ newsize = str->maxsize;
+ while ((str->len + expand) >= newsize)
+ newsize *= 2;
+
+ ns = (char *) DohMalloc(newsize);
+ t = ns;
+ s = first;
+
+ /* Copy the first part of the string */
+ if (first > str->str) {
+ memcpy(t, str->str, (first - str->str));
+ t += (first - str->str);
+ }
+ for (i = 0; i < rcount; i++) {
+ memcpy(t, rep, replen);
+ t += replen;
+ s += tokenlen;
+ c = (*match) (base, s, token, tokenlen);
+ if (noquote) {
+ q = strpbrk(s, "\"\'");
+ if (!q) {
+ noquote = 0;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a quote. Try to find another match */
+ q2 = end_quote(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c) {
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ }
+ q = strpbrk(q2 + 1, "\"\'");
+ if (!q)
+ noquote = 0; /* No more quotes */
+ }
+ }
+ }
+ if (nocomment) {
+ q = strstr(s, "/*");
+ if (!q) {
+ nocomment = 0;
+ } else {
+ while (q && (q < c)) {
+ /* First match was found inside a comment. Try to find another match */
+ q2 = end_comment(q);
+ if (!q2) {
+ c = 0;
+ break;
+ }
+ if (q2 > c) {
+ c = (*match) (base, q2 + 1, token, tokenlen);
+ if (!c)
+ break;
+ }
+ q = strstr(q2 + 1, "/*");
+ if (!q)
+ nocomment = 0; /* No more comments */
+ }
+ }
+ }
+ if (i < (rcount - 1)) {
+ memcpy(t, s, c - s);
+ t += (c - s);
+ } else {
+ memcpy(t, s, (str->str + str->len) - s + 1);
+ }
+ s = c;
+ }
+ c = str->str;
+ str->str = ns;
+ if (str->sp >= str->len)
+ str->sp += expand;
+ str->len += expand;
+ str->str[str->len] = 0;
+ str->maxsize = newsize;
+ DohFree(c);
+ return rcount;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * String_replace()
+ * ----------------------------------------------------------------------------- */
+
+static int String_replace(DOH *stro, const DOHString_or_char *token, const DOHString_or_char *rep, int flags) {
+ int count = -1;
+ String *str = (String *) ObjData(stro);
+
+ if (flags & DOH_REPLACE_FIRST)
+ count = 1;
+
+ if (flags & DOH_REPLACE_ID_END) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_end);
+ } else if (flags & DOH_REPLACE_ID_BEGIN) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier_begin);
+ } else if (flags & DOH_REPLACE_ID) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_identifier);
+ } else if (flags & DOH_REPLACE_NUMBER_END) {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_number_end);
+ } else {
+ return replace_simple(str, Char(token), Char(rep), flags, count, match_simple);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * String_chop()
+ * ----------------------------------------------------------------------------- */
+
+static void String_chop(DOH *so) {
+ char *c;
+ String *str = (String *) ObjData(so);
+ /* Replace trailing whitespace */
+ c = str->str + str->len - 1;
+ while ((str->len > 0) && (isspace((int) *c))) {
+ if (str->sp >= str->len) {
+ str->sp--;
+ if (*c == '\n')
+ str->line--;
+ }
+ str->len--;
+ c--;
+ }
+ str->str[str->len] = 0;
+ assert(str->sp >= 0);
+ str->hashkey = -1;
+}
+
+static void String_setfile(DOH *so, DOH *file) {
+ DOH *fo;
+ String *str = (String *) ObjData(so);
+
+ if (!DohCheck(file)) {
+ fo = NewString(file);
+ Decref(fo);
+ } else
+ fo = file;
+ Incref(fo);
+ Delete(str->file);
+ str->file = fo;
+}
+
+static DOH *String_getfile(DOH *so) {
+ String *str = (String *) ObjData(so);
+ return str->file;
+}
+
+static void String_setline(DOH *so, int line) {
+ String *str = (String *) ObjData(so);
+ str->line = line;
+}
+
+static int String_getline(DOH *so) {
+ String *str = (String *) ObjData(so);
+ return str->line;
+}
+
+static DohListMethods StringListMethods = {
+ 0, /* doh_getitem */
+ 0, /* doh_setitem */
+ String_delitem, /* doh_delitem */
+ String_insert, /* doh_insitem */
+ String_delslice, /* doh_delslice */
+};
+
+static DohFileMethods StringFileMethods = {
+ String_read,
+ String_write,
+ String_putc,
+ String_getc,
+ String_ungetc,
+ String_seek,
+ String_tell,
+};
+
+static DohStringMethods StringStringMethods = {
+ String_replace,
+ String_chop,
+};
+
+DohObjInfo DohStringType = {
+ "String", /* objname */
+ DelString, /* doh_del */
+ CopyString, /* doh_copy */
+ String_clear, /* doh_clear */
+ String_str, /* doh_str */
+ String_data, /* doh_data */
+ String_dump, /* doh_dump */
+ String_len, /* doh_len */
+ String_hash, /* doh_hash */
+ String_cmp, /* doh_cmp */
+ String_equal, /* doh_equal */
+ 0, /* doh_first */
+ 0, /* doh_next */
+ String_setfile, /* doh_setfile */
+ String_getfile, /* doh_getfile */
+ String_setline, /* doh_setline */
+ String_getline, /* doh_getline */
+ 0, /* doh_mapping */
+ &StringListMethods, /* doh_sequence */
+ &StringFileMethods, /* doh_file */
+ &StringStringMethods, /* doh_string */
+ 0, /* doh_position */
+ 0
+};
+
+
+#define INIT_MAXSIZE 16
+
+/* -----------------------------------------------------------------------------
+ * NewString() - Create a new string
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewString(const DOHString_or_char *so) {
+ int l = 0, max;
+ String *str;
+ char *s;
+ int hashkey = -1;
+ if (DohCheck(so)) {
+ str = (String *) ObjData(so);
+ s = (char *) String_data((String *) so);
+ l = s ? str->len : 0;
+ hashkey = str->hashkey;
+ } else {
+ s = (char *) so;
+ l = s ? (int) strlen(s) : 0;
+ }
+
+ str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = hashkey;
+ str->sp = 0;
+ str->line = 0;
+ str->file = 0;
+ max = INIT_MAXSIZE;
+ if (s) {
+ if ((l + 1) > max)
+ max = l + 1;
+ }
+ str->str = (char *) DohMalloc(max);
+ str->maxsize = max;
+ if (s) {
+ strcpy(str->str, s);
+ str->len = l;
+ str->sp = l;
+ } else {
+ str->str[0] = 0;
+ str->len = 0;
+ }
+ return DohObjMalloc(&DohStringType, str);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * NewStringEmpty() - Create a new string
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewStringEmpty(void) {
+ int max = INIT_MAXSIZE;
+ String *str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = 0;
+ str->sp = 0;
+ str->line = 0;
+ str->file = 0;
+ str->str = (char *) DohMalloc(max);
+ str->maxsize = max;
+ str->str[0] = 0;
+ str->len = 0;
+ return DohObjMalloc(&DohStringType, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewStringWithSize() - Create a new string
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewStringWithSize(const DOHString_or_char *so, int len) {
+ int l = 0, max;
+ String *str;
+ char *s;
+ if (DohCheck(so)) {
+ s = (char *) String_data((String *) so);
+ } else {
+ s = (char *) so;
+ }
+
+ str = (String *) DohMalloc(sizeof(String));
+ str->hashkey = -1;
+ str->sp = 0;
+ str->line = 0;
+ str->file = 0;
+ max = INIT_MAXSIZE;
+ if (s) {
+ l = (int) len;
+ if ((l + 1) > max)
+ max = l + 1;
+ }
+ str->str = (char *) DohMalloc(max);
+ str->maxsize = max;
+ if (s) {
+ memcpy(str->str, s, len);
+ str->str[l] = 0;
+ str->len = l;
+ str->sp = l;
+ } else {
+ str->str[0] = 0;
+ str->len = 0;
+ }
+ return DohObjMalloc(&DohStringType, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * NewStringf()
+ *
+ * Create a new string from a list of objects.
+ * ----------------------------------------------------------------------------- */
+
+DOHString *DohNewStringf(const DOHString_or_char *fmt, ...) {
+ va_list ap;
+ DOH *r;
+ va_start(ap, fmt);
+ r = NewStringEmpty();
+ DohvPrintf(r, Char(fmt), ap);
+ va_end(ap);
+ return (DOHString *) r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Strcmp()
+ * Strncmp()
+ * Strstr()
+ * Strchr()
+ *
+ * Some utility functions.
+ * ----------------------------------------------------------------------------- */
+
+int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2) {
+ const char *c1 = Char(s1);
+ const char *c2 = Char(s2);
+ return strcmp(c1, c2);
+}
+
+int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n) {
+ return strncmp(Char(s1), Char(s2), n);
+}
+
+char *DohStrstr(const DOHString_or_char *s1, const DOHString_or_char *s2) {
+ char *p1 = Char(s1);
+ char *p2 = Char(s2);
+ return p1 == 0 || p2 == 0 || *p2 == '\0' ? p1 : strstr(p1, p2);
+}
+
+char *DohStrchr(const DOHString_or_char *s1, int ch) {
+ return strchr(Char(s1), ch);
+}
diff --git a/contrib/tools/swig/Source/DOH/void.c b/contrib/tools/swig/Source/DOH/void.c
new file mode 100644
index 00000000000..bbecca21b4e
--- /dev/null
+++ b/contrib/tools/swig/Source/DOH/void.c
@@ -0,0 +1,96 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * void.c
+ *
+ * Implements a "void" object that is really just a DOH container around
+ * an arbitrary C object represented as a void *.
+ * ----------------------------------------------------------------------------- */
+
+#include "dohint.h"
+
+typedef struct {
+ void *ptr;
+ void (*del) (void *);
+} VoidObj;
+
+/* -----------------------------------------------------------------------------
+ * Void_delete()
+ *
+ * Delete a void object. Invokes the destructor supplied at the time of creation.
+ * ----------------------------------------------------------------------------- */
+
+static void Void_delete(DOH *vo) {
+ VoidObj *v = (VoidObj *) ObjData(vo);
+ if (v->del)
+ (*v->del) (v->ptr);
+ DohFree(v);
+}
+
+/* -----------------------------------------------------------------------------
+ * Void_copy()
+ *
+ * Copies a void object. This is only a shallow copy. The object destruction
+ * function is not copied in order to avoid potential double-free problems.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *Void_copy(DOH *vo) {
+ VoidObj *v = (VoidObj *) ObjData(vo);
+ return NewVoid(v->ptr, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Void_data()
+ *
+ * Returns the void * stored in the object.
+ * ----------------------------------------------------------------------------- */
+
+static void *Void_data(DOH *vo) {
+ VoidObj *v = (VoidObj *) ObjData(vo);
+ return v->ptr;
+}
+
+static DohObjInfo DohVoidType = {
+ "VoidObj", /* objname */
+ Void_delete, /* doh_del */
+ Void_copy, /* doh_copy */
+ 0, /* doh_clear */
+ 0, /* doh_str */
+ Void_data, /* doh_data */
+ 0, /* doh_dump */
+ 0, /* doh_len */
+ 0, /* doh_hash */
+ 0, /* doh_cmp */
+ 0, /* doh_equal */
+ 0, /* doh_first */
+ 0, /* doh_next */
+ 0, /* doh_setfile */
+ 0, /* doh_getfile */
+ 0, /* doh_setline */
+ 0, /* doh_getline */
+ 0, /* doh_mapping */
+ 0, /* doh_sequence */
+ 0, /* doh_file */
+ 0, /* doh_string */
+ 0, /* doh_reserved */
+ 0, /* clientdata */
+};
+
+/* -----------------------------------------------------------------------------
+ * NewVoid()
+ *
+ * Creates a new Void object given a void * and an optional destructor function.
+ * ----------------------------------------------------------------------------- */
+
+DOH *DohNewVoid(void *obj, void (*del) (void *)) {
+ VoidObj *v;
+ v = (VoidObj *) DohMalloc(sizeof(VoidObj));
+ v->ptr = obj;
+ v->del = del;
+ return DohObjMalloc(&DohVoidType, v);
+}
diff --git a/contrib/tools/swig/Source/Doxygen/csharpdoc.cxx b/contrib/tools/swig/Source/Doxygen/csharpdoc.cxx
new file mode 100644
index 00000000000..9b2b6038b94
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/csharpdoc.cxx
@@ -0,0 +1,989 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * csharpdoc.cxx
+ *
+ * Module to return documentation for nodes formatted for CSharpDoc
+ * ----------------------------------------------------------------------------- */
+
+#include "csharpdoc.h"
+#include "doxyparser.h"
+#include <sstream>
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "swigmod.h"
+
+// define static tables, they are filled in CSharpDocConverter's constructor
+CSharpDocConverter::TagHandlersMap CSharpDocConverter::tagHandlers;
+
+using std::string;
+
+// Helper class increasing the provided indent string in its ctor and decreasing
+// it in its dtor.
+class IndentGuard {
+public:
+ // One indent level.
+ static const char *Level() {
+ return " ";
+ }
+ // Default ctor doesn't do anything and prevents the dtor from doing anything// too and should only be used when the guard needs to be initialized// conditionally as Init() can then be called after checking some condition.// Otherwise, prefer to use the non default ctor below.
+ IndentGuard() {
+ m_initialized = false;
+ }
+
+ // Ctor takes the output to determine the current indent and to remove the
+ // extra indent added to it in the dtor and the variable containing the indent
+ // to use, which must be used after every new line by the code actually
+ // updating the output.
+ IndentGuard(string &output, string &indent) {
+ Init(output, indent);
+ }
+
+ // Really initializes the object created using the default ctor.
+ void Init(string &output, string &indent) {
+ m_output = &output;
+ m_indent = &indent;
+
+ const string::size_type lastNonSpace = m_output->find_last_not_of(' ');
+ if (lastNonSpace == string::npos) {
+ m_firstLineIndent = m_output->length();
+ } else if ((*m_output)[lastNonSpace] == '\n') {
+ m_firstLineIndent = m_output->length() - (lastNonSpace + 1);
+ } else {
+ m_firstLineIndent = 0;
+ }
+
+ // Notice that the indent doesn't include the first line indent because it's
+ // implicit, i.e. it is present in the input and so is copied into the
+ // output anyhow.
+ *m_indent = Level();
+
+ m_initialized = true;
+ }
+
+ // Get the indent for the first line of the paragraph, which is smaller than
+ // the indent for the subsequent lines.
+ string getFirstLineIndent() const {
+ return string(m_firstLineIndent, ' ');
+ }
+
+ ~IndentGuard() {
+ if (!m_initialized)
+ return;
+
+ m_indent->clear();
+
+ // Get rid of possible remaining extra indent, e.g. if there were any trailing
+ // new lines: we shouldn't add the extra indent level to whatever follows
+ // this paragraph.
+ static const size_t lenIndentLevel = strlen(Level());
+ if (m_output->length() > lenIndentLevel) {
+ const size_t start = m_output->length() - lenIndentLevel;
+ if (m_output->compare(start, string::npos, Level()) == 0)
+ m_output->erase(start);
+ }
+ }
+
+private:
+ string *m_output;
+ string *m_indent;
+ string::size_type m_firstLineIndent;
+ bool m_initialized;
+
+ IndentGuard(const IndentGuard &);
+};
+
+static void replaceAll(std::string &src, const std::string &token, const std::string &replace) {
+ std::string::size_type pos = src.find(token);
+
+ while (pos != std::string::npos) {
+ src.replace(pos, token.size(), replace);
+ pos = src.find(token, pos + replace.size());
+ }
+}
+
+static void trimWhitespace(string &s) {
+ const string::size_type lastNonSpace = s.find_last_not_of(' ');
+ if (lastNonSpace == string::npos)
+ s.clear();
+ else
+ s.erase(lastNonSpace + 1);
+}
+
+// Erase the first character in the string if it is a newline
+static void eraseLeadingNewLine(string &s) {
+ if (!s.empty() && s[0] == '\n')
+ s.erase(s.begin());
+}
+
+// Erase the first character in the string if it is a newline
+static void eraseAllNewLine(string &str) {
+ for (size_t i = 0; i < str.size(); i++) {
+ // if the character is a newline character
+ if (str[i] == '\n') {
+ // remove the character
+ str.erase(i, 1);
+ // decrement the index to account for the removed character
+ i--;
+ }
+ }
+}
+
+// Erase last characters in the string if it is a newline or a space
+static void eraseTrailingSpaceNewLines(string &s) {
+ while (!s.empty() && (s[s.size() - 1] == '\n' || s[s.size() - 1] == ' '))
+ s.erase(s.size() - 1);
+}
+
+// escape some characters which cannot appear as it in C# comments
+static void escapeSpecificCharacters(string &str) {
+ for (size_t i = 0; i < str.size(); i++) {
+ if (str[i] == '<') {
+ str.replace(i, 1, "&lt;");
+ } else if (str[i] == '>') {
+ str.replace(i, 1, "&gt;");
+ } else if (str[i] == '&') {
+ str.replace(i, 1, "&amp;");
+ }
+ }
+}
+
+// Check the generated docstring line by line and make sure that any
+// code and verbatim blocks have an empty line preceding them, which
+// is necessary for Sphinx. Additionally, this strips any empty lines
+// appearing at the beginning of the docstring.
+static string padCodeAndVerbatimBlocks(const string &docString) {
+ std::string result;
+
+ std::istringstream iss(docString);
+
+ // Initialize to false because there is no previous line yet
+ bool lastLineWasNonBlank = false;
+
+ for (string line; std::getline(iss, line); result += line) {
+ if (!result.empty()) {
+ // Terminate the previous line
+ result += '\n';
+ }
+
+ const size_t pos = line.find_first_not_of(" \t");
+ if (pos == string::npos) {
+ lastLineWasNonBlank = false;
+ } else {
+ if (lastLineWasNonBlank &&
+ (line.compare(pos, 13, ".. code-block") == 0 ||
+ line.compare(pos, 7, ".. math") == 0 ||
+ line.compare(pos, 3, ">>>") == 0)) {
+ // Must separate code or math blocks from the previous line
+ result += '\n';
+ }
+ lastLineWasNonBlank = true;
+ }
+ }
+ return result;
+}
+
+/* static */
+CSharpDocConverter::TagHandlersMap::mapped_type CSharpDocConverter::make_handler(tagHandler handler) {
+ return make_pair(handler, std::string());
+}
+
+/* static */
+CSharpDocConverter::TagHandlersMap::mapped_type CSharpDocConverter::make_handler(tagHandler handler, const char *arg) {
+ return make_pair(handler, arg);
+}
+
+void CSharpDocConverter::fillStaticTables() {
+ if (tagHandlers.size()) // fill only once
+ return;
+
+
+ tagHandlers["a"] = make_handler(&CSharpDocConverter::handleTagWrap, "*");
+ tagHandlers["b"] = make_handler(&CSharpDocConverter::handleTagWrap, "**");
+ // \c command is translated as single quotes around next word
+ tagHandlers["c"] = make_handler(&CSharpDocConverter::handleTagWrap, "``");
+ tagHandlers["cite"] = make_handler(&CSharpDocConverter::handleTagWrap, "'");
+ tagHandlers["e"] = make_handler(&CSharpDocConverter::handleTagWrap, "*");
+ // these commands insert just a single char, some of them need to be escaped
+ tagHandlers["$"] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["@"] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["\\"] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["<"] = make_handler(&CSharpDocConverter::handleTagCharReplace, "&lt;");
+ tagHandlers[">"] = make_handler(&CSharpDocConverter::handleTagCharReplace, "&gt;");
+ tagHandlers["&"] = make_handler(&CSharpDocConverter::handleTagCharReplace, "&amp;");
+ tagHandlers["#"] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["%"] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["~"] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["\""] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["."] = make_handler(&CSharpDocConverter::handleTagChar);
+ tagHandlers["::"] = make_handler(&CSharpDocConverter::handleTagChar);
+ // these commands are stripped out, and only their content is printed
+ tagHandlers["attention"] = make_handler(&CSharpDocConverter::handleParagraph, "remarks");
+ tagHandlers["author"] = make_handler(&CSharpDocConverter::handleTagWord, "Author");
+ tagHandlers["authors"] = make_handler(&CSharpDocConverter::handleTagWord, "Author");
+ tagHandlers["brief"] = make_handler(&CSharpDocConverter::handleSummary);
+ tagHandlers["bug"] = make_handler(&CSharpDocConverter::handleTagWord, "Bug:");
+ tagHandlers["code"] = make_handler(&CSharpDocConverter::handleCode);
+ tagHandlers["copyright"] = make_handler(&CSharpDocConverter::handleParagraph, "remarks");
+ tagHandlers["date"] = make_handler(&CSharpDocConverter::handleTagWord, "Date");
+ tagHandlers["deprecated"] = make_handler(&CSharpDocConverter::handleTagWord, "Deprecated");
+ tagHandlers["details"] = make_handler(&CSharpDocConverter::handleParagraph, "remarks");
+ tagHandlers["em"] = make_handler(&CSharpDocConverter::handleTagWrap, "*");
+ tagHandlers["example"] = make_handler(&CSharpDocConverter::handleTagWord, "Example");
+ tagHandlers["exception"] = tagHandlers["throw"] = tagHandlers["throws"] = make_handler(&CSharpDocConverter::handleTagException);
+ tagHandlers["htmlonly"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["invariant"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["latexonly"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["link"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["manonly"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["note"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["p"] = make_handler(&CSharpDocConverter::handleTagWrap, "``");
+ tagHandlers["partofdescription"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["rtfonly"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["remark"] = make_handler(&CSharpDocConverter::handleParagraph, "remarks");
+ tagHandlers["remarks"] = make_handler(&CSharpDocConverter::handleParagraph, "remarks");
+ tagHandlers["sa"] = make_handler(&CSharpDocConverter::handleTagSee);
+ tagHandlers["see"] = make_handler(&CSharpDocConverter::handleTagSee);
+ tagHandlers["since"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["short"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ tagHandlers["todo"] = make_handler(&CSharpDocConverter::handleTagWord, "TODO");
+ tagHandlers["version"] = make_handler(&CSharpDocConverter::handleTagWord, "Version");
+ tagHandlers["verbatim"] = make_handler(&CSharpDocConverter::handleVerbatimBlock);
+ tagHandlers["warning"] = make_handler(&CSharpDocConverter::handleLine, "remarks");
+ tagHandlers["xmlonly"] = make_handler(&CSharpDocConverter::handleNotHandled);
+ // these commands have special handlers
+ tagHandlers["arg"] = make_handler(&CSharpDocConverter::handleAddList);
+ tagHandlers["cond"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["else"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["elseif"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["endcond"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["if"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["ifnot"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["image"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["li"] = make_handler(&CSharpDocConverter::handleIgnore);
+ tagHandlers["overload"] = make_handler(&CSharpDocConverter::handleIgnore);
+
+ tagHandlers["par"] = make_handler(&CSharpDocConverter::handleTagWord, "Title");
+ tagHandlers["param"] = tagHandlers["tparam"] = make_handler(&CSharpDocConverter::handleTagParam);
+ tagHandlers["ref"] = make_handler(&CSharpDocConverter::handleTagRef);
+ tagHandlers["result"] = tagHandlers["return"] = tagHandlers["returns"] = make_handler(&CSharpDocConverter::handleTagReturn);
+
+ // this command just prints its contents
+ // (it is internal command of swig's parser, contains plain text)
+ tagHandlers["plainstd::string"] = make_handler(&CSharpDocConverter::handlePlainString);
+ tagHandlers["plainstd::endl"] = make_handler(&CSharpDocConverter::handleNewLine);
+ tagHandlers["n"] = make_handler(&CSharpDocConverter::handleNewLine);
+
+ // \f commands output literal Latex formula, which is still better than nothing.
+ tagHandlers["f$"] = tagHandlers["f["] = tagHandlers["f{"] = make_handler(&CSharpDocConverter::handleMath);
+
+ // HTML tags
+ tagHandlers["<a"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag_A);
+ tagHandlers["<b"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "**");
+ tagHandlers["<blockquote"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag_A, "Quote: ");
+ tagHandlers["<body"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<br"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "\n");
+
+ // there is no formatting for this tag as it was deprecated in HTML 4.01 and
+ // not used in HTML 5
+ tagHandlers["<center"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<caption"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<code"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "``");
+
+ tagHandlers["<dl"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<dd"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, " ");
+ tagHandlers["<dt"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+
+ tagHandlers["<dfn"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<div"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<em"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "**");
+ tagHandlers["<form"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<hr"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "--------------------------------------------------------------------\n");
+ tagHandlers["<h1"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "# ");
+ tagHandlers["<h2"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "## ");
+ tagHandlers["<h3"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "### ");
+ tagHandlers["<i"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "*");
+ tagHandlers["<input"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<img"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "Image:");
+ tagHandlers["<li"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "* ");
+ tagHandlers["<meta"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<multicol"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<ol"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<p"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, "\n");
+ tagHandlers["<pre"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<small"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<span"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "'");
+ tagHandlers["<strong"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "**");
+
+ // make a space between text and super/sub script.
+ tagHandlers["<sub"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, " ");
+ tagHandlers["<sup"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag, " ");
+
+ tagHandlers["<table"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTagNoParam);
+ tagHandlers["<td"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag_td);
+ tagHandlers["<th"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag_th);
+ tagHandlers["<tr"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag_tr);
+ tagHandlers["<tt"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<kbd"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<ul"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<var"] = make_handler(&CSharpDocConverter::handleDoxyHtmlTag2, "*");
+
+ // HTML entities
+ tagHandlers["&copy"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "(C)");
+ tagHandlers["&trade"] = make_handler(&CSharpDocConverter::handleHtmlEntity, " TM");
+ tagHandlers["&reg"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "(R)");
+ tagHandlers["&lt"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "<");
+ tagHandlers["&gt"] = make_handler(&CSharpDocConverter::handleHtmlEntity, ">");
+ tagHandlers["&amp"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "&");
+ tagHandlers["&apos"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "'");
+ tagHandlers["&quot"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "\"");
+ tagHandlers["&lsquo"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "`");
+ tagHandlers["&rsquo"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "'");
+ tagHandlers["&ldquo"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "\"");
+ tagHandlers["&rdquo"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "\"");
+ tagHandlers["&ndash"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "-");
+ tagHandlers["&mdash"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "--");
+ tagHandlers["&nbsp"] = make_handler(&CSharpDocConverter::handleHtmlEntity, " ");
+ tagHandlers["&times"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "x");
+ tagHandlers["&minus"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "-");
+ tagHandlers["&sdot"] = make_handler(&CSharpDocConverter::handleHtmlEntity, ".");
+ tagHandlers["&sim"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "~");
+ tagHandlers["&le"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "<=");
+ tagHandlers["&ge"] = make_handler(&CSharpDocConverter::handleHtmlEntity, ">=");
+ tagHandlers["&larr"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "<--");
+ tagHandlers["&rarr"] = make_handler(&CSharpDocConverter::handleHtmlEntity, "-->");
+}
+
+CSharpDocConverter::CSharpDocConverter(int flags):
+DoxygenTranslator(flags), m_tableLineLen(0), m_prevRowIsTH(false) {
+ fillStaticTables();
+}
+
+// Return the type as it should appear in the output documentation.
+static std::string getCSharpDocType(Node *n, const_String_or_char_ptr lname = "") {
+ std::string type;
+
+ String *s = Swig_typemap_lookup("doctype", n, lname, 0);
+ if (!s) {
+ if (String *t = Getattr(n, "type"))
+ s = SwigType_str(t, "");
+ }
+ /////////////////
+
+ if (!s)
+ return type;
+
+ type = Char(s);
+
+ Delete(s);
+
+ return type;
+}
+
+std::string CSharpDocConverter::getParamType(std::string param) {
+ std::string type;
+
+ ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
+ for (Parm *p = plist; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+ if (pname && Char(pname) == param) {
+ type = getCSharpDocType(p, pname);
+ break;
+ }
+ }
+ Delete(plist);
+ return type;
+}
+
+std::string CSharpDocConverter::getParamValue(std::string param) {
+ std::string value;
+
+ ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
+ for (Parm *p = plist; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+ if (pname && Char(pname) == param) {
+ String *pval = Getattr(p, "value");
+ if (pval)
+ value = Char(pval);
+ break;
+ }
+ }
+ Delete(plist);
+ return value;
+}
+
+/**
+ * Returns true, if the given parameter exists in the current node
+ * (for example param is a name of function parameter). If feature
+ * 'doxygen:nostripparams' is set, then this method always returns
+ * true - parameters are copied to output regardless of presence in
+ * function params list.
+ */
+bool CSharpDocConverter::paramExists(std::string param) {
+
+ if (GetFlag(currentNode, "feature:doxygen:nostripparams")) {
+ return true;
+ }
+
+ ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
+
+ for (Parm *p = plist; p;) {
+
+ if (Getattr(p, "name") && Char(Getattr(p, "name")) == param) {
+ return true;
+ }
+ /* doesn't seem to work always: in some cases (especially for 'self' parameters)
+ * tmap:in is present, but tmap:in:next is not and so this code skips all the parameters
+ */
+ //p = Getattr(p, "tmap:in") ? Getattr(p, "tmap:in:next") : nextSibling(p);
+ p = nextSibling(p);
+ }
+
+ Delete(plist);
+
+ return false;
+}
+
+std::string CSharpDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
+ std::string translatedComment;
+
+ if (doxygenEntity.isLeaf)
+ return translatedComment;
+
+ std::string currentSection;
+ std::list<DoxygenEntity>::iterator p = doxygenEntity.entityList.begin();
+ while (p != doxygenEntity.entityList.end()) {
+ translateEntity(*p, translatedComment);
+ translateSubtree(*p);
+ p++;
+ }
+
+ return translatedComment;
+}
+
+void CSharpDocConverter::translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment) {
+ // check if we have needed handler and call it
+ std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
+ it = tagHandlers.find(getBaseCommand(doxyEntity.typeOfEntity));
+ if (it != tagHandlers.end())
+ (this->*(it->second.first)) (doxyEntity, translatedComment, it->second.second);
+}
+
+void CSharpDocConverter::handleIgnore(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ if (tag.entityList.size()) {
+ tag.entityList.pop_front();
+ }
+
+ translatedComment += translateSubtree(tag);
+}
+
+void CSharpDocConverter::handleSummary(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+
+ translatedComment += "<summary>";
+ std::string summary = translateSubtree(tag);
+
+ eraseAllNewLine(summary);
+ trimWhitespace(summary);
+ // remove final newlines
+ eraseTrailingSpaceNewLines(summary);
+ escapeSpecificCharacters(summary);
+
+ translatedComment += summary;
+
+
+ translatedComment += "</summary>";
+ translatedComment += "\n";
+}
+
+void CSharpDocConverter::handleLine(DoxygenEntity &tag, std::string &translatedComment, const std::string &tagName) {
+
+ translatedComment += "<" + tagName + ">";
+ if (tag.entityList.size()) {
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ }
+ translatedComment += "</" + tagName + ">";
+}
+
+
+void CSharpDocConverter::handleNotHandled(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+
+ std::string paragraph = translateSubtree(tag);
+
+ eraseLeadingNewLine(paragraph);
+ eraseTrailingSpaceNewLines(paragraph);
+ trimWhitespace(paragraph);
+ escapeSpecificCharacters(paragraph);
+ translatedComment += paragraph;
+ translatedComment += "\n";
+}
+
+void CSharpDocConverter::handleAddList(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string listItem = translateSubtree(tag);
+ eraseAllNewLine(listItem);
+
+ translatedComment += "* ";
+ translatedComment += listItem;
+ translatedComment += "\n";
+}
+
+
+void CSharpDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &tagName) {
+ translatedComment += "<";
+ translatedComment += tagName;
+ translatedComment += ">";
+
+ std::string paragraph = translateSubtree(tag);
+
+ eraseAllNewLine(paragraph);
+ trimWhitespace(paragraph);
+ eraseTrailingSpaceNewLines(paragraph);
+ escapeSpecificCharacters(paragraph);
+
+ translatedComment += paragraph;
+
+ translatedComment += "</";
+ translatedComment += tagName;
+ translatedComment += ">\n";
+}
+
+void CSharpDocConverter::handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ string verb = translateSubtree(tag);
+
+ eraseLeadingNewLine(verb);
+
+ // Remove the last newline to prevent doubling the newline already present after \endverbatim
+ trimWhitespace(verb); // Needed to catch trailing newline below
+ eraseTrailingSpaceNewLines(verb);
+ escapeSpecificCharacters(verb);
+
+ translatedComment += verb;
+}
+
+void CSharpDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ IndentGuard indent;
+
+ // Only \f$ is translated to inline formulae, \f[ and \f{ are for the block ones.
+ const bool inlineFormula = tag.typeOfEntity == "f$";
+
+ string formulaNL;
+
+ if (inlineFormula) {
+ translatedComment += ":math:`";
+ } else {
+ indent.Init(translatedComment, m_indent);
+
+ trimWhitespace(translatedComment);
+
+ const string formulaIndent = indent.getFirstLineIndent();
+ translatedComment += formulaIndent;
+ translatedComment += ".. math::\n";
+
+ formulaNL = '\n';
+ formulaNL += formulaIndent;
+ formulaNL += m_indent;
+ translatedComment += formulaNL;
+ }
+
+ std::string formula;
+ handleTagVerbatim(tag, formula, arg);
+
+ // It is important to ensure that we have no spaces around the inline math
+ // contents, so strip them.
+ const size_t start = formula.find_first_not_of(" \t\n");
+ const size_t end = formula.find_last_not_of(" \t\n");
+ if (start != std::string::npos) {
+ for (size_t n = start; n <= end; n++) {
+ if (formula[n] == '\n') {
+ // New lines must be suppressed in inline maths and indented in the block ones.
+ if (!inlineFormula)
+ translatedComment += formulaNL;
+ } else {
+ // Just copy everything else.
+ translatedComment += formula[n];
+ }
+ }
+ }
+
+ if (inlineFormula) {
+ translatedComment += "`";
+ }
+}
+
+void CSharpDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ IndentGuard indent(translatedComment, m_indent);
+
+ trimWhitespace(translatedComment);
+
+ translatedComment += "<code>";
+
+ std::string code;
+ handleTagVerbatim(tag, code, arg);
+
+ // Try and remove leading newline, which is present for block \code
+ // command:
+ escapeSpecificCharacters(code);
+ eraseLeadingNewLine(code);
+ trimWhitespace(code);
+
+ // Check for python doctest blocks, and treat them specially:
+ bool isDocTestBlock = false;
+ size_t startPos;
+ // ">>>" would normally appear at the beginning, but doxygen comment
+ // style may have space in front, so skip leading whitespace
+ if ((startPos = code.find_first_not_of(" \t")) != string::npos && code.substr(startPos, 3) == ">>>")
+ isDocTestBlock = true;
+
+ string codeIndent;
+ if (!isDocTestBlock) {
+ // Use the current indent for the code-block line itself.
+ translatedComment += indent.getFirstLineIndent();
+
+ // Specify the level of extra indentation that will be used for
+ // subsequent lines within the code block. Note that the correct
+ // "starting indentation" is already present in the input, so we
+ // only need to add the desired code block indentation.
+ codeIndent = m_indent;
+ }
+
+ translatedComment += codeIndent;
+ for (size_t n = 0; n < code.length(); n++) {
+ if (code[n] == '\n') {
+ // Don't leave trailing white space, this results in PEP8 validation
+ // errors in Python code (which are performed by our own unit tests).
+ trimWhitespace(translatedComment);
+ translatedComment += '\n';
+
+ // Ensure that we indent all the lines by the code indent.
+ translatedComment += codeIndent;
+ } else {
+ // Just copy everything else.
+ translatedComment += code[n];
+ }
+ }
+
+ trimWhitespace(translatedComment);
+
+ // For block commands, the translator adds the newline after
+ // \endcode, so try and compensate by removing the last newline from
+ // the code text:
+ eraseTrailingSpaceNewLines(translatedComment);
+
+ translatedComment += "</code>";
+ translatedComment += "\n";
+}
+
+void CSharpDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += tag.data;
+}
+
+void CSharpDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+ for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
+ translatedComment += it->data;
+ }
+}
+
+void CSharpDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+ handleParagraph(tag, translatedComment);
+ translatedComment += "\">\n";
+}
+
+void CSharpDocConverter::handleTagSee(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += "<seealso cref=\"";
+ std::string seeAlso = translateSubtree(tag);
+ escapeSpecificCharacters(seeAlso);
+
+ // Remove parameter list
+ // Alternative would be to try and convert them into C# types similar to Java implementation
+ std::string::size_type lbrace = seeAlso.find('(');
+ if (lbrace != std::string::npos)
+ seeAlso.erase(lbrace);
+
+ replaceAll(seeAlso, "::", ".");
+ eraseTrailingSpaceNewLines(seeAlso);
+
+ translatedComment += seeAlso;
+ translatedComment += "\"/>\n";
+}
+
+void CSharpDocConverter::handleTagCharReplace(DoxygenEntity &, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+}
+
+void CSharpDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += tag.typeOfEntity;
+}
+
+void CSharpDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+ if (tag.entityList.size()) {
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ translatedComment += " {" + translateSubtree(tag) + "}";
+ }
+}
+
+void CSharpDocConverter::handleTagWord(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg + ": ";
+ if (tag.entityList.size())
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ translatedComment += translateSubtree(tag);
+ translatedComment += "\n";
+}
+
+void CSharpDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ if (tag.entityList.size() < 2)
+ return;
+ tag.entityList.pop_front();
+ translatedComment += "Image: ";
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ if (tag.entityList.size())
+ translatedComment += "(" + tag.entityList.begin()->data + ")";
+}
+
+void CSharpDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+
+ if (tag.entityList.size() < 2)
+ return;
+
+ if (!paramExists(tag.entityList.begin()->data))
+ return;
+
+ IndentGuard indent(translatedComment, m_indent);
+
+ DoxygenEntity paramNameEntity = *tag.entityList.begin();
+ tag.entityList.pop_front();
+
+ const std::string &paramName = paramNameEntity.data;
+
+ const std::string paramValue = getParamValue(paramName);
+
+ translatedComment += "<param name=\"" + paramName + "\">";
+
+ translatedComment += translateSubtree(tag);
+ eraseTrailingSpaceNewLines(translatedComment);
+
+ translatedComment += "</param> \n";
+}
+
+
+void CSharpDocConverter::handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ IndentGuard indent(translatedComment, m_indent);
+
+ translatedComment += "<returns>";
+ translatedComment += translateSubtree(tag);
+ eraseTrailingSpaceNewLines(translatedComment);
+ translatedComment += "</returns> \n";
+}
+
+
+void CSharpDocConverter::handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ IndentGuard indent(translatedComment, m_indent);
+
+ DoxygenEntity paramNameEntity = *tag.entityList.begin();
+ tag.entityList.pop_front();
+
+ const std::string &paramName = paramNameEntity.data;
+
+ const std::string paramType = getParamType(paramName);
+ const std::string paramValue = getParamValue(paramName);
+
+ translatedComment += "<exception cref=\"" + paramName + "\">";
+
+ translatedComment += translateSubtree(tag);
+ eraseTrailingSpaceNewLines(translatedComment);
+
+ translatedComment += "</exception> \n";
+}
+
+
+void CSharpDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+
+ if (!tag.entityList.size())
+ return;
+
+ string anchor = tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ string anchorText = anchor;
+
+ size_t pos = anchorText.find('#');
+ if (pos != string::npos) {
+ anchorText = anchorText.substr(pos + 1);
+ }
+
+ if (!tag.entityList.empty()) {
+ anchorText = tag.entityList.begin()->data;
+ }
+ translatedComment += "\\ref " + anchorText;
+}
+
+
+void CSharpDocConverter::handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ if (tag.entityList.size()) { // do not include empty tags
+ std::string tagData = translateSubtree(tag);
+ // wrap the thing, ignoring whitespace
+ size_t wsPos = tagData.find_last_not_of("\n\t ");
+ if (wsPos != std::string::npos && wsPos != tagData.size() - 1)
+ translatedComment += arg + tagData.substr(0, wsPos + 1) + arg + tagData.substr(wsPos + 1);
+ else
+ translatedComment += arg + tagData + arg;
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</ul>
+ // translatedComment += "</" + arg.substr(1) + ">";
+ } else {
+ translatedComment += arg + htmlTagArgs;
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</ul>
+ } else {
+ translatedComment += arg;
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, "</a>
+ translatedComment += " (" + m_url + ')';
+ m_url.clear();
+ } else {
+ m_url.clear();
+ size_t pos = htmlTagArgs.find('=');
+ if (pos != string::npos) {
+ m_url = htmlTagArgs.substr(pos + 1);
+ }
+ translatedComment += arg;
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</em>
+ translatedComment += arg;
+ } else {
+ translatedComment += arg;
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string htmlTagArgs = tag.data;
+ size_t nlPos = translatedComment.rfind('\n');
+ if (htmlTagArgs == "/") {
+ // end tag, </tr> appends vertical table line '|'
+ translatedComment += '|';
+ if (nlPos != string::npos) {
+ size_t startOfTableLinePos = translatedComment.find_first_not_of(" \t", nlPos + 1);
+ if (startOfTableLinePos != string::npos) {
+ m_tableLineLen = translatedComment.size() - startOfTableLinePos;
+ }
+ }
+ } else {
+ if (m_prevRowIsTH) {
+ // if previous row contained <th> tag, add horizontal separator
+ // but first get leading spaces, because they'll be needed for the next row
+ size_t numLeadingSpaces = translatedComment.size() - nlPos - 1;
+
+ translatedComment += string(m_tableLineLen, '-') + '\n';
+
+ if (nlPos != string::npos) {
+ translatedComment += string (numLeadingSpaces, ' ');
+ }
+ m_prevRowIsTH = false;
+ }
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end tag, </th> is ignored
+ } else {
+ translatedComment += '|';
+ m_prevRowIsTH = true;
+ }
+}
+
+void CSharpDocConverter::handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end tag, </td> is ignored
+ } else {
+ translatedComment += '|';
+ }
+}
+
+void CSharpDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg) {
+ // html entities
+ translatedComment += arg;
+}
+
+void CSharpDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, const std::string &) {
+ trimWhitespace(translatedComment);
+
+ translatedComment += "\n";
+
+ if (!m_indent.empty())
+ translatedComment += m_indent;
+}
+
+String *CSharpDocConverter::makeDocumentation(Node *n) {
+ String *documentation;
+ std::string csharpDocString;
+
+ // store the node, we may need it later
+ currentNode = n;
+
+ documentation = getDoxygenComment(n);
+ if (documentation != NULL) {
+ if (GetFlag(n, "feature:doxygen:notranslate")) {
+ String *comment = NewString("");
+ Append(comment, documentation);
+ Replaceall(comment, "\n *", "\n");
+ csharpDocString = Char(comment);
+ Delete(comment);
+ } else {
+ std::list<DoxygenEntity> entityList = parser.createTree(n, documentation);
+ DoxygenEntity root("root", entityList);
+ csharpDocString = translateSubtree(root);
+ }
+ }
+
+ // if we got something log the result
+ if (!csharpDocString.empty()) {
+
+ // remove the last spaces and '\n' since additional one is added during writing to file
+ eraseTrailingSpaceNewLines(csharpDocString);
+
+ // ensure that a blank line occurs before code or math blocks
+ csharpDocString = padCodeAndVerbatimBlocks(csharpDocString);
+
+ if (m_flags & debug_translator) {
+ std::cout << "\n---RESULT IN CSHARPDOC---" << std::endl;
+ std::cout << csharpDocString;
+ std::cout << std::endl;
+ }
+ }
+
+ return NewString(csharpDocString.c_str());
+}
diff --git a/contrib/tools/swig/Source/Doxygen/csharpdoc.h b/contrib/tools/swig/Source/Doxygen/csharpdoc.h
new file mode 100644
index 00000000000..4f47f6a76a9
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/csharpdoc.h
@@ -0,0 +1,243 @@
+/* -----------------------------------------------------------------------------
+ * 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.
+ *
+ * csharpdoc.h
+ *
+ * Module to return documentation for nodes formatted for CSharp
+ * ----------------------------------------------------------------------------- */
+
+#ifndef CSHARPDOCCONVERTER_H_
+#define CSHARPDOCCONVERTER_H_
+
+#include <list>
+#include <string>
+#include "swig.h"
+#include "doxyentity.h"
+#include "doxytranslator.h"
+
+#define DOC_STRING_LENGTH 64 // characters per line allowed
+#define DOC_PARAM_STRING_LENGTH 30 // characters reserved for param name / type
+
+class CSharpDocConverter : public DoxygenTranslator {
+public:
+ CSharpDocConverter(int flags = 0);
+
+ String *makeDocumentation(Node *node);
+
+protected:
+
+ size_t m_tableLineLen;
+ bool m_prevRowIsTH;
+ std::string m_url;
+
+ /*
+ * Translate every entity in a tree, also manages sections
+ * display. Prints title for every group of tags that have
+ * a section title associated with them
+ */
+ std::string translateSubtree(DoxygenEntity &doxygenEntity);
+
+ /*
+ * Translate one entity with the appropriate handler, according
+ * to the tagHandlers
+ */
+ void translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment);
+
+ /*
+ * Typedef for the function that handles one tag
+ * arg - some string argument to easily pass it through lookup table
+ */
+ typedef void (CSharpDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Wrap the command data with the some string
+ * arg - string to wrap with, like '_' or '*'
+ */
+ void handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Just prints new line
+ */
+ void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Replace char by the one ine argument
+ */
+ void handleTagCharReplace(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print the name of tag to the output, used for escape-commands
+ */
+ void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Format the contents of the \exception tag or its synonyms.
+ */
+ void handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /**
+ * Print the content without any tag
+ */
+ void handleNotHandled(DoxygenEntity &tag, std::string &translatedComment, const std::string &tagName);
+
+ /**
+ * Print the content as an item of a list
+ */
+ void handleAddList(DoxygenEntity &tag, std::string &translatedComment, const std::string &tagName);
+
+ /*
+ * Print only the content and strip original tag
+ */
+ void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+/*
+ * Ignore the tag
+ */
+ void handleIgnore(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
+ * Print only the line content and strip original tag
+ */
+ void handleLine(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
+ * Print summary
+ */
+ void handleSummary(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
+ * Handle Doxygen verbatim tag
+ */
+ void handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
+ * Handle one of the Doxygen formula-related tags.
+ */
+ void handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Handle a code snippet.
+ */
+ void handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print only data part of code
+ */
+ void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /**
+ * Copies verbatim args of the tag to output, used for commands like \f$, ...
+ */
+ void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print the if-elseif-else-endif section
+ */
+ void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Prints the specified message, than the contents of the tag
+ * arg - message
+ */
+ void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Prints the seealso tag
+ */
+ void handleTagSee(DoxygenEntity &tag, std::string &translatedComment, const std::string &);
+
+ /*
+ * Insert 'Word: ...'
+ */
+ void handleTagWord(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Insert 'Image: ...'
+ */
+ void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Format nice param description with type information
+ */
+ void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Format the contents of the \return tag or its synonyms.
+ */
+ void handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Writes text for \ref tag.
+ */
+ void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML tags recognized by Doxygen, like <A ...>, <ul>, <table>, ... */
+
+ void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /** Does not output params of HTML tag, for example in <table border='1'>
+ * 'border=1' is not written to output.
+ */
+ void handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /** Translates tag <a href = "url">text</a> to: text ("url"). */
+ void handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Handles HTML tags, which are translated to markdown-like syntax, for example
+ * <i>text</i> --> _text_. Appends arg for start HTML tag and end HTML tag.
+ */
+ void handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML table, tag <tr> */
+ void handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML table, tag <th> */
+ void handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML table, tag <td> */
+ void handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML entities recognized by Doxygen, like &lt;, &copy;, ... */
+ void handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg);
+
+
+ /*
+ * Simple helper function that calculates correct parameter type
+ * of the node stored in 'currentNode'
+ * If param with specified name is not found, empty string is returned
+ */
+ std::string getParamType(std::string name);
+
+ /*
+ * Simple helper function to retrieve the parameter value
+ */
+ std::string getParamValue(std::string name);
+
+private:
+ // temporary thing, should be refactored somehow
+ Node *currentNode;
+
+ // Extra indent for the current paragraph, must be output after each new line.
+ std::string m_indent;
+
+ // this contains the handler pointer and one string argument
+ typedef std::map<std::string, std::pair<tagHandler, std::string> >TagHandlersMap;
+ static TagHandlersMap tagHandlers;
+
+
+ // Helper functions for fillStaticTables(): make a new tag handler object.
+ TagHandlersMap::mapped_type make_handler(tagHandler handler);
+ TagHandlersMap::mapped_type make_handler(tagHandler handler, const char *arg);
+
+ void fillStaticTables();
+
+ bool paramExists(std::string param);
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Doxygen/doxycommands.h b/contrib/tools/swig/Source/Doxygen/doxycommands.h
new file mode 100644
index 00000000000..782b6ab9441
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxycommands.h
@@ -0,0 +1,174 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxycommands.h
+ *
+ * Part of the Doxygen comment translation module of SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef DOXYGENCOMMANDS_H
+#define DOXYGENCOMMANDS_H
+
+// doxy commands are not processed inside this block
+const char *CMD_HTML_ONLY = "htmlonly";
+// doxy commands are not processed inside this block
+const char *CMD_VERBATIM = "verbatim";
+const char *CMD_CODE = "code";
+const char *CMD_LATEX_1 = "f$";
+const char *CMD_LATEX_2 = "f{";
+const char *CMD_LATEX_3 = "f[";
+const char *CMD_END_HTML_ONLY = "endhtmlonly";
+const char *CMD_END_VERBATIM = "endverbatim";
+const char *CMD_END_CODE = "endcode";
+const char *CMD_END_LATEX_1 = "f$";
+const char *CMD_END_LATEX_2 = "f}";
+const char *CMD_END_LATEX_3 = "f]";
+
+const char *sectionIndicators[] = {
+ "attention", "author", "authors", "brief", "bug", "cond", "date",
+ "deprecated", "details", "else", "elseif", "endcond", "endif",
+ "exception", "if", "ifnot", "invariant", "note", "par", "param",
+ "tparam", "post", "pre", "remarks", "remark", "result", "return",
+ "returns", "retval", "sa", "see", "since", "test", "throw", "throws",
+ "todo", "version", "warning", "xrefitem"
+};
+
+const int sectionIndicatorsSize = sizeof(sectionIndicators) / sizeof(*sectionIndicators);
+
+/* All of the doxygen commands divided up by how they are parsed */
+const char *simpleCommands[] = {
+ // the first line are escaped chars, except \~, which is a language ID command.
+ "n", "$", "@", "\\", "&", "~", "<", ">", "#", "%", "\"", ".", "::",
+ // Member groups, which we currently ignore.
+ "{", "}",
+ "endcond",
+ "callgraph", "callergraph", "showinitializer", "hideinitializer", "internal",
+ "nosubgrouping", "public", "publicsection", "private", "privatesection",
+ "protected", "protectedsection", "tableofcontents"
+};
+
+const int simpleCommandsSize = sizeof(simpleCommands) / sizeof(*simpleCommands);
+
+const char *commandWords[] = {
+ "a", "b", "c", "e", "em", "p", "def", "enum", "package", "relates",
+ "namespace", "relatesalso", "anchor", "dontinclude", "include",
+ "includelineno", "copydoc", "copybrief", "copydetails", "verbinclude",
+ "htmlinclude", "extends", "implements", "memberof", "related", "relatedalso",
+ "cite"
+};
+
+const int commandWordsSize = sizeof(commandWords) / sizeof(*commandWords);
+
+const char *commandLines[] = {
+ "addindex", "fn", "name", "line", "var", "skipline", "typedef", "skip",
+ "until", "property"
+};
+
+const int commandLinesSize = sizeof(commandLines) / sizeof(*commandLines);
+
+const char *commandParagraph[] = {
+ "partofdescription", "result", "return", "returns", "remarks", "remark",
+ "since", "test", "sa", "see", "pre", "post", "details", "invariant",
+ "deprecated", "date", "note", "warning", "version", "todo", "bug",
+ "attention", "brief", "author", "authors", "copyright", "short"
+};
+
+const int commandParagraphSize = sizeof(commandParagraph) / sizeof(*commandParagraph);
+
+const char *commandEndCommands[] = {
+ CMD_HTML_ONLY, "latexonly", "manonly", "xmlonly", "link", "rtfonly"
+};
+
+const int commandEndCommandsSize = sizeof(commandEndCommands) / sizeof(*commandEndCommands);
+
+const char *commandWordParagraphs[] = {
+ "param", "tparam", "throw", "throws", "retval", "exception", "example"
+};
+
+const int commandWordParagraphsSize = sizeof(commandWordParagraphs) / sizeof(*commandWordParagraphs);
+
+const char *commandWordLines[] = {
+ "page", "subsection", "subsubsection", "section", "paragraph", "defgroup",
+ "snippet", "mainpage"
+};
+
+const int commandWordLinesSize = sizeof(commandWordLines) / sizeof(*commandWordLines);
+
+const char *commandWordOWordOWords[] = {
+ "category", "class", "protocol", "interface", "struct", "union"
+};
+
+const int commandWordOWordOWordsSize = sizeof(commandWordOWordOWords) / sizeof(*commandWordOWordOWords);
+
+const char *commandOWords[] = {
+ "dir", "file", "cond"
+};
+
+const int commandOWordsSize = sizeof(commandOWords) / sizeof(*commandOWords);
+
+const char *commandErrorThrowings[] = {
+ "annotatedclassstd::list", "classhierarchy", "define", "functionindex", "header",
+ "headerfilestd::list", "inherit", "l", "postheader", "endcode", "enddot", "endmsc", "endhtmlonly",
+ "endlatexonly", "endmanonly", "endlink", "endverbatim", "endxmlonly", "f]", "f}", "endif", "else",
+ "endrtfonly"
+};
+
+const int commandErrorThrowingsSize = sizeof(commandErrorThrowings) / sizeof(*commandErrorThrowings);
+
+const char *commandUniques[] = {
+ "xrefitem", "arg", "ingroup", "par", "headerfile", "overload", "weakgroup", "ref", "subpage", "dotfile", "image", "addtogroup", "li",
+ "if", "ifnot", "elseif", "else", "mscfile", "code", CMD_VERBATIM, "f{", "f[", "f$", "dot", "msc"
+};
+
+const int commandUniquesSize = sizeof(commandUniques) / sizeof(*commandUniques);
+
+// These HTML commands are transformed when producing output in other formats.
+// Other commands are left intact, but '<' and '> are replaced with entities in HTML
+// output. So <varName> appears as &lt;varName&gt; in HTML output. The same
+// behavior must be repeated by SWIG. See Doxygen doc for the list of commands.
+// '<' is prepended to distinguish HTML tags from Doxygen commands.
+const char *commandHtml[] = {
+ "<a", "<b", "<blockquote", "<body", "<br", "<center", "<caption", "<code", "<dd", "<dfn",
+ "<div", "<dl", "<dt", "<em", "<form", "<hr", "<h1", "<h2", "<h3", "<i", "<input", "<img",
+ "<li", "<meta", "<multicol", "<ol", "<p", "<pre", "<small", "<span", "<strong",
+ "<sub", "<sup", "<table", "<td", "<th", "<tr", "<tt", "<kbd", "<ul", "<var"
+};
+
+const int commandHtmlSize = sizeof(commandHtml) / sizeof(*commandHtml);
+
+// Only entities which are translatable to plain text are used here. Others
+// are copied unchanged to output.
+const char *commandHtmlEntities[] = {
+ "&copy", // (C)
+ "&trade", // (TM)
+ "&reg", // (R)
+ "&lt", // less-than symbol
+ "&gt", // greater-than symbol
+ "&amp", // ampersand
+ "&apos", // single quotation mark (straight)
+ "&quot", // double quotation mark (straight)
+ "&lsquo", // left single quotation mark
+ "&rsquo", // right single quotation mark
+ "&ldquo", // left double quotation mark
+ "&rdquo", // right double quotation mark
+ "&ndash", // n-dash (for numeric ranges, e.g. 2–8)
+ "&mdash", // --
+ "&nbsp", //
+ "&times", // x
+ "&minus", // -
+ "&sdot", // .
+ "&sim", // ~
+ "&le", // <=
+ "&ge", // >=
+ "&larr", // <--
+ "&rarr" // -->
+};
+
+const int commandHtmlEntitiesSize = sizeof(commandHtmlEntities) / sizeof(*commandHtmlEntities);
+
+#endif
diff --git a/contrib/tools/swig/Source/Doxygen/doxyentity.cxx b/contrib/tools/swig/Source/Doxygen/doxyentity.cxx
new file mode 100644
index 00000000000..29bbbe6c125
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxyentity.cxx
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxyentity.cxx
+ *
+ * Part of the Doxygen comment translation module of SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "doxyentity.h"
+#include <iostream>
+
+using std::cout;
+
+DoxygenEntity::DoxygenEntity(const std::string &typeEnt):typeOfEntity(typeEnt), isLeaf(true) {
+}
+
+
+/* Basic node for commands that have
+ * only 1 item after them
+ * example: \b word
+ * OR holding a std::string
+ */
+DoxygenEntity::DoxygenEntity(const std::string &typeEnt, const std::string &param1) : typeOfEntity(typeEnt), data(param1), isLeaf(true) {
+}
+
+
+/* Nonterminal node
+ * contains
+ */
+DoxygenEntity::DoxygenEntity(const std::string &typeEnt, const DoxygenEntityList &entList) : typeOfEntity(typeEnt), isLeaf(false), entityList(entList) {
+}
+
+
+void DoxygenEntity::printEntity(int level) const {
+
+ int thisLevel = level;
+
+ if (isLeaf) {
+ for (int i = 0; i < thisLevel; i++) {
+ cout << '\t';
+ }
+
+ cout << "Node Leaf Command: '" << typeOfEntity << "', ";
+
+ if (!data.empty()) {
+ cout << "Node Data: '" << data << "'";
+ }
+ cout << std::endl;
+
+ } else {
+
+ for (int i = 0; i < thisLevel; i++) {
+ cout << '\t';
+ }
+
+ cout << "Node Command: '" << typeOfEntity << "'" << std::endl;
+
+ thisLevel++;
+
+ for (DoxygenEntityListCIt p = entityList.begin(); p != entityList.end(); p++) {
+ p->printEntity(thisLevel);
+ }
+ }
+}
diff --git a/contrib/tools/swig/Source/Doxygen/doxyentity.h b/contrib/tools/swig/Source/Doxygen/doxyentity.h
new file mode 100644
index 00000000000..e475141a3a8
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxyentity.h
@@ -0,0 +1,45 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxyentity.h
+ *
+ * Part of the Doxygen comment translation module of SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DOXYENTITY_H
+#define SWIG_DOXYENTITY_H
+
+#include <string>
+#include <list>
+
+
+class DoxygenEntity;
+
+typedef std::list<DoxygenEntity> DoxygenEntityList;
+typedef DoxygenEntityList::iterator DoxygenEntityListIt;
+typedef DoxygenEntityList::const_iterator DoxygenEntityListCIt;
+
+
+/*
+ * Structure to represent a doxygen comment entry
+ */
+class DoxygenEntity {
+public:
+ std::string typeOfEntity;
+ std::string data;
+ bool isLeaf;
+ DoxygenEntityList entityList;
+
+ DoxygenEntity(const std::string &typeEnt);
+ DoxygenEntity(const std::string &typeEnt, const std::string &param1);
+ DoxygenEntity(const std::string &typeEnt, const DoxygenEntityList &entList);
+
+ void printEntity(int level) const;
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Doxygen/doxyparser.cxx b/contrib/tools/swig/Source/Doxygen/doxyparser.cxx
new file mode 100644
index 00000000000..451c7035988
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxyparser.cxx
@@ -0,0 +1,1493 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxyparser.cxx
+ * ----------------------------------------------------------------------------- */
+
+#include "doxyparser.h"
+#include "doxycommands.h"
+#include "swig.h"
+#include "swigwarn.h"
+
+#include <iostream>
+#include <vector>
+
+using std::string;
+using std::cout;
+using std::endl;
+
+// This constant defines the (only) characters valid inside a Doxygen "word".
+// It includes some unusual ones because of the commands such as \f[, \f{, \f],
+// \f} and \f$.
+static const char *DOXYGEN_WORD_CHARS = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "$[]{}";
+
+// Define static class members
+DoxygenParser::DoxyCommandsMap DoxygenParser::doxygenCommands;
+std::set<std::string> DoxygenParser::doxygenSectionIndicators;
+
+const int TOKENSPERLINE = 8; //change this to change the printing behaviour of the token list
+const std::string END_HTML_TAG_MARK("/");
+
+std::string getBaseCommand(const std::string &cmd) {
+ if (cmd.substr(0,5) == "param")
+ return "param";
+ else if (cmd.substr(0,4) == "code")
+ return "code";
+ else
+ return cmd;
+}
+
+// Find the first position beyond the word command. Extra logic is
+// used to avoid putting the characters "," and "." in
+// DOXYGEN_WORD_CHARS.
+static size_t getEndOfWordCommand(const std::string &line, size_t pos) {
+ size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
+ if (line.substr(pos, 6) == "param[")
+ // include ",", which can appear in param[in,out]
+ endOfWordPos = line.find_first_not_of(string(DOXYGEN_WORD_CHARS)+ ",", pos);
+ else if (line.substr(pos, 5) == "code{")
+ // include ".", which can appear in e.g. code{.py}
+ endOfWordPos = line.find_first_not_of(string(DOXYGEN_WORD_CHARS)+ ".", pos);
+ return endOfWordPos;
+}
+
+
+DoxygenParser::DoxygenParser(bool noisy) : noisy(noisy) {
+ fillTables();
+}
+
+DoxygenParser::~DoxygenParser() {
+}
+
+void DoxygenParser::fillTables() {
+ // run it only once
+ if (doxygenCommands.size())
+ return;
+
+ // fill in tables with data from doxycommands.h
+ for (int i = 0; i < simpleCommandsSize; i++)
+ doxygenCommands[simpleCommands[i]] = SIMPLECOMMAND;
+
+ for (int i = 0; i < commandWordsSize; i++)
+ doxygenCommands[commandWords[i]] = COMMANDWORD;
+
+ for (int i = 0; i < commandLinesSize; i++)
+ doxygenCommands[commandLines[i]] = COMMANDLINE;
+
+ for (int i = 0; i < commandParagraphSize; i++)
+ doxygenCommands[commandParagraph[i]] = COMMANDPARAGRAPH;
+
+ for (int i = 0; i < commandEndCommandsSize; i++)
+ doxygenCommands[commandEndCommands[i]] = COMMANDENDCOMMAND;
+
+ for (int i = 0; i < commandWordParagraphsSize; i++)
+ doxygenCommands[commandWordParagraphs[i]] = COMMANDWORDPARAGRAPH;
+
+ for (int i = 0; i < commandWordLinesSize; i++)
+ doxygenCommands[commandWordLines[i]] = COMMANDWORDLINE;
+
+ for (int i = 0; i < commandWordOWordOWordsSize; i++)
+ doxygenCommands[commandWordOWordOWords[i]] = COMMANDWORDOWORDWORD;
+
+ for (int i = 0; i < commandOWordsSize; i++)
+ doxygenCommands[commandOWords[i]] = COMMANDOWORD;
+
+ for (int i = 0; i < commandErrorThrowingsSize; i++)
+ doxygenCommands[commandErrorThrowings[i]] = COMMANDERRORTHROW;
+
+ for (int i = 0; i < commandUniquesSize; i++)
+ doxygenCommands[commandUniques[i]] = COMMANDUNIQUE;
+
+ for (int i = 0; i < commandHtmlSize; i++)
+ doxygenCommands[commandHtml[i]] = COMMAND_HTML;
+
+ for (int i = 0; i < commandHtmlEntitiesSize; i++)
+ doxygenCommands[commandHtmlEntities[i]] = COMMAND_HTML_ENTITY;
+
+ // fill section indicators command set
+ for (int i = 0; i < sectionIndicatorsSize; i++)
+ doxygenSectionIndicators.insert(sectionIndicators[i]);
+}
+
+std::string DoxygenParser::stringToLower(const std::string &stringToConvert) {
+
+ string result(stringToConvert.size(), ' ');
+
+ for (size_t i = 0; i < result.size(); i++) {
+ result[i] = tolower(stringToConvert[i]);
+ }
+
+ return result;
+}
+
+bool DoxygenParser::isSectionIndicator(const std::string &smallString) {
+
+ std::set<std::string>::iterator it = doxygenSectionIndicators.find(stringToLower(smallString));
+
+ return it != doxygenSectionIndicators.end();
+}
+
+void DoxygenParser::printTree(const DoxygenEntityList &rootList) {
+ DoxygenEntityList::const_iterator p = rootList.begin();
+ while (p != rootList.end()) {
+ (*p).printEntity(0);
+ p++;
+ }
+}
+
+DoxygenParser::DoxyCommandEnum DoxygenParser::commandBelongs(const std::string &theCommand) {
+ DoxyCommandsMapIt it = doxygenCommands.find(stringToLower(getBaseCommand(theCommand)));
+
+ if (it != doxygenCommands.end()) {
+ return it->second;
+ }
+ // Check if this command is defined as an alias.
+ if (Getattr(m_node, ("feature:doxygen:alias:" + theCommand).c_str())) {
+ return COMMAND_ALIAS;
+ }
+ // Check if this command should be ignored.
+ if (String *const ignore = getIgnoreFeature(theCommand)) {
+ // Check that no value is specified for this feature ("1" is the implicit
+ // one given to it by SWIG itself), we may use the value in the future, but
+ // for now we only use the attributes.
+ if (Strcmp(ignore, "1") != 0) {
+ Swig_warning(WARN_PP_UNEXPECTED_TOKENS, m_fileName.c_str(), m_fileLineNo,
+ "Feature \"doxygen:ignore\" value ignored for Doxygen command \"%s\".\n", theCommand.c_str());
+ }
+ // Also ensure that the matching end command, if any, will be recognized.
+ const string endCommand = getIgnoreFeatureEndCommand(theCommand);
+ if (!endCommand.empty()) {
+ Setattr(m_node, ("feature:doxygen:ignore:" + endCommand).c_str(), NewString("1"));
+ }
+
+ return COMMAND_IGNORE;
+ }
+
+ return NONE;
+}
+
+std::string DoxygenParser::trim(const std::string &text) {
+ size_t start = text.find_first_not_of(" \t");
+ size_t end = text.find_last_not_of(" \t");
+
+ if (start == string::npos || start > end) {
+ return "";
+ }
+ return text.substr(start, end - start + 1);
+}
+
+bool DoxygenParser::isEndOfLine() {
+ if (m_tokenListIt == m_tokenList.end()) {
+ return false;
+ }
+ Token nextToken = *m_tokenListIt;
+ return nextToken.m_tokenType == END_LINE;
+}
+
+void DoxygenParser::skipWhitespaceTokens() {
+ if (m_tokenListIt == m_tokenList.end()) {
+ return;
+ }
+
+ while (m_tokenListIt != m_tokenList.end()
+ && (m_tokenListIt->m_tokenType == END_LINE || trim(m_tokenListIt->m_tokenString).empty())) {
+
+ m_tokenListIt++;
+ }
+}
+
+std::string DoxygenParser::getNextToken() {
+
+ if (m_tokenListIt == m_tokenList.end()) {
+ return "";
+ }
+
+ if (m_tokenListIt->m_tokenType == PLAINSTRING) {
+ return (m_tokenListIt++)->m_tokenString;
+ }
+
+ return "";
+}
+
+std::string DoxygenParser::getNextWord() {
+
+ /* if (m_tokenListIt == m_tokenList.end()) {
+ return "";
+ }
+ */
+ while (m_tokenListIt != m_tokenList.end()
+ && (m_tokenListIt->m_tokenType == PLAINSTRING)) {
+ // handle quoted strings as words
+ string token = m_tokenListIt->m_tokenString;
+ if (token == "\"") {
+
+ string word = m_tokenListIt->m_tokenString;
+ m_tokenListIt++;
+ while (true) {
+ string nextWord = getNextToken();
+ if (nextWord.empty()) { // maybe report unterminated string error
+ return word;
+ }
+ word += nextWord;
+ if (nextWord == "\"") {
+ return word;
+ }
+ }
+ }
+
+ string tokenStr = trim(m_tokenListIt->m_tokenString);
+ m_tokenListIt++;
+ if (!tokenStr.empty()) {
+ return tokenStr;
+ }
+ }
+
+ return "";
+}
+
+DoxygenParser::TokenListCIt DoxygenParser::getOneLine(const TokenList &tokList) {
+
+ TokenListCIt endOfLineIt = m_tokenListIt;
+
+ while (endOfLineIt != tokList.end()) {
+ if (endOfLineIt->m_tokenType == END_LINE) {
+ return endOfLineIt;
+ }
+ endOfLineIt++;
+ }
+
+ return tokList.end();
+}
+
+std::string DoxygenParser::getStringTilCommand(const TokenList &tokList) {
+
+ if (m_tokenListIt == tokList.end()) {
+ return "";
+ }
+
+ string description;
+
+ while (m_tokenListIt->m_tokenType == PLAINSTRING) {
+ const Token &currentToken = *m_tokenListIt++;
+ if (currentToken.m_tokenType == PLAINSTRING) {
+ description = description + currentToken.m_tokenString; // + " ";
+ }
+ }
+ return description;
+}
+
+std::string DoxygenParser::getStringTilEndCommand(const std::string &theCommand, const TokenList &tokList) {
+
+ if (m_tokenListIt == tokList.end()) {
+ return "";
+ }
+
+ string description;
+ while (m_tokenListIt != tokList.end()) {
+
+ if (m_tokenListIt->m_tokenType == PLAINSTRING) {
+ description += m_tokenListIt->m_tokenString;
+ } else if (m_tokenListIt->m_tokenType == END_LINE) {
+ description += "\n";
+ } else if (m_tokenListIt->m_tokenString == theCommand) {
+ m_tokenListIt++;
+ return description;
+ }
+
+ m_tokenListIt++;
+ }
+
+ printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: " + theCommand + ".");
+
+ return description;
+}
+
+DoxygenParser::TokenListCIt DoxygenParser::getEndOfParagraph(const TokenList &tokList) {
+
+ TokenListCIt endOfParagraph = m_tokenListIt;
+
+ while (endOfParagraph != tokList.end()) {
+ // If \code or \verbatim is encountered within a paragraph, then
+ // go all the way to the end of that command, since the content
+ // could contain empty lines that would appear to be paragraph
+ // ends:
+ if (endOfParagraph->m_tokenType == COMMAND &&
+ (endOfParagraph->m_tokenString == "code" ||
+ endOfParagraph->m_tokenString == "verbatim")) {
+ const string theCommand = endOfParagraph->m_tokenString;
+ endOfParagraph = getEndCommand("end" + theCommand, tokList);
+ endOfParagraph++; // Move after the end command
+ return endOfParagraph;
+ }
+ if (endOfParagraph->m_tokenType == END_LINE) {
+ endOfParagraph++;
+ if (endOfParagraph != tokList.end()
+ && endOfParagraph->m_tokenType == END_LINE) {
+ endOfParagraph++;
+ //cout << "ENCOUNTERED END OF PARA" << endl;
+ return endOfParagraph;
+ }
+
+ } else if (endOfParagraph->m_tokenType == COMMAND) {
+
+ if (isSectionIndicator(getBaseCommand(endOfParagraph->m_tokenString))) {
+ return endOfParagraph;
+ } else {
+ endOfParagraph++;
+ }
+
+ } else if (endOfParagraph->m_tokenType == PLAINSTRING) {
+ endOfParagraph++;
+ } else {
+ return tokList.end();
+ }
+ }
+
+ return tokList.end();
+}
+
+DoxygenParser::TokenListCIt DoxygenParser::getEndOfSection(const std::string &theCommand, const TokenList &tokList) {
+
+ TokenListCIt endOfParagraph = m_tokenListIt;
+
+ while (endOfParagraph != tokList.end()) {
+ if (endOfParagraph->m_tokenType == COMMAND) {
+ if (theCommand == endOfParagraph->m_tokenString)
+ return endOfParagraph;
+ else
+ endOfParagraph++;
+ } else if (endOfParagraph->m_tokenType == PLAINSTRING) {
+ endOfParagraph++;
+ } else if (endOfParagraph->m_tokenType == END_LINE) {
+ endOfParagraph++;
+ if (endOfParagraph->m_tokenType == END_LINE) {
+ endOfParagraph++;
+ return endOfParagraph;
+ }
+ }
+ }
+ return tokList.end();
+}
+
+DoxygenParser::TokenListCIt DoxygenParser::getEndCommand(const std::string &theCommand, const TokenList &tokList) {
+
+ TokenListCIt endOfCommand = m_tokenListIt;
+
+ while (endOfCommand != tokList.end()) {
+ endOfCommand++;
+ if ((*endOfCommand).m_tokenType == COMMAND) {
+ if (theCommand == (*endOfCommand).m_tokenString) {
+ return endOfCommand;
+ }
+ }
+ }
+ //End command not found
+ return tokList.end();
+}
+
+void DoxygenParser::skipEndOfLine() {
+ if (m_tokenListIt != m_tokenList.end()
+ && m_tokenListIt->m_tokenType == END_LINE) {
+ m_tokenListIt++;
+ }
+}
+
+void DoxygenParser::addSimpleCommand(const std::string &theCommand, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ doxyList.push_back(DoxygenEntity(theCommand));
+}
+
+void DoxygenParser::addCommandWord(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ if (isEndOfLine()) {
+ // handles cases when command is at the end of line (for example "\c\nreally"
+ skipWhitespaceTokens();
+ doxyList.push_back(DoxygenEntity("plainstd::endl"));
+ }
+ std::string name = getNextWord();
+ if (!name.empty()) {
+ DoxygenEntityList aNewList;
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ } else {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored.");
+ }
+}
+
+void DoxygenParser::addCommandLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ TokenListCIt endOfLine = getOneLine(tokList);
+ DoxygenEntityList aNewList = parse(endOfLine, tokList);
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ skipEndOfLine();
+}
+
+void DoxygenParser::addCommandParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ TokenListCIt endOfParagraph = getEndOfParagraph(tokList);
+ DoxygenEntityList aNewList;
+ aNewList = parse(endOfParagraph, tokList);
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+}
+
+void DoxygenParser::addCommandEndCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ TokenListCIt endCommand = getEndCommand("end" + theCommand, tokList);
+ if (endCommand == tokList.end()) {
+ printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: end" + theCommand + ".");
+ return;
+ }
+ DoxygenEntityList aNewList;
+ aNewList = parse(endCommand, tokList);
+ m_tokenListIt++;
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+}
+
+void DoxygenParser::addCommandWordParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ std::string name = getNextWord();
+
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored.");
+ return;
+ }
+ TokenListCIt endOfParagraph = getEndOfParagraph(tokList);
+ DoxygenEntityList aNewList;
+ aNewList = parse(endOfParagraph, tokList);
+ aNewList.push_front(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+}
+
+void DoxygenParser::addCommandWordLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string name = getNextWord();
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored.");
+ return;
+ }
+
+ TokenListCIt endOfLine = getOneLine(tokList);
+ DoxygenEntityList aNewList;
+ aNewList = parse(endOfLine, tokList);
+ aNewList.push_front(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ //else cout << "No line followed " << theCommand << " command. Not added" << endl;
+}
+
+void DoxygenParser::addCommandWordOWordOWord(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ std::string name = getNextWord();
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored.");
+ return;
+ }
+ std::string headerfile = getNextWord();
+ std::string headername = getNextWord();
+ DoxygenEntityList aNewList;
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ if (!headerfile.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", headerfile));
+ if (!headername.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", headername));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+}
+
+void DoxygenParser::addCommandOWord(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ std::string name = getNextWord();
+ DoxygenEntityList aNewList;
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+}
+
+void DoxygenParser::addCommandErrorThrow(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &) {
+
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": Unexpectedly encountered this command.");
+ m_tokenListIt = getOneLine(tokList);
+}
+
+void DoxygenParser::addCommandHtml(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ std::string htmlTagArgs = getNextToken();
+ doxyList.push_back(DoxygenEntity(theCommand, htmlTagArgs));
+}
+
+void DoxygenParser::addCommandHtmlEntity(const std::string &theCommand, const TokenList &, DoxygenEntityList &doxyList) {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ DoxygenEntityList aNewList;
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+}
+
+void DoxygenParser::addCommandUnique(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+
+ static std::map<std::string, std::string> endCommands;
+ DoxygenEntityList aNewList;
+ if (theCommand == "arg" || theCommand == "li") {
+ TokenListCIt endOfSection = getEndOfSection(theCommand, tokList);
+ DoxygenEntityList aNewList;
+ aNewList = parse(endOfSection, tokList);
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \xrefitem <key> "(heading)" "(std::list title)" {text}
+ else if (theCommand == "xrefitem") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string key = getNextWord();
+ if (key.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No key followed the command. Command ignored.");
+ return;
+ }
+ std::string heading = getNextWord();
+ if (key.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No heading followed the command. Command ignored.");
+ return;
+ }
+ std::string title = getNextWord();
+ if (title.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No title followed the command. Command ignored.");
+ return;
+ }
+ TokenListCIt endOfParagraph = getEndOfParagraph(tokList);
+ aNewList = parse(endOfParagraph, tokList);
+ aNewList.push_front(DoxygenEntity("plainstd::string", title));
+ aNewList.push_front(DoxygenEntity("plainstd::string", heading));
+ aNewList.push_front(DoxygenEntity("plainstd::string", key));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \ingroup (<groupname> [<groupname> <groupname>])
+ else if (theCommand == "ingroup") {
+ std::string name = getNextWord();
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ name = getNextWord();
+ if (!name.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ name = getNextWord();
+ if (!name.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \par [(paragraph title)] { paragraph }
+ else if (theCommand == "par") {
+ TokenListCIt endOfLine = getOneLine(tokList);
+ aNewList = parse(endOfLine, tokList);
+ DoxygenEntityList aNewList2;
+ TokenListCIt endOfParagraph = getEndOfParagraph(tokList);
+ aNewList2 = parse(endOfParagraph, tokList);
+ aNewList.splice(aNewList.end(), aNewList2);
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \headerfile <header-file> [<header-name>]
+ else if (theCommand == "headerfile") {
+ DoxygenEntityList aNewList;
+ std::string name = getNextWord();
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ name = getNextWord();
+ if (!name.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \overload [(function declaration)]
+ else if (theCommand == "overload") {
+ TokenListCIt endOfLine = getOneLine(tokList);
+ if (endOfLine != m_tokenListIt) {
+ DoxygenEntityList aNewList;
+ aNewList = parse(endOfLine, tokList);
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ } else
+ doxyList.push_back(DoxygenEntity(theCommand));
+ }
+ // \weakgroup <name> [(title)]
+ else if (theCommand == "weakgroup") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string name = getNextWord();
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored.");
+ return;
+ }
+ DoxygenEntityList aNewList;
+ TokenListCIt endOfLine = getOneLine(tokList);
+ if (endOfLine != m_tokenListIt) {
+ aNewList = parse(endOfLine, tokList);
+ }
+ aNewList.push_front(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \ref <name> ["(text)"]
+ else if (theCommand == "ref") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string name = getNextWord();
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No key followed the command. Command ignored.");
+ return;
+ }
+ DoxygenEntityList aNewList;
+ aNewList.push_front(DoxygenEntity("plainstd::string", name));
+ // TokenListCIt endOfLine = getOneLine(tokList);
+ // if (endOfLine != m_tokenListIt) {
+ // aNewList = parse(endOfLine, tokList);
+ //}
+ TokenListCIt tmpIt = m_tokenListIt;
+ std::string refTitle = getNextWord();
+ // If title is following the ref tag, it must be quoted. Otherwise
+ // doxy puts link on ref id.
+ if (refTitle.size() > 1 && refTitle[0] == '"') {
+ // remove quotes
+ refTitle = refTitle.substr(1, refTitle.size() - 2);
+ aNewList.push_back(DoxygenEntity("plainstd::string", refTitle));
+ } else {
+ // no quoted string is following, so we have to restore iterator
+ m_tokenListIt = tmpIt;
+ }
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \subpage <name> ["(text)"]
+ else if (theCommand == "subpage") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string name = getNextWord();
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No name followed the command. Command ignored.");
+ return;
+ }
+ std::string text = getNextWord();
+ aNewList.push_back(DoxygenEntity("plainstd::string", name));
+ if (!text.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", text));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \code ... \endcode
+ // \verbatim ... \endverbatim
+ // \dot dotcode \enddot
+ // \msc msccode \endmsc
+ // \f[ ... \f]
+ // \f{ ... \f}
+ // \f{env}{ ... \f}
+ // \f$ ... \f$
+ else if (getBaseCommand(theCommand) == "code" || theCommand == "verbatim"
+ || theCommand == "dot" || theCommand == "msc" || theCommand == "f[" || theCommand == "f{" || theCommand == "f$") {
+ if (!endCommands.size()) {
+ // fill in static table of end commands
+ endCommands["f["] = "f]";
+ endCommands["f{"] = "f}";
+ endCommands["f$"] = "f$";
+ }
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ std::string endCommand;
+ std::map<std::string, std::string>::iterator it;
+ it = endCommands.find(theCommand);
+ if (it != endCommands.end())
+ endCommand = it->second;
+ else
+ endCommand = "end" + getBaseCommand(theCommand);
+
+ std::string content = getStringTilEndCommand(endCommand, tokList);
+ aNewList.push_back(DoxygenEntity("plainstd::string", content));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \dotfile <file> ["caption"]
+ // \mscfile <file> ["caption"]
+ else if (theCommand == "dotfile" || theCommand == "mscfile") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string file = getNextWord();
+ if (file.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No file followed the command. Command ignored.");
+ return;
+ }
+ std::string caption = getNextWord();
+ aNewList.push_back(DoxygenEntity("plainstd::string", file));
+ if (!caption.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", caption));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \image <format> <file> ["caption"] [<sizeindication>=<size>]
+ else if (theCommand == "image") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string format = getNextWord();
+ if (format.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No format followed the command. Command ignored.");
+ return;
+ }
+ std::string file = getNextWord();
+ if (file.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No name followed the command. Command ignored.");
+ return;
+ }
+ std::string caption = getNextWord();
+ std::string size = getNextWord();
+
+ DoxygenEntityList aNewList;
+ aNewList.push_back(DoxygenEntity("plainstd::string", format));
+ aNewList.push_back(DoxygenEntity("plainstd::string", file));
+ if (!caption.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", caption));
+ if (!size.empty())
+ aNewList.push_back(DoxygenEntity("plainstd::string", size));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+ // \addtogroup <name> [(title)]
+ else if (theCommand == "addtogroup") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+ std::string name = getNextWord();
+ if (name.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": There should be at least one word following the command. Command ignored.");
+ return;
+ }
+ DoxygenEntityList aNewList;
+ TokenListCIt endOfLine = getOneLine(tokList);
+ if (endOfLine != m_tokenListIt) {
+ aNewList = parse(endOfLine, tokList);
+ }
+ aNewList.push_front(DoxygenEntity("plainstd::string", name));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ skipEndOfLine();
+ }
+ // \if <cond> [\else ...] [\elseif <cond> ...] \endif
+ else if (theCommand == "if" || theCommand == "ifnot" || theCommand == "else" || theCommand == "elseif") {
+ if (noisy)
+ cout << "Parsing " << theCommand << endl;
+
+ std::string cond;
+ bool skipEndif = false; // if true then we skip endif after parsing block of code
+ bool needsCond = (theCommand == "if" || theCommand == "ifnot" || theCommand == "elseif");
+ if (needsCond) {
+ cond = getNextWord();
+ if (cond.empty()) {
+ printListError(WARN_DOXYGEN_COMMAND_ERROR, "Error parsing Doxygen command " + theCommand + ": No word followed the command. Command ignored.");
+ return;
+ }
+ }
+
+ int nestedCounter = 1;
+ TokenListCIt endCommand = tokList.end();
+
+ // go through the commands and find closing endif or else or elseif
+ for (TokenListCIt it = m_tokenListIt; it != tokList.end(); it++) {
+ if (it->m_tokenType == COMMAND) {
+ if (it->m_tokenString == "if" || it->m_tokenString == "ifnot")
+ nestedCounter++;
+ else if (it->m_tokenString == "endif")
+ nestedCounter--;
+ if (nestedCounter == 1 && (it->m_tokenString == "else" || it->m_tokenString == "elseif")) { // else found
+ endCommand = it;
+ break;
+ }
+ if (nestedCounter == 0) { // endif found
+ endCommand = it;
+ skipEndif = true;
+ break;
+ }
+ }
+ }
+
+ if (endCommand == tokList.end()) {
+ printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: endif.");
+ return;
+ }
+
+ DoxygenEntityList aNewList;
+ aNewList = parse(endCommand, tokList);
+ if (skipEndif)
+ m_tokenListIt++;
+ if (needsCond)
+ aNewList.push_front(DoxygenEntity("plainstd::string", cond));
+ doxyList.push_back(DoxygenEntity(theCommand, aNewList));
+ }
+}
+
+void DoxygenParser::aliasCommand(const std::string &theCommand, const TokenList &/* tokList */ , DoxygenEntityList &doxyList) {
+ String *const alias = Getattr(m_node, ("feature:doxygen:alias:" + theCommand).c_str());
+ if (!alias)
+ return;
+
+ doxyList.push_back(DoxygenEntity("plainstd::string", Char(alias)));
+}
+
+String *DoxygenParser::getIgnoreFeature(const std::string &theCommand, const char *argument) const {
+ string feature_name = "feature:doxygen:ignore:" + theCommand;
+ if (argument) {
+ feature_name += ':';
+ feature_name += argument;
+ }
+
+ return Getattr(m_node, feature_name.c_str());
+}
+
+string DoxygenParser::getIgnoreFeatureEndCommand(const std::string &theCommand) const {
+ // We may be dealing either with a simple command or with the starting command
+ // of a block, as indicated by the value of "range" starting with "end".
+ string endCommand;
+ if (String *const range = getIgnoreFeature(theCommand, "range")) {
+ const char *const p = Char(range);
+ if (strncmp(p, "end", 3) == 0) {
+ if (p[3] == ':') {
+ // Normally the end command name follows after the colon.
+ endCommand = p + 4;
+ } else if (p[3] == '\0') {
+ // But it may be omitted in which case the default Doxygen convention of
+ // using "something"/"endsomething" is used.
+ endCommand = "end" + theCommand;
+ }
+ }
+ }
+
+ return endCommand;
+}
+
+void DoxygenParser::ignoreCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList) {
+ const string endCommand = getIgnoreFeatureEndCommand(theCommand);
+ if (!endCommand.empty()) {
+ TokenListCIt itEnd = getEndCommand(endCommand, tokList);
+ if (itEnd == tokList.end()) {
+ printListError(WARN_DOXYGEN_COMMAND_EXPECTED, "Expected Doxygen command: " + endCommand + ".");
+ return;
+ }
+ // If we ignore the command, also ignore any whitespace preceding it as we
+ // want to avoid having lines consisting of whitespace only or trailing
+ // whitespace in general (at least Python, with its pep8 tool, really
+ // doesn't like it).
+ if (!doxyList.empty()) {
+ DoxygenEntityList::iterator i = doxyList.end();
+ --i;
+ if (i->typeOfEntity == "plainstd::string" && i->data.find_first_not_of(" \t") == std::string::npos) {
+ doxyList.erase(i);
+ }
+ }
+ // Determine what to do with the part of the comment between the start and
+ // end commands: by default, we simply throw it away, but "contents"
+ // attribute may be used to change this.
+ if (String *const contents = getIgnoreFeature(theCommand, "contents")) {
+ // Currently only "parse" is supported but we may need to add "copy" to
+ // handle custom tags which contain text that is supposed to be copied
+ // verbatim in the future.
+ if (Strcmp(contents, "parse") == 0) {
+ DoxygenEntityList aNewList = parse(itEnd, tokList);
+ doxyList.splice(doxyList.end(), aNewList);
+ } else {
+ Swig_error(m_fileName.c_str(), m_fileLineNo, "Invalid \"doxygen:ignore\" feature \"contents\" attribute \"%s\".\n", Char(contents));
+ return;
+ }
+ }
+
+ m_tokenListIt = itEnd;
+ m_tokenListIt++;
+ } else if (String *const range = getIgnoreFeature(theCommand, "range")) {
+ // Currently we only support "line" but, in principle, we should also
+ // support "word" and "paragraph" for consistency with the built-in Doxygen
+ // commands which can have either of these three ranges (which are indicated
+ // using <word-arg>, (line-arg) and {para-arg} respectively in Doxygen
+ // documentation).
+ if (Strcmp(range, "line") == 0) {
+ // Consume everything until the end of line.
+ m_tokenListIt = getOneLine(tokList);
+ skipEndOfLine();
+ } else {
+ Swig_error(m_fileName.c_str(), m_fileLineNo, "Invalid \"doxygen:ignore\" feature \"range\" attribute \"%s\".\n", Char(range));
+ return;
+ }
+ }
+}
+
+void DoxygenParser::addCommand(const std::string &commandString, const TokenList &tokList, DoxygenEntityList &doxyList) {
+
+ string theCommand = stringToLower(commandString);
+
+ if (theCommand == "plainstd::string") {
+ string nextPhrase = getStringTilCommand(tokList);
+ if (noisy)
+ cout << "Parsing plain std::string :" << nextPhrase << endl;
+ doxyList.push_back(DoxygenEntity("plainstd::string", nextPhrase));
+ return;
+ }
+
+ switch (commandBelongs(commandString)) {
+ case SIMPLECOMMAND:
+ addSimpleCommand(theCommand, doxyList);
+ break;
+ case COMMANDWORD:
+ addCommandWord(theCommand, tokList, doxyList);
+ break;
+ case COMMANDLINE:
+ addCommandLine(theCommand, tokList, doxyList);
+ break;
+ case COMMANDPARAGRAPH:
+ addCommandParagraph(theCommand, tokList, doxyList);
+ break;
+ case COMMANDENDCOMMAND:
+ addCommandEndCommand(theCommand, tokList, doxyList);
+ break;
+ case COMMANDWORDPARAGRAPH:
+ addCommandWordParagraph(theCommand, tokList, doxyList);
+ break;
+ case COMMANDWORDLINE:
+ addCommandWordLine(theCommand, tokList, doxyList);
+ break;
+ case COMMANDWORDOWORDWORD:
+ addCommandWordOWordOWord(theCommand, tokList, doxyList);
+ break;
+ case COMMANDOWORD:
+ addCommandOWord(theCommand, tokList, doxyList);
+ break;
+ case COMMANDERRORTHROW:
+ addCommandErrorThrow(theCommand, tokList, doxyList);
+ break;
+ case COMMANDUNIQUE:
+ addCommandUnique(theCommand, tokList, doxyList);
+ break;
+ case COMMAND_HTML:
+ addCommandHtml(theCommand, tokList, doxyList);
+ break;
+ case COMMAND_HTML_ENTITY:
+ addCommandHtmlEntity(theCommand, tokList, doxyList);
+ break;
+ case COMMAND_ALIAS:
+ aliasCommand(commandString, tokList, doxyList);
+ break;
+ case COMMAND_IGNORE:
+ ignoreCommand(commandString, tokList, doxyList);
+ break;
+ case NONE:
+ case END_LINE:
+ case PARAGRAPH_END:
+ case PLAINSTRING:
+ case COMMAND:
+ // TODO: Ensure that these values either are correctly ignored here or can't happen.
+ break;
+ }
+}
+
+/**
+ * This method converts TokenList to DoxygenEntryList.
+ */
+DoxygenEntityList DoxygenParser::parse(TokenListCIt endParsingIndex, const TokenList &tokList, bool root) {
+ // if we are root, than any strings should be added as 'partofdescription', else as 'plainstd::string'
+ std::string currPlainstringCommandType = root ? "partofdescription" : "plainstd::string";
+ DoxygenEntityList aNewList;
+
+ // Less than check (instead of not equal) is a safeguard in case the
+ // iterator is incremented past the end
+ while (m_tokenListIt < endParsingIndex) {
+
+ Token currToken = *m_tokenListIt;
+
+ if (noisy)
+ cout << "Parsing for phrase starting in:" << currToken.toString() << endl;
+
+ if (currToken.m_tokenType == END_LINE) {
+ aNewList.push_back(DoxygenEntity("plainstd::endl"));
+ m_tokenListIt++;
+ } else if (currToken.m_tokenType == COMMAND) {
+ m_tokenListIt++;
+ addCommand(currToken.m_tokenString, tokList, aNewList);
+ } else if (currToken.m_tokenType == PLAINSTRING) {
+ addCommand(currPlainstringCommandType, tokList, aNewList);
+ }
+
+ // If addCommand above misbehaves, it can move the iterator past endParsingIndex
+ if (m_tokenListIt > endParsingIndex)
+ printListError(WARN_DOXYGEN_UNEXPECTED_ITERATOR_VALUE, "Unexpected iterator value in DoxygenParser::parse");
+
+ if (endParsingIndex != tokList.end() && m_tokenListIt == tokList.end()) {
+ // this could happen if we can't reach the original endParsingIndex
+ printListError(WARN_DOXYGEN_UNEXPECTED_END_OF_COMMENT, "Unexpected end of Doxygen comment encountered.");
+ break;
+ }
+ }
+ return aNewList;
+}
+
+DoxygenEntityList DoxygenParser::createTree(Node *node, String *documentation) {
+ m_node = node;
+
+ tokenizeDoxygenComment(Char(documentation), Char(Getfile(documentation)), Getline(documentation));
+
+ if (noisy) {
+ cout << "---TOKEN LIST---" << endl;
+ printList();
+ }
+
+ DoxygenEntityList rootList = parse(m_tokenList.end(), m_tokenList, true);
+
+ if (noisy) {
+ cout << "PARSED LIST" << endl;
+ printTree(rootList);
+ }
+ return rootList;
+}
+
+/*
+ * Splits 'text' on 'separator' chars. Separator chars are not part of the
+ * strings.
+ */
+DoxygenParser::StringVector DoxygenParser::split(const std::string &text, char separator) {
+ StringVector lines;
+ size_t prevPos = 0, pos = 0;
+
+ while (pos < string::npos) {
+ pos = text.find(separator, prevPos);
+ lines.push_back(text.substr(prevPos, pos - prevPos));
+ prevPos = pos + 1;
+ }
+
+ return lines;
+}
+
+/*
+ * Returns true, if 'c' is one of doxygen comment block start
+ * characters: *, /, or !
+ */
+bool DoxygenParser::isStartOfDoxyCommentChar(char c) {
+ return (strchr("*/!", c) != NULL);
+}
+
+/*
+ * Adds token with Doxygen command to token list, but only if command is one of
+ * Doxygen commands. In that case true is returned. If the command is not
+ * recognized as a doxygen command, it is ignored and false is returned.
+ */
+bool DoxygenParser::addDoxyCommand(DoxygenParser::TokenList &tokList, const std::string &cmd) {
+ if (commandBelongs(cmd) != NONE) {
+ tokList.push_back(Token(COMMAND, cmd));
+ return true;
+ } else {
+ if (cmd.empty()) {
+ // This actually indicates a bug in the code in this file, as this
+ // function shouldn't be called at all in this case.
+ printListError(WARN_DOXYGEN_UNKNOWN_COMMAND, "Unexpected empty Doxygen command.");
+ return false;
+ }
+
+ // This function is called for the special Doxygen commands, but also for
+ // HTML commands (or anything that looks like them, actually) and entities.
+ // We don't recognize all of those, so just ignore them and pass them
+ // through, but warn about unknown Doxygen commands as ignoring them will
+ // often result in wrong output being generated.
+ const char ch = *cmd.begin();
+ if (ch != '<' && ch != '&') {
+ // Before calling printListError() we must ensure that m_tokenListIt used
+ // by it is valid.
+ const TokenListCIt itSave = m_tokenListIt;
+ m_tokenListIt = m_tokenList.end();
+
+ printListError(WARN_DOXYGEN_UNKNOWN_COMMAND, "Unknown Doxygen command: " + cmd + ".");
+
+ m_tokenListIt = itSave;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * This method copies comment text to output as it is - no processing is
+ * done, Doxygen commands are ignored. It is used for commands \verbatim,
+ * \htmlonly, \f$, \f[, and \f{.
+ */
+size_t DoxygenParser::processVerbatimText(size_t pos, const std::string &line) {
+ if (line[pos] == '\\' || line[pos] == '@') { // check for end commands
+
+ pos++;
+ size_t endOfWordPos = line.find_first_not_of(DOXYGEN_WORD_CHARS, pos);
+ string cmd = line.substr(pos, endOfWordPos - pos);
+
+ if (cmd == CMD_END_HTML_ONLY || cmd == CMD_END_VERBATIM || cmd == CMD_END_LATEX_1 || cmd == CMD_END_LATEX_2 || cmd == CMD_END_LATEX_3 || cmd == CMD_END_CODE) {
+
+ m_isVerbatimText = false;
+ addDoxyCommand(m_tokenList, cmd);
+
+ } else {
+
+ m_tokenList.push_back(Token(PLAINSTRING,
+ // include '\' or '@'
+ line.substr(pos - 1, endOfWordPos - pos + 1)));
+ }
+
+ pos = endOfWordPos;
+
+ } else {
+
+ // whitespaces are stored as plain strings
+ size_t startOfPossibleEndCmd = line.find_first_of("\\@", pos);
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, startOfPossibleEndCmd - pos)));
+ pos = startOfPossibleEndCmd;
+ }
+
+ return pos;
+}
+
+/*
+ * Processes doxy commands for escaped characters: \$ \@ \\ \& \~ \< \> \# \% \" \. \::
+ * Handling this separately supports documentation text like \@someText.
+ */
+bool DoxygenParser::processEscapedChars(size_t &pos, const std::string &line) {
+ if ((pos + 1) < line.size()) {
+
+ // \ and @ with trailing whitespace or quoted get to output as plain string
+ string whitespaces = " '\t\n";
+ if (whitespaces.find(line[pos + 1]) != string::npos) {
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, 1)));
+ pos++;
+ return true;
+ }
+ // these chars can be escaped for doxygen
+ string escapedChars = "$@\\&~<>#%\".";
+ if (escapedChars.find(line[pos + 1]) != string::npos) {
+
+ addDoxyCommand(m_tokenList, line.substr(pos + 1, 1));
+ pos += 2;
+ return true;
+
+ } else if ((pos + 2) < line.size() && line[pos + 1] == ':' && line[pos + 2] == ':') {
+
+ // add command \:: - handling this separately supports documentation
+ // text like \::someText
+ addDoxyCommand(m_tokenList, line.substr(pos + 1, 2));
+ pos += 3;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Processes word doxygen commands, like \arg, \c, \b, \return, ...
+ */
+void DoxygenParser::processWordCommands(size_t &pos, const std::string &line) {
+ pos++;
+ size_t endOfWordPos = getEndOfWordCommand(line, pos);
+
+ string cmd = line.substr(pos, endOfWordPos - pos);
+ if (cmd.empty()) {
+ // This was a bare backslash, just ignore it.
+ return;
+ }
+
+ addDoxyCommand(m_tokenList, cmd);
+
+ // A flag for whether we want to skip leading spaces after the command
+ bool skipLeadingSpace = true;
+
+ if (cmd == CMD_HTML_ONLY || cmd == CMD_VERBATIM || cmd == CMD_LATEX_1 || cmd == CMD_LATEX_2 || cmd == CMD_LATEX_3 || getBaseCommand(cmd) == CMD_CODE) {
+
+ m_isVerbatimText = true;
+
+ // Skipping leading space is necessary with inline \code command,
+ // and it won't hurt anything for block \code (TODO: are the other
+ // commands also compatible with skip leading space? If so, just
+ // do it every time.)
+ if (getBaseCommand(cmd) == CMD_CODE) skipLeadingSpace = true;
+ else skipLeadingSpace = false;
+ } else if (cmd.substr(0,3) == "end") {
+ // If processing an "end" command such as "endlink", don't skip
+ // the space before the next string
+ skipLeadingSpace = false;
+ }
+
+ if (skipLeadingSpace) {
+ // skip any possible spaces after command, because some commands have parameters,
+ // and spaces between command and parameter must be ignored.
+ if (endOfWordPos != string::npos) {
+ endOfWordPos = line.find_first_not_of(" \t", endOfWordPos);
+ }
+ }
+
+ pos = endOfWordPos;
+}
+
+void DoxygenParser::processHtmlTags(size_t &pos, const std::string &line) {
+ bool isEndHtmlTag = false;
+ pos++;
+ if (line.size() > pos && line[pos] == '/') {
+ isEndHtmlTag = true;
+ pos++;
+ }
+
+ size_t endHtmlPos = line.find_first_of("\t >", pos);
+
+ string cmd = line.substr(pos, endHtmlPos - pos);
+ pos = endHtmlPos;
+
+ // prepend '<' to distinguish HTML tags from doxygen commands
+ if (!cmd.empty() && addDoxyCommand(m_tokenList, '<' + cmd)) {
+ // it is a valid HTML command
+ if (pos == string::npos) {
+ pos = line.size();
+ }
+ if (line[pos] != '>') {
+ // it should be HTML tag with args,
+ // for example <A ...>, <IMG ...>, ...
+ if (isEndHtmlTag) {
+ m_tokenListIt = m_tokenList.end();
+ printListError(WARN_DOXYGEN_HTML_ERROR, "Doxygen HTML error for tag " + cmd + ": Illegal end HTML tag without greater-than ('>') found.");
+ }
+
+ endHtmlPos = line.find('>', pos);
+ if (endHtmlPos == string::npos) {
+ m_tokenListIt = m_tokenList.end();
+ printListError(WARN_DOXYGEN_HTML_ERROR, "Doxygen HTML error for tag " + cmd + ": HTML tag without greater-than ('>') found.");
+ }
+ // add args of HTML command, like link URL, image URL, ...
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, endHtmlPos - pos)));
+ pos = endHtmlPos;
+ } else {
+ if (isEndHtmlTag) {
+ m_tokenList.push_back(Token(PLAINSTRING, END_HTML_TAG_MARK));
+ } else {
+ // it is a simple tag, so push empty string
+ m_tokenList.push_back(Token(PLAINSTRING, ""));
+ }
+ }
+
+ if (pos < line.size()) {
+ pos++; // skip '>'
+ }
+ } else {
+ // the command is not HTML supported by Doxygen, < and > will be
+ // replaced by HTML entities &lt; and &gt; respectively,
+ addDoxyCommand(m_tokenList, "&lt");
+ m_tokenList.push_back(Token(PLAINSTRING, cmd));
+ }
+}
+
+void DoxygenParser::processHtmlEntities(size_t &pos, const std::string &line) {
+ size_t endOfWordPos = line.find_first_not_of("abcdefghijklmnopqrstuvwxyz", pos + 1);
+
+ if (endOfWordPos != string::npos) {
+
+ if (line[endOfWordPos] == ';' && (endOfWordPos - pos) > 1) {
+ // if entity is not recognized by Doxygen (not in the list of
+ // commands) nothing is added (here and in Doxygen).
+ addDoxyCommand(m_tokenList, line.substr(pos, endOfWordPos - pos));
+ endOfWordPos++; // skip ';'
+ } else {
+ // it is not an entity - add entity for ampersand and the rest of string
+ addDoxyCommand(m_tokenList, "&amp");
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos + 1, endOfWordPos - pos - 1)));
+ }
+ }
+ pos = endOfWordPos;
+}
+
+/*
+ * This method processes normal comment, which has to be tokenized.
+ */
+size_t DoxygenParser::processNormalComment(size_t pos, const std::string &line) {
+ switch (line[pos]) {
+ case '\\':
+ case '@':
+ if (processEscapedChars(pos, line)) {
+ break;
+ }
+ // handle word commands \arg, \c, \return, ... and \f[, \f$, ... commands
+ processWordCommands(pos, line);
+ break;
+
+ case ' ': // whitespace
+ case '\t':
+ {
+ // whitespaces are stored as plain strings
+ size_t startOfNextWordPos = line.find_first_not_of(" \t", pos + 1);
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, startOfNextWordPos - pos)));
+ pos = startOfNextWordPos;
+ }
+ break;
+
+ case '<':
+ processHtmlTags(pos, line);
+ break;
+ case '>': // this char is detected here only when it is not part of HTML tag
+ addDoxyCommand(m_tokenList, "&gt");
+ pos++;
+ break;
+ case '&':
+ processHtmlEntities(pos, line);
+ break;
+ case '"':
+ m_isInQuotedString = true;
+ m_tokenList.push_back(Token(PLAINSTRING, "\""));
+ pos++;
+ break;
+ default:
+ m_tokenListIt = m_tokenList.end();
+ printListError(WARN_DOXYGEN_UNKNOWN_CHARACTER, std::string("Unknown special character in Doxygen comment: ") + line[pos] + ".");
+ }
+
+ return pos;
+}
+
+/*
+ * This is the main method, which tokenizes Doxygen comment to words and
+ * doxygen commands.
+ */
+void DoxygenParser::tokenizeDoxygenComment(const std::string &doxygenComment, const std::string &fileName, int fileLine) {
+ m_isVerbatimText = false;
+ m_isInQuotedString = false;
+ m_tokenList.clear();
+ m_fileLineNo = fileLine;
+ m_fileName = fileName;
+
+ StringVector lines = split(doxygenComment, '\n');
+
+ // remove trailing spaces, because they cause additional new line at the end
+ // comment, which is wrong, because these spaces are space preceding
+ // end of comment : ' */'
+ if (!doxygenComment.empty() && doxygenComment[doxygenComment.size() - 1] == ' ') {
+
+ string lastLine = lines[lines.size() - 1];
+
+ if (trim(lastLine).empty()) {
+ lines.pop_back(); // remove trailing empty line
+ }
+ }
+
+ for (StringVectorCIt it = lines.begin(); it != lines.end(); it++) {
+ const string &line = *it;
+ size_t pos = line.find_first_not_of(" \t");
+
+ if (pos == string::npos) {
+ m_tokenList.push_back(Token(END_LINE, "\n"));
+ continue;
+ }
+ // skip sequences of '*', '/', and '!' of any length
+ bool isStartOfCommentLineCharFound = false;
+ while (pos < line.size() && isStartOfDoxyCommentChar(line[pos])) {
+ pos++;
+ isStartOfCommentLineCharFound = true;
+ }
+
+ if (pos == line.size()) {
+ m_tokenList.push_back(Token(END_LINE, "\n"));
+ continue;
+ }
+ // if 'isStartOfCommentLineCharFound' then preserve leading spaces, so
+ // ' * comment' gets translated to ' * comment', not ' * comment'
+ // This is important to keep formatting for comments translated to Python.
+ if (isStartOfCommentLineCharFound && line[pos] == ' ') {
+ pos++; // points to char after ' * '
+ if (pos == line.size()) {
+ m_tokenList.push_back(Token(END_LINE, "\n"));
+ continue;
+ }
+ }
+ // line[pos] may be ' \t' or start of word, it there was no '*', '/' or '!'
+ // at beginning of the line. Make sure it points to start of the first word
+ // in the line.
+ if (isStartOfCommentLineCharFound) {
+ size_t firstWordPos = line.find_first_not_of(" \t", pos);
+ if (firstWordPos == string::npos) {
+ m_tokenList.push_back(Token(END_LINE, "\n"));
+ continue;
+ }
+
+ if (firstWordPos > pos) {
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, firstWordPos - pos)));
+ pos = firstWordPos;
+ }
+ } else {
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(0, pos)));
+ }
+
+ while (pos != string::npos) {
+ // find the end of the word
+ size_t doxyCmdOrHtmlTagPos = line.find_first_of("\\@<>&\" \t", pos);
+ if (doxyCmdOrHtmlTagPos != pos) {
+ // plain text found
+ // if the last char is punctuation, make it a separate word, otherwise
+ // it may be included with word also when not appropriate, for example:
+ // colors are \b red, green, and blue --> colors are <b>red,</b> green, and blue
+ // instead of (comma not bold):
+ // colors are \b red, green, and blue --> colors are <b>red</b>, green, and blue
+ // In Python it looks even worse:
+ // colors are \b red, green, and blue --> colors are 'red,' green, and blue
+ string text = line.substr(pos, doxyCmdOrHtmlTagPos - pos);
+ string punctuations(".,:");
+ size_t textSize = text.size();
+
+ if (!text.empty()
+ && punctuations.find(text[text.size() - 1]) != string::npos &&
+ // but do not break ellipsis (...)
+ !(textSize > 1 && text[textSize - 2] == '.')) {
+ m_tokenList.push_back(Token(PLAINSTRING, text.substr(0, text.size() - 1)));
+ m_tokenList.push_back(Token(PLAINSTRING, text.substr(text.size() - 1)));
+ } else {
+ m_tokenList.push_back(Token(PLAINSTRING, text));
+ }
+ }
+
+ pos = doxyCmdOrHtmlTagPos;
+ if (pos != string::npos) {
+ if (m_isVerbatimText) {
+ pos = processVerbatimText(pos, line);
+
+ } else if (m_isInQuotedString) {
+
+ if (line[pos] == '"') {
+ m_isInQuotedString = false;
+ }
+ m_tokenList.push_back(Token(PLAINSTRING, line.substr(pos, 1)));
+ pos++;
+
+ } else {
+ pos = processNormalComment(pos, line);
+ }
+ }
+ }
+ m_tokenList.push_back(Token(END_LINE, "\n")); // add when pos == npos - end of line
+ }
+
+ m_tokenListIt = m_tokenList.begin();
+}
+
+void DoxygenParser::printList() {
+
+ int tokNo = 0;
+ for (TokenListCIt it = m_tokenList.begin(); it != m_tokenList.end(); it++, tokNo++) {
+
+ cout << it->toString() << ' ';
+
+ if ((tokNo % TOKENSPERLINE) == 0) {
+ cout << endl;
+ }
+ }
+}
+
+void DoxygenParser::printListError(int warningType, const std::string &message) {
+ int curLine = m_fileLineNo;
+ for (TokenListCIt it = m_tokenList.begin(); it != m_tokenListIt; it++) {
+ if (it->m_tokenType == END_LINE) {
+ curLine++;
+ }
+ }
+
+ Swig_warning(warningType, m_fileName.c_str(), curLine, "%s\n", message.c_str());
+}
diff --git a/contrib/tools/swig/Source/Doxygen/doxyparser.h b/contrib/tools/swig/Source/Doxygen/doxyparser.h
new file mode 100644
index 00000000000..a60446517bf
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxyparser.h
@@ -0,0 +1,377 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxyparser.h
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DOXYPARSER_H
+#define SWIG_DOXYPARSER_H
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+#include <set>
+
+#include "swig.h"
+
+#include "doxyentity.h"
+
+// Utility function to return the base part of a command that may
+// include options, e.g. param[in] -> param
+std::string getBaseCommand(const std::string &cmd);
+
+
+class DoxygenParser {
+private:
+
+ enum DoxyCommandEnum {
+ NONE = -1,
+ SIMPLECOMMAND,
+ COMMANDWORD,
+ COMMANDLINE,
+ COMMANDPARAGRAPH,
+ COMMANDENDCOMMAND,
+ COMMANDWORDPARAGRAPH,
+ COMMANDWORDLINE,
+ COMMANDWORDOWORDWORD,
+ COMMANDOWORD,
+ COMMANDERRORTHROW,
+ COMMANDUNIQUE,
+ COMMAND_HTML,
+ COMMAND_HTML_ENTITY,
+ COMMAND_ALIAS,
+ COMMAND_IGNORE,
+ END_LINE,
+ PARAGRAPH_END,
+ PLAINSTRING,
+ COMMAND
+ };
+
+
+ /** This class contains parts of Doxygen comment as a token. */
+ class Token {
+ public:
+ DoxyCommandEnum m_tokenType;
+ std::string m_tokenString; /* the data , such as param for @param */
+
+ Token(DoxyCommandEnum tType, std::string tString) : m_tokenType(tType), m_tokenString(tString) {
+ }
+
+ std::string toString() const {
+ switch (m_tokenType) {
+ case END_LINE:
+ return "{END OF LINE}";
+ case PARAGRAPH_END:
+ return "{END OF PARAGRAPH}";
+ case PLAINSTRING:
+ return "{PLAINSTRING :" + m_tokenString + "}";
+ case COMMAND:
+ return "{COMMAND : " + m_tokenString + "}";
+ default:
+ return "";
+ }
+ }
+ };
+
+
+ typedef std::vector<Token> TokenList;
+ typedef TokenList::const_iterator TokenListCIt;
+ typedef TokenList::iterator TokenListIt;
+
+ TokenList m_tokenList;
+ TokenListCIt m_tokenListIt;
+
+ typedef std::map<std::string, DoxyCommandEnum> DoxyCommandsMap;
+ typedef DoxyCommandsMap::iterator DoxyCommandsMapIt;
+
+ /*
+ * Map of Doxygen commands to determine if a string is a
+ * command and how it needs to be parsed
+ */
+ static DoxyCommandsMap doxygenCommands;
+ static std::set<std::string> doxygenSectionIndicators;
+
+ bool m_isVerbatimText; // used to handle \htmlonly and \verbatim commands
+ bool m_isInQuotedString;
+
+ Node *m_node;
+ std::string m_fileName;
+ int m_fileLineNo;
+
+ /*
+ * Return the end command for a command appearing in "ignore" feature or empty
+ * string if this is a simple command and not a block one.
+ */
+ std::string getIgnoreFeatureEndCommand(const std::string &theCommand) const;
+
+ /*
+ * Helper for getting the value of doxygen:ignore feature or its argument.
+ */
+ String *getIgnoreFeature(const std::string &theCommand, const char *argument = NULL) const;
+
+ /*
+ * Whether to print lots of debug info during parsing
+ */
+ bool noisy;
+
+ /*
+ *Changes a std::string to all lower case
+ */
+ std::string stringToLower(const std::string &stringToConvert);
+
+ /*
+ * isSectionIndicator returns a boolean if the command is a section indicator
+ * This is a helper method for finding the end of a paragraph
+ * by Doxygen's terms
+ */
+ bool isSectionIndicator(const std::string &smallString);
+ /*
+ * Determines how a command should be handled (what group it belongs to
+ * for parsing rules
+ */
+ DoxyCommandEnum commandBelongs(const std::string &theCommand);
+
+ /*
+ *prints the parse tree
+ */
+ void printTree(const std::list<DoxygenEntity> &rootList);
+
+ /**
+ * Returns true if the next token is end of line token. This is important
+ * when single word commands like \c are at the end of line.
+ */
+ bool isEndOfLine();
+
+ /**
+ * Skips spaces, tabs, and end of line tokens.
+ */
+ void skipWhitespaceTokens();
+
+ /**
+ * Removes all spaces and tabs from beginning end end of string.
+ */
+ std::string trim(const std::string &text);
+
+ /*
+ * Returns string of the next token if the next token is PLAINSTRING. Returns
+ * empty string otherwise.
+ */
+ std::string getNextToken();
+
+ /*
+ * Returns the next word ON THE CURRENT LINE ONLY
+ * if a new line is encountered, returns a blank std::string.
+ * Updates the iterator if successful.
+ */
+ std::string getNextWord();
+
+ /*
+ * Returns the next word, which is not necessarily on the same line.
+ * Updates the iterator if successful.
+ */
+ std::string getNextWordInComment();
+
+ /*
+ * Returns the location of the end of the line as
+ * an iterator.
+ */
+ TokenListCIt getOneLine(const TokenList &tokList);
+
+ /*
+ * Returns a properly formatted std::string
+ * up til ANY command or end of line is encountered.
+ */
+ std::string getStringTilCommand(const TokenList &tokList);
+
+ /*
+ * Returns a properly formatted std::string
+ * up til the command specified is encountered
+ */
+ //TODO check that this behaves properly for formulas
+ std::string getStringTilEndCommand(const std::string &theCommand, const TokenList &tokList);
+
+ /*
+ * Returns the end of a Paragraph as an iterator-
+ * Paragraph is defined in Doxygen to be a paragraph of text
+ * separated by either a structural command or a blank line
+ */
+ TokenListCIt getEndOfParagraph(const TokenList &tokList);
+
+ /*
+ * Returns the end of a section, defined as the first blank line OR first
+ * encounter of the same command. Example of this behaviour is \arg.
+ * If no end is encountered, returns the last token of the std::list.
+ */
+ TokenListCIt getEndOfSection(const std::string &theCommand, const TokenList &tokList);
+
+ /*
+ * This method is for returning the end of a specific form of doxygen command
+ * that begins with a \command and ends in \endcommand
+ * such as \code and \endcode. The proper usage is
+ * progressTilEndCommand("endcode", tokenList);
+ * If the end is never encountered, it returns the end of the std::list.
+ */
+ TokenListCIt getEndCommand(const std::string &theCommand, const TokenList &tokList);
+ /*
+ * A special method for commands such as \arg that end at the end of a
+ * paragraph OR when another \arg is encountered
+ //TODO getTilAnyCommand
+ TokenListCIt getTilAnyCommand(const std::string &theCommand, const TokenList &tokList);
+ */
+
+ /**
+ * This methods skips end of line token, if it is the next token to be
+ * processed. It is called with comment commands which have args till the
+ * end of line, such as 'addtogroup' or 'addindex'.
+ * It is up to translator to specific language to decide whether
+ * to insert eol or not. For example, if a command is ignored in target
+ * language, new lines may make formatting ugly (Python).
+ */
+ void skipEndOfLine();
+
+ /*
+ * Method for Adding a Simple Command
+ * Format: @command
+ * Plain commands, such as newline etc, they contain no other data
+ * \n \\ \@ \& \$ \# \< \> \% \{ \}
+ */
+ void addSimpleCommand(const std::string &theCommand, DoxygenEntityList &doxyList);
+ /*
+ * CommandWord
+ * Format: @command <word>
+ * Commands with a single WORD after then such as @b
+ * "a", "b", "c", "e", "em", "p", "def", "enum", "example", "package",
+ * "relates", "namespace", "relatesalso","anchor", "dontinclude", "include",
+ * "includelineno"
+ */
+ void addCommandWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * CommandLine
+ * Format: @command (line)
+ * Commands with a single LINE after then such as @var
+ * "addindex", "fn", "name", "line", "var", "skipline", "typedef", "skip",
+ * "until", "property"
+ */
+ void addCommandLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * CommandParagraph
+ * Format: @command {paragraph}
+ * Commands with a single paragraph after then such as @return
+ * "return", "remarks", "since", "test", "sa", "see", "pre", "post",
+ * "details", "invariant", "deprecated", "date", "note", "warning",
+ * "version", "todo", "bug", "attention", "brief", "arg", "author"
+ */
+ void addCommandParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * Command EndCommand
+ * Format: @command and ends at @endcommand
+ * Commands that take in a block of text such as @code:
+ * "code", "dot", "msc", "f$", "f[", "f{environment}{", "htmlonly",
+ * "latexonly", "manonly", "verbatim", "xmlonly", "cond", "if", "ifnot",
+ * "link"
+ * Returns 1 if success, 0 if the endcommand is never encountered.
+ */
+ void addCommandEndCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * CommandWordParagraph
+ * Format: @command <word> {paragraph}
+ * Commands such as param
+ * "param", "tparam", "throw", "throws", "retval", "exception"
+ */
+ void addCommandWordParagraph(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * CommandWordLine
+ * Format: @command <word> (line)
+ * Commands such as param
+ * "page", "subsection", "subsubsection", "section", "paragraph", "defgroup"
+ */
+ void addCommandWordLine(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * Command Word Optional Word Optional Word
+ * Format: @command <word> [<header-file>] [<header-name>]
+ * Commands such as class
+ * "category", "class", "protocol", "interface", "struct", "union"
+ */
+ void addCommandWordOWordOWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+ /*
+ * Command Optional Word
+ * Format: @command [<word>]
+ * Commands such as dir
+ * "dir", "file", "cond"
+ */
+ void addCommandOWord(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ /*
+ * Commands that should not be encountered (such as PHP only)
+ * goes til the end of line then returns
+ */
+ void addCommandErrorThrow(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ void addCommandHtml(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ void addCommandHtmlEntity(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ /*
+ *Adds the unique commands- different process for each unique command
+ */
+ void addCommandUnique(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ /*
+ * Replace the given command with its predefined alias expansion.
+ */
+ void aliasCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ /*
+ * Simply ignore the given command, possibly with the word following it or
+ * until the matching end command.
+ */
+ void ignoreCommand(const std::string &theCommand, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ /*
+ * The actual "meat" of the doxygen parser. Calls the correct addCommand...()
+ * function.
+ */
+ void addCommand(const std::string &commandString, const TokenList &tokList, DoxygenEntityList &doxyList);
+
+ DoxygenEntityList parse(TokenListCIt endParsingIndex, const TokenList &tokList, bool root = false);
+
+ /*
+ * Fill static doxygenCommands and sectionIndicators containers
+ */
+ void fillTables();
+
+ /** Processes comment when \htmlonly and \verbatim commands are encountered. */
+ size_t processVerbatimText(size_t pos, const std::string &line);
+
+ bool processEscapedChars(size_t &pos, const std::string &line);
+ void processWordCommands(size_t &pos, const std::string &line);
+ void processHtmlTags(size_t &pos, const std::string &line);
+ void processHtmlEntities(size_t &pos, const std::string &line);
+
+
+ /** Processes comment outside \htmlonly and \verbatim commands. */
+ size_t processNormalComment(size_t pos, const std::string &line);
+
+ void tokenizeDoxygenComment(const std::string &doxygenComment, const std::string &fileName, int fileLine);
+ void printList();
+ void printListError(int warningType, const std::string &message);
+
+ typedef std::vector<std::string> StringVector;
+ typedef StringVector::const_iterator StringVectorCIt;
+
+ StringVector split(const std::string &text, char separator);
+ bool isStartOfDoxyCommentChar(char c);
+ bool addDoxyCommand(DoxygenParser::TokenList &tokList, const std::string &cmd);
+
+public:
+ DoxygenParser(bool noisy = false);
+ virtual ~DoxygenParser();
+ DoxygenEntityList createTree(Node *node, String *documentation);
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Doxygen/doxytranslator.cxx b/contrib/tools/swig/Source/Doxygen/doxytranslator.cxx
new file mode 100644
index 00000000000..a638717eca1
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxytranslator.cxx
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxytranslator.cxx
+ *
+ * Module to return documentation for nodes formatted for various documentation
+ * systems.
+ * ----------------------------------------------------------------------------- */
+
+#include "doxytranslator.h"
+
+DoxygenTranslator::DoxygenTranslator(int flags) : m_flags(flags), parser((flags &debug_parser) != 0) {
+}
+
+
+DoxygenTranslator::~DoxygenTranslator() {
+}
+
+
+bool DoxygenTranslator::hasDocumentation(Node *node) {
+ return getDoxygenComment(node) != NULL;
+}
+
+
+String *DoxygenTranslator::getDoxygenComment(Node *node) {
+ return Getattr(node, "doxygen");
+}
+
+/**
+ * Indent all lines in the comment by given indentation string
+ */
+void DoxygenTranslator::extraIndentation(String *comment, const_String_or_char_ptr indentationString) {
+ if (indentationString || Len(indentationString) > 0) {
+ int len = Len(comment);
+ bool trailing_newline = len > 0 && *(Char(comment) + len - 1) == '\n';
+ Insert(comment, 0, indentationString);
+ String *replace = NewStringf("\n%s", indentationString);
+ Replaceall(comment, "\n", replace);
+ if (trailing_newline) {
+ len = Len(comment);
+ Delslice(comment, len - 2, len); // Remove added trailing spaces on last line
+ }
+ Delete(replace);
+ }
+}
+
+String *DoxygenTranslator::getDocumentation(Node *node, const_String_or_char_ptr indentationString) {
+
+ if (!hasDocumentation(node)) {
+ return NewString("");
+ }
+
+ String *documentation = makeDocumentation(node);
+ extraIndentation(documentation, indentationString);
+ return documentation;
+}
+
+
+void DoxygenTranslator::printTree(const DoxygenEntityList &entityList) {
+
+ for (DoxygenEntityListCIt p = entityList.begin(); p != entityList.end(); p++) {
+ p->printEntity(0);
+ }
+}
diff --git a/contrib/tools/swig/Source/Doxygen/doxytranslator.h b/contrib/tools/swig/Source/Doxygen/doxytranslator.h
new file mode 100644
index 00000000000..f0d3b1b0607
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/doxytranslator.h
@@ -0,0 +1,90 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * doxytranslator.h
+ *
+ * Module to return documentation for nodes formatted for various documentation
+ * systems.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_DOXYTRANSLATOR_H
+#define SWIG_DOXYTRANSLATOR_H
+
+#include "swig.h"
+#include "doxyentity.h"
+#include "doxyparser.h"
+#include <list>
+#include <string>
+
+
+/*
+ * This is a base class for translator classes. It defines the basic interface
+ * for translators, which convert Doxygen comments into alternative formats for
+ * target languages.
+ */
+class DoxygenTranslator {
+public:
+ /*
+ * Bit flags for the translator ctor.
+ *
+ * Derived classes may define additional flags.
+ */
+ enum {
+ // Use DoxygenParser in "noisy" mode.
+ debug_parser = 1,
+
+ // Output results of translating Doxygen comments.
+ debug_translator = 2
+ };
+
+ /*
+ * Constructor
+ */
+ DoxygenTranslator(int flags = 0);
+
+ /*
+ * Virtual destructor.
+ */
+ virtual ~DoxygenTranslator();
+
+ /*
+ * Return the documentation for a given node formatted for the correct
+ * documentation system.
+ */
+ String *getDocumentation(Node *node, const_String_or_char_ptr indentationString);
+
+ /*
+ * Returns true if the specified node has comment attached.
+ */
+ bool hasDocumentation(Node *node);
+
+ /*
+ * Get original comment string in Doxygen-format.
+ */
+ String *getDoxygenComment(Node *node);
+
+protected:
+ // The flags passed to the ctor.
+ const int m_flags;
+
+ DoxygenParser parser;
+
+ /*
+ * Returns the documentation formatted for a target language.
+ */
+ virtual String *makeDocumentation(Node *node) = 0;
+
+ /*
+ * Prints the details of a parsed entity list to stdout (for debugging).
+ */
+ void printTree(const DoxygenEntityList &entityList);
+
+ void extraIndentation(String *comment, const_String_or_char_ptr indentationString);
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Doxygen/javadoc.cxx b/contrib/tools/swig/Source/Doxygen/javadoc.cxx
new file mode 100644
index 00000000000..17c7d03abb5
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/javadoc.cxx
@@ -0,0 +1,849 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * javadoc.cxx
+ * ----------------------------------------------------------------------------- */
+
+#include "javadoc.h"
+#include "doxyparser.h"
+#include <iostream>
+#include <vector>
+#include <list>
+#include "swigmod.h"
+#define APPROX_LINE_LENGTH 64 // characters per line allowed
+#define TAB_SIZE 8 // current tab size in spaces
+//TODO {@link} {@linkplain} {@docRoot}, and other useful doxy commands that are not a javadoc tag
+
+// define static tables, they are filled in JavaDocConverter's constructor
+std::map<std::string, std::pair<JavaDocConverter::tagHandler, std::string> > JavaDocConverter::tagHandlers;
+
+using std::string;
+using std::list;
+using std::vector;
+
+void JavaDocConverter::fillStaticTables() {
+ if (tagHandlers.size()) // fill only once
+ return;
+
+ /*
+ * Some translation rules:
+ *
+ * @ and \ must be escaped for both Java and Python to appear on output: \@, \\,
+ * while Doxygen produces output in both cases.
+ * Rule: @ and \ with space on the right should get to output.
+ *
+ * :: remains intact, even in class::method(). But you can use class#method also
+ * in C++ comment and it is properly translated to C++ output (changed by doxygen to ::)
+ * and Java output (remains #).
+ * Rule: SWIG type system can't be used to convert C::m to C#m, because in Java it is C.m
+ * Use string replacement :: --> # in tag see and links.
+ *
+ * HTML tags must be translated - remain in Java, to markdown in Python
+ *
+ * Unknown HTML tags, for example <x> is translated to &lt;x&gt; by doxygen, while
+ * Java src is <x> and therefore invisible on output - browser ignores unknown command.
+ * This is handy in syntax descriptions, for example: more <fileName>.
+ *
+ * Standalone < and > need not be translated, they are rendered properly in
+ * all three outputs.
+ *
+ * ., %, and " need not to be translated
+ *
+ * entities must be translated - remain in Java, something meaningful in Python (&lt, ...)
+ *
+ * - Python
+ * - add comments also to auto-generated methods like equals(), delete() in Java,
+ * and methods for std::vector(), ...
+ * Commenting methods of std types is simple - add comment to std_*.i file.
+ */
+
+ // these commands insert HTML tags
+ tagHandlers["a"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
+ tagHandlers["arg"] = make_pair(&JavaDocConverter::handleTagHtml, "li");
+ tagHandlers["b"] = make_pair(&JavaDocConverter::handleTagHtml, "b");
+ tagHandlers["c"] = make_pair(&JavaDocConverter::handleTagHtml, "code");
+ tagHandlers["cite"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
+ tagHandlers["e"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
+ tagHandlers["em"] = make_pair(&JavaDocConverter::handleTagHtml, "i");
+ tagHandlers["li"] = make_pair(&JavaDocConverter::handleTagHtml, "li");
+ tagHandlers["p"] = make_pair(&JavaDocConverter::handleTagHtml, "code");
+ // these commands insert just a single char, some of them need to be escaped
+ tagHandlers["$"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["@"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["\\"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["<"] = make_pair(&JavaDocConverter::handleTagChar, "&lt;");
+ tagHandlers[">"] = make_pair(&JavaDocConverter::handleTagChar, "&gt;");
+ tagHandlers["&"] = make_pair(&JavaDocConverter::handleTagChar, "&amp;");
+ tagHandlers["#"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["%"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["~"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["\""] = make_pair(&JavaDocConverter::handleTagChar, "&quot;");
+ tagHandlers["."] = make_pair(&JavaDocConverter::handleTagChar, "");
+ tagHandlers["::"] = make_pair(&JavaDocConverter::handleTagChar, "");
+ // these commands are stripped out
+ tagHandlers["attention"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["anchor"] = make_pair(&JavaDocConverter::handleTagAnchor, "");
+ tagHandlers["brief"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["bug"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["date"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["details"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ // this command is inserts text accumulated after cmd htmlonly -
+ // see DoxygenParser - CMD_HTML_ONLY.
+ tagHandlers["htmlonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["invariant"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["latexonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["manonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["partofdescription"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["rtfonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["short"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ tagHandlers["xmlonly"] = make_pair(&JavaDocConverter::handleParagraph, "");
+ // these commands are kept as-is, they are supported by JavaDoc
+ tagHandlers["author"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["authors"] = make_pair(&JavaDocConverter::handleTagSame, "author");
+ tagHandlers["deprecated"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["exception"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["package"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["param"] = make_pair(&JavaDocConverter::handleTagParam, "");
+ tagHandlers["tparam"] = make_pair(&JavaDocConverter::handleTagParam, "");
+ tagHandlers["ref"] = make_pair(&JavaDocConverter::handleTagRef, "");
+ tagHandlers["result"] = make_pair(&JavaDocConverter::handleTagSame, "return");
+ tagHandlers["return"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["returns"] = make_pair(&JavaDocConverter::handleTagSame, "return");
+ //tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ //tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSame, "see");
+ tagHandlers["since"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["throws"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ tagHandlers["throw"] = make_pair(&JavaDocConverter::handleTagSame, "throws");
+ tagHandlers["version"] = make_pair(&JavaDocConverter::handleTagSame, "");
+ // these commands have special handlers
+ tagHandlers["code"] = make_pair(&JavaDocConverter::handleTagExtended, "code");
+ tagHandlers["cond"] = make_pair(&JavaDocConverter::handleTagMessage, "Conditional comment: ");
+ tagHandlers["copyright"] = make_pair(&JavaDocConverter::handleTagMessage, "Copyright: ");
+ tagHandlers["else"] = make_pair(&JavaDocConverter::handleTagIf, "Else: ");
+ tagHandlers["elseif"] = make_pair(&JavaDocConverter::handleTagIf, "Else if: ");
+ tagHandlers["endcond"] = make_pair(&JavaDocConverter::handleTagMessage, "End of conditional comment.");
+ // space in second arg prevents Javadoc to treat '@ example' as command. File name of
+ // example is still informative to user.
+ tagHandlers["example"] = make_pair(&JavaDocConverter::handleTagSame, " example");
+ tagHandlers["if"] = make_pair(&JavaDocConverter::handleTagIf, "If: ");
+ tagHandlers["ifnot"] = make_pair(&JavaDocConverter::handleTagIf, "If not: ");
+ tagHandlers["image"] = make_pair(&JavaDocConverter::handleTagImage, "");
+ tagHandlers["link"] = make_pair(&JavaDocConverter::handleTagLink, "");
+ tagHandlers["see"] = make_pair(&JavaDocConverter::handleTagSee, "");
+ tagHandlers["sa"] = make_pair(&JavaDocConverter::handleTagSee, "");
+ tagHandlers["note"] = make_pair(&JavaDocConverter::handleTagMessage, "Note: ");
+ tagHandlers["overload"] = make_pair(&JavaDocConverter::handleTagMessage,
+ "This is an overloaded member function, provided for"
+ " convenience. It differs from the above function only in what" " argument(s) it accepts.");
+ tagHandlers["par"] = make_pair(&JavaDocConverter::handleTagPar, "");
+ tagHandlers["remark"] = make_pair(&JavaDocConverter::handleTagMessage, "Remarks: ");
+ tagHandlers["remarks"] = make_pair(&JavaDocConverter::handleTagMessage, "Remarks: ");
+ tagHandlers["todo"] = make_pair(&JavaDocConverter::handleTagMessage, "TODO: ");
+ tagHandlers["verbatim"] = make_pair(&JavaDocConverter::handleTagExtended, "literal");
+
+ // \f commands output literal Latex formula, which is still better than nothing.
+ tagHandlers["f$"] = make_pair(&JavaDocConverter::handleTagVerbatim, "");
+ tagHandlers["f["] = make_pair(&JavaDocConverter::handleTagVerbatim, "");
+ tagHandlers["f{"] = make_pair(&JavaDocConverter::handleTagVerbatim, "");
+
+ tagHandlers["warning"] = make_pair(&JavaDocConverter::handleTagMessage, "Warning: ");
+ // this command just prints its contents
+ // (it is internal command of swig's parser, contains plain text)
+ tagHandlers["plainstd::string"] = make_pair(&JavaDocConverter::handlePlainString, "");
+ tagHandlers["plainstd::endl"] = make_pair(&JavaDocConverter::handleNewLine, "");
+ tagHandlers["n"] = make_pair(&JavaDocConverter::handleNewLine, "");
+
+ // HTML tags
+ tagHandlers["<a"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<a");
+ tagHandlers["<b"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<b");
+ tagHandlers["<blockquote"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<blockquote");
+ tagHandlers["<body"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<body");
+ tagHandlers["<br"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<br");
+ tagHandlers["<center"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<center");
+ tagHandlers["<caption"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<caption");
+ tagHandlers["<code"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<code");
+ tagHandlers["<dd"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dd");
+ tagHandlers["<dfn"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dfn");
+ tagHandlers["<div"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<div");
+ tagHandlers["<dl"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dl");
+ tagHandlers["<dt"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<dt");
+ tagHandlers["<em"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<em");
+ tagHandlers["<form"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<form");
+ tagHandlers["<hr"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<hr");
+ tagHandlers["<h1"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<h1");
+ tagHandlers["<h2"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<h2");
+ tagHandlers["<h3"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<h3");
+ tagHandlers["<i"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<i");
+ tagHandlers["<input"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<input");
+ tagHandlers["<img"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<img");
+ tagHandlers["<li"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<li");
+ tagHandlers["<meta"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<meta");
+ tagHandlers["<multicol"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<multicol");
+ tagHandlers["<ol"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<ol");
+ tagHandlers["<p"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<p");
+ tagHandlers["<pre"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<pre");
+ tagHandlers["<small"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<small");
+ tagHandlers["<span"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<span");
+ tagHandlers["<strong"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<strong");
+ tagHandlers["<sub"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<sub");
+ tagHandlers["<sup"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<sup");
+ tagHandlers["<table"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<table");
+ tagHandlers["<td"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<td");
+ tagHandlers["<th"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<th");
+ tagHandlers["<tr"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<tr");
+ tagHandlers["<tt"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<tt");
+ tagHandlers["<kbd"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<kbd");
+ tagHandlers["<ul"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<ul");
+ tagHandlers["<var"] = make_pair(&JavaDocConverter::handleDoxyHtmlTag, "<var");
+
+ // HTML entities
+ tagHandlers["&copy"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&copy");
+ tagHandlers["&trade"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&trade");
+ tagHandlers["&reg"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&reg");
+ tagHandlers["&lt"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&lt");
+ tagHandlers["&gt"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&gt");
+ tagHandlers["&amp"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&amp");
+ tagHandlers["&apos"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&apos");
+ tagHandlers["&quot"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&quot");
+ tagHandlers["&lsquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&lsquo");
+ tagHandlers["&rsquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&rsquo");
+ tagHandlers["&ldquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&ldquo");
+ tagHandlers["&rdquo"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&rdquo");
+ tagHandlers["&ndash"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&ndash");
+ tagHandlers["&mdash"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&mdash");
+ tagHandlers["&nbsp"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&nbsp");
+ tagHandlers["&times"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&times");
+ tagHandlers["&minus"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&minus");
+ tagHandlers["&sdot"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&sdot");
+ tagHandlers["&sim"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&sim");
+ tagHandlers["&le"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&le");
+ tagHandlers["&ge"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&ge");
+ tagHandlers["&larr"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&larr");
+ tagHandlers["&rarr"] = make_pair(&JavaDocConverter::handleHtmlEntity, "&rarr");
+}
+
+JavaDocConverter::JavaDocConverter(int flags) :
+ DoxygenTranslator(flags) {
+ fillStaticTables();
+}
+
+/**
+ * Formats comment lines by inserting '\n *' at to long lines and tabs for
+ * indent. Currently it is disabled, which means original comment format is
+ * preserved. Experience shows, that this is usually better than breaking
+ * lines automatically, especially because original line endings are not removed,
+ * which results in short lines. To be useful, this function should have much
+ * better algorithm.
+ */
+std::string JavaDocConverter::formatCommand(std::string unformattedLine, int indent) {
+ std::string formattedLines;
+ return unformattedLine; // currently disabled
+ std::string::size_type lastPosition = 0;
+ std::string::size_type i = 0;
+ int isFirstLine = 1;
+ while (i != std::string::npos && i < unformattedLine.length()) {
+ lastPosition = i;
+ if (isFirstLine) {
+ i += APPROX_LINE_LENGTH;
+ } else {
+ i += APPROX_LINE_LENGTH - indent * TAB_SIZE;
+ }
+
+ i = unformattedLine.find(' ', i);
+
+ if (i > 0 && i + 1 < unformattedLine.length()) {
+ if (!isFirstLine)
+ for (int j = 0; j < indent; j++) {
+ formattedLines.append("\t");
+ } else {
+ isFirstLine = 0;
+ }
+ formattedLines.append(unformattedLine.substr(lastPosition, i - lastPosition + 1));
+ formattedLines.append("\n *");
+
+ }
+ }
+ if (lastPosition < unformattedLine.length()) {
+ if (!isFirstLine) {
+ for (int j = 0; j < indent; j++) {
+ formattedLines.append("\t");
+ }
+ }
+ formattedLines.append(unformattedLine.substr(lastPosition, unformattedLine.length() - lastPosition));
+ }
+
+ return formattedLines;
+}
+
+/**
+ * Returns true, if the given parameter exists in the current node
+ * (for example param is a name of function parameter). If feature
+ * 'doxygen:nostripparams' is set, then this method always returns
+ * true - parameters are copied to output regardless of presence in
+ * function params list.
+ */
+bool JavaDocConverter::paramExists(std::string param) {
+
+ if (GetFlag(currentNode, "feature:doxygen:nostripparams")) {
+ return true;
+ }
+
+ ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
+
+ for (Parm *p = plist; p;) {
+
+ if (Getattr(p, "name") && Char(Getattr(p, "name")) == param) {
+ return true;
+ }
+ /* doesn't seem to work always: in some cases (especially for 'self' parameters)
+ * tmap:in is present, but tmap:in:next is not and so this code skips all the parameters
+ */
+ //p = Getattr(p, "tmap:in") ? Getattr(p, "tmap:in:next") : nextSibling(p);
+ p = nextSibling(p);
+ }
+
+ Delete(plist);
+
+ return false;
+}
+
+std::string JavaDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
+ std::string translatedComment;
+
+ if (doxygenEntity.isLeaf) {
+ return translatedComment;
+ }
+
+ for (DoxygenEntityListIt p = doxygenEntity.entityList.begin(); p != doxygenEntity.entityList.end(); p++) {
+
+ translateEntity(*p, translatedComment);
+ translateSubtree(*p);
+ }
+
+ return translatedComment;
+}
+
+/**
+ * Checks if a handler for the given tag exists, and calls it.
+ */
+void JavaDocConverter::translateEntity(DoxygenEntity &tag, std::string &translatedComment) {
+
+ std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
+ it = tagHandlers.find(getBaseCommand(tag.typeOfEntity));
+
+ if (it != tagHandlers.end()) {
+ (this->*(it->second.first))(tag, translatedComment, it->second.second);
+ } else {
+ // do NOT print warning, since there are many tags, which are not
+ // translatable - many warnings hide important ones
+ // addError(WARN_DOXYGEN_COMMAND_ERROR, "Unknown doxygen or HTML tag: " + tag.typeOfEntity);
+ }
+}
+
+
+void JavaDocConverter::handleTagAnchor(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ translatedComment += "<a id=\"" + translateSubtree(tag) + "\"></a>";
+}
+
+
+void JavaDocConverter::handleTagHtml(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ if (tag.entityList.size()) { // do not include empty tags
+ std::string tagData = translateSubtree(tag);
+ // wrap the thing, ignoring whitespace
+ size_t wsPos = tagData.find_last_not_of("\n\t ");
+ if (wsPos != std::string::npos)
+ translatedComment += "<" + arg + ">" + tagData.substr(0, wsPos + 1) + "</" + arg + ">" + tagData.substr(wsPos + 1);
+ else
+ translatedComment += "<" + arg + ">" + translateSubtree(tag) + "</" + arg + "> ";
+ }
+}
+
+void JavaDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</ul>
+ translatedComment += "</" + arg.substr(1) + ">";
+ } else {
+ translatedComment += arg + htmlTagArgs + ">";
+ }
+}
+
+void JavaDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, std::string &arg) {
+ // html entities can be preserved for Java
+ translatedComment += arg + ';';
+}
+
+void JavaDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, std::string &) {
+ // <br> tag is added, because otherwise to much text is joined
+ // into same paragraph by javadoc. For example, doxy list:
+ // - item one
+ // - item two
+ // becomes one paragraph with surrounding text without newlines.
+ // This way we get to many empty lines in javadoc output, but this
+ // is still better than joined lines. Possibility for improvements
+ // exists.
+ translatedComment += "<br>\n * ";
+}
+
+void JavaDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ // escape it if we need to, else just print
+ if (arg.size())
+ translatedComment += arg;
+ else
+ translatedComment += tag.typeOfEntity;
+}
+
+// handles tags which are the same in Doxygen and Javadoc.
+void JavaDocConverter::handleTagSame(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ if (arg.size())
+ tag.typeOfEntity = arg;
+ translatedComment += formatCommand(std::string("@" + tag.typeOfEntity + " " + translateSubtree(tag)), 2);
+}
+
+void JavaDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ translatedComment += formatCommand(translateSubtree(tag), 0);
+}
+
+void JavaDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ translatedComment += tag.data;
+ // if (tag.data.size() && tag.data[tag.data.size()-1] != ' ')
+ // translatedComment += " ";
+}
+
+void JavaDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ translatedComment += arg + " ";
+ for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
+ translatedComment += it->data;
+ }
+}
+
+void JavaDocConverter::handleTagExtended(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ std::string dummy;
+ translatedComment += "{@" + arg + " ";
+ handleParagraph(tag, translatedComment, dummy);
+ translatedComment += "}";
+}
+
+void JavaDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ std::string dummy;
+ translatedComment += arg;
+ if (tag.entityList.size()) {
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ translatedComment += " {" + translateSubtree(tag) + "}";
+ }
+}
+
+void JavaDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg) {
+ std::string dummy;
+ translatedComment += formatCommand(arg, 0);
+ handleParagraph(tag, translatedComment, dummy);
+}
+
+void JavaDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ if (tag.entityList.size() < 2)
+ return;
+
+ std::string file;
+ std::string title;
+
+ std::list<DoxygenEntity>::iterator it = tag.entityList.begin();
+ if (it->data != "html")
+ return;
+
+ it++;
+ file = it->data;
+
+ it++;
+ if (it != tag.entityList.end())
+ title = it->data;
+
+ translatedComment += "<img src=";
+ if (file.size() >= 2 && file[0] == '"' && file[file.size() - 1] == '"')
+ translatedComment += file;
+ else
+ translatedComment += "\"" + file + "\"";
+ if (title.size())
+ translatedComment += " alt=" + title;
+
+ // the size indication is supported for Latex only in Doxygen, see manual
+
+ translatedComment += "/>";
+}
+
+void JavaDocConverter::handleTagPar(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ std::string dummy;
+ translatedComment += "<p";
+ if (tag.entityList.size()) {
+ translatedComment += " alt=\"" + tag.entityList.begin()->data + "\"";
+ translatedComment += ">";
+ tag.entityList.pop_front();
+ handleParagraph(tag, translatedComment, dummy);
+ }
+ translatedComment += "</p>";
+}
+
+
+void JavaDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ std::string dummy;
+
+ if (!tag.entityList.size())
+ return;
+ if (!paramExists(tag.entityList.begin()->data))
+ return;
+
+ translatedComment += "@param ";
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ handleParagraph(tag, translatedComment, dummy);
+}
+
+
+void JavaDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ std::string dummy;
+ if (!tag.entityList.size())
+ return;
+
+ // we translate to link, although \page is not supported in Java, but
+ // reader at least knows what to look at. Also for \anchor tag on the same
+ // page this link works.
+ string anchor = tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ string anchorText = anchor;
+ if (!tag.entityList.empty()) {
+ anchorText = tag.entityList.begin()->data;
+ }
+ translatedComment += "<a href=\"#" + anchor + "\">" + anchorText + "</a>";
+}
+
+
+string JavaDocConverter::convertLink(string linkObject) {
+ if (GetFlag(currentNode, "feature:doxygen:nolinktranslate"))
+ return linkObject;
+ // find the params in function in linkObject (if any)
+ size_t lbracePos = linkObject.find('(', 0);
+ size_t rbracePos = linkObject.find(')', 0);
+ if (lbracePos == string::npos || rbracePos == string::npos || lbracePos >= rbracePos)
+ return "";
+
+ string paramsStr = linkObject.substr(lbracePos + 1,
+ rbracePos - lbracePos - 1);
+ // strip the params, to fill them later
+ string additionalObject = linkObject.substr(rbracePos + 1, string::npos);
+ linkObject = linkObject.substr(0, lbracePos);
+
+ // find all the params
+ vector<string> params;
+ size_t lastPos = 0, commaPos = 0;
+ while (true) {
+ commaPos = paramsStr.find(',', lastPos);
+ if (commaPos == string::npos)
+ commaPos = paramsStr.size();
+ string param = paramsStr.substr(lastPos, commaPos - lastPos);
+ // if any param type is empty, we are failed
+ if (!param.size())
+ return "";
+ params.push_back(param);
+ lastPos = commaPos + 1;
+ if (lastPos >= paramsStr.size())
+ break;
+ }
+
+ linkObject += "(";
+ for (size_t i = 0; i < params.size(); i++) {
+ // translate c/c++ type string to swig's type
+ // i e 'int **arr[100][10]' -> 'a(100).a(10).p.p.int'
+ // also converting arrays to pointers
+ string paramStr = params[i];
+ String *swigType = NewString("");
+
+ // handle const qualifier
+ if (paramStr.find("const") != string::npos)
+ SwigType_add_qualifier(swigType, "const");
+
+ // handle pointers, references and arrays
+ for (int j = (int)params[i].size() - 1; j >= 0; j--) {
+ // skip all the [...] blocks, write 'p.' for every of it
+ if (paramStr[j] == ']') {
+ while (j >= 0 && paramStr[j] != '[')
+ j--;
+ // no closing brace
+ if (j < 0)
+ return "";
+ SwigType_add_pointer(swigType);
+ continue;
+ } else if (paramStr[j] == '*')
+ SwigType_add_pointer(swigType);
+ else if (paramStr[j] == '&')
+ SwigType_add_reference(swigType);
+ else if (isalnum(paramStr[j])) {
+ size_t typeNameStart = paramStr.find_last_of(' ', j + 1);
+ if (typeNameStart == string::npos)
+ typeNameStart = 0;
+ else
+ typeNameStart++;
+ Append(swigType, paramStr.substr(typeNameStart, j - typeNameStart + 1).c_str());
+ break;
+ }
+ }
+
+ // make dummy param list, to lookup typemaps for it
+ Parm *dummyParam = NewParm(swigType, "", 0);
+ Swig_typemap_attach_parms("jstype", dummyParam, NULL);
+ Language::instance()->replaceSpecialVariables(0, Getattr(dummyParam, "tmap:jstype"), dummyParam);
+
+ //Swig_print(dummyParam, 1);
+ linkObject += Char(Getattr(dummyParam, "tmap:jstype"));
+ if (i != params.size() - 1)
+ linkObject += ",";
+
+ Delete(dummyParam);
+ Delete(swigType);
+ }
+ linkObject += ")";
+
+ return linkObject + additionalObject;
+}
+
+void JavaDocConverter::handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ std::string dummy;
+ if (!tag.entityList.size())
+ return;
+
+ string linkObject = convertLink(tag.entityList.begin()->data);
+ if (!linkObject.size())
+ linkObject = tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+
+ translatedComment += "{@link ";
+ translatedComment += linkObject + " ";
+ handleParagraph(tag, translatedComment, dummy);
+ translatedComment += "}";
+}
+
+void JavaDocConverter::handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &) {
+ std::string dummy;
+ if (!tag.entityList.size())
+ return;
+
+ // tag.entity list contains contents of the @see paragraph. It should contain
+ // one link (references) to method with or without parameters. Doxygen supports
+ // arbitrary text and types mixed, but this feature is not supported here.
+ // :: or # may be used as a separator between class name and method name.
+ list<DoxygenEntity>::iterator it;
+ string methodRef;
+ for (it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
+ if (it->typeOfEntity == "plainstd::endl") {
+ // handleNewLine(*it, translatedComment, dummy);
+ continue;
+ }
+ // restore entities which may be used in C++ type declaration
+ if (it->typeOfEntity == "&amp") {
+ methodRef += '&';
+ } else if (it->typeOfEntity == "&lt") {
+ methodRef += '<';
+ } else if (it->typeOfEntity == "&gt") {
+ methodRef += '>';
+ } else {
+ methodRef += it->data;
+ }
+ }
+
+ // replace :: with #, but only if it appears before left brace
+ size_t lbrace = methodRef.find('(');
+ size_t dblColon = methodRef.find("::");
+ if (dblColon < lbrace) {
+ methodRef = methodRef.substr(0, dblColon) + '#' + methodRef.substr(dblColon + 2);
+ }
+
+ translatedComment += "@see ";
+ string linkObject = convertLink(methodRef);
+ if (!linkObject.size()) {
+ linkObject = methodRef;
+ }
+ translatedComment += linkObject;
+}
+
+/* This function moves all line endings at the end of child entities
+ * out of the child entities to the parent.
+ * For example, entity tree:
+
+ -root
+ |-param
+ |-paramText
+ |-endline
+
+ should be turned to
+
+ -root
+ |-param
+ |-paramText
+ |-endline
+ *
+ */
+int JavaDocConverter::shiftEndlinesUpTree(DoxygenEntity &root, int level) {
+ DoxygenEntityListIt it = root.entityList.begin();
+ while (it != root.entityList.end()) {
+ // remove line endings
+ int ret = shiftEndlinesUpTree(*it, level + 1);
+ // insert them after this element
+ it++;
+ for (int i = 0; i < ret; i++) {
+ root.entityList.insert(it, DoxygenEntity("plainstd::endl"));
+ }
+ }
+
+ // continue only if we are not root
+ if (!level) {
+ return 0;
+ }
+
+ int removedCount = 0;
+ while (!root.entityList.empty()
+ && root.entityList.rbegin()->typeOfEntity == "plainstd::endl") {
+ root.entityList.pop_back();
+ removedCount++;
+ }
+ return removedCount;
+}
+
+/**
+ * This makes sure that all comment lines contain '*'. It is not mandatory in doxygen,
+ * but highly recommended for Javadoc. '*' in empty lines are indented according
+ * to indentation of the first line. Indentation of non-empty lines is not
+ * changed - garbage in garbage out.
+ */
+std::string JavaDocConverter::indentAndInsertAsterisks(const string &doc) {
+
+ size_t idx = doc.find('\n');
+ size_t indent = 0;
+ bool singleLineComment = idx == string::npos;
+ // Detect indentation.
+ // The first line in comment is the one after '/**', which may be
+ // spaces and '\n' or the text. In any case it is not suitable to detect
+ // indentation, so we have to skip the first '\n'.
+ // However, if there is just one line, then use that line to detect indentation.
+ if (idx != string::npos) {
+ size_t nonspaceIdx = doc.find_first_not_of(" \t", idx + 1);
+ if (nonspaceIdx != string::npos) {
+ indent = nonspaceIdx - idx;
+ }
+ }
+
+ if (indent == 0) {
+ // we can't indent the first line less than 0
+ indent = 1;
+ }
+ // Create the first line of Javadoc comment.
+ string indentStr(indent - 1, ' ');
+ string translatedStr = indentStr + "/**";
+ if (indent > 1) {
+ // remove the first space, so that '*' will be aligned
+ translatedStr = translatedStr.substr(1);
+ }
+
+ translatedStr += doc;
+
+ // insert '*' before each comment line, if it does not have it
+ idx = translatedStr.find('\n');
+
+ while (idx != string::npos) {
+
+ size_t nonspaceIdx = translatedStr.find_first_not_of(" \t", idx + 1);
+ if (nonspaceIdx != string::npos && translatedStr[nonspaceIdx] != '*') {
+ // line without '*' found - is it empty?
+ if (translatedStr[nonspaceIdx] != '\n') {
+ // add '* ' to each line without it
+ translatedStr = translatedStr.substr(0, nonspaceIdx) + "* " + translatedStr.substr(nonspaceIdx);
+ //printf(translatedStr.c_str());
+ } else {
+ // we found empty line, replace it with indented '*'
+ translatedStr = translatedStr.substr(0, idx + 1) + indentStr + "* " + translatedStr.substr(nonspaceIdx);
+ }
+ }
+ idx = translatedStr.find('\n', nonspaceIdx);
+ }
+
+ // Add the last comment line properly indented
+ size_t nonspaceEndIdx = translatedStr.find_last_not_of(" \t");
+ if (nonspaceEndIdx != string::npos) {
+ if (translatedStr[nonspaceEndIdx] != '\n') {
+ if (!singleLineComment)
+ translatedStr += '\n';
+ } else {
+ // remove trailing spaces
+ translatedStr = translatedStr.substr(0, nonspaceEndIdx + 1);
+ }
+ }
+ translatedStr += indentStr + "*/\n";
+
+ return translatedStr;
+}
+
+String *JavaDocConverter::makeDocumentation(Node *node) {
+
+ String *documentation = getDoxygenComment(node);
+
+ if (documentation == NULL) {
+ return NewString("");
+ }
+
+ if (GetFlag(node, "feature:doxygen:notranslate")) {
+
+ string doc = Char(documentation);
+
+ string translatedStr = indentAndInsertAsterisks(doc);
+
+ return NewString(translatedStr.c_str());
+ }
+
+ DoxygenEntityList entityList = parser.createTree(node, documentation);
+
+ // entityList.sort(CompareDoxygenEntities()); sorting currently not used,
+
+ if (m_flags & debug_translator) {
+ std::cout << "---RESORTED LIST---" << std::endl;
+ printTree(entityList);
+ }
+ // store the current node
+ // (currently just to handle params)
+ currentNode = node;
+
+ std::string javaDocString = "/**\n * ";
+
+ DoxygenEntity root("root", entityList);
+
+ shiftEndlinesUpTree(root);
+
+ // strip line endings at the beginning
+ while (!root.entityList.empty()
+ && root.entityList.begin()->typeOfEntity == "plainstd::endl") {
+ root.entityList.pop_front();
+ }
+
+ // and at the end
+ while (!root.entityList.empty()
+ && root.entityList.rbegin()->typeOfEntity == "plainstd::endl") {
+ root.entityList.pop_back();
+ }
+
+ javaDocString += translateSubtree(root);
+
+ javaDocString += "\n */\n";
+
+ if (m_flags & debug_translator) {
+ std::cout << "\n---RESULT IN JAVADOC---" << std::endl;
+ std::cout << javaDocString;
+ }
+
+ return NewString(javaDocString.c_str());
+}
+
+void JavaDocConverter::addError(int warningType, const std::string &message) {
+ Swig_warning(warningType, "", 0, "Doxygen parser warning: %s. \n", message.c_str());
+}
diff --git a/contrib/tools/swig/Source/Doxygen/javadoc.h b/contrib/tools/swig/Source/Doxygen/javadoc.h
new file mode 100644
index 00000000000..d2c956c9dbf
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/javadoc.h
@@ -0,0 +1,169 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * javadoc.h
+ *
+ * Module to return documentation for nodes formatted for JavaDoc
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_JAVADOC_H
+#define SWIG_JAVADOC_H
+
+#include "doxytranslator.h"
+#include <map>
+
+/*
+ * A class to translate doxygen comments into JavaDoc style comments.
+ */
+class JavaDocConverter : public DoxygenTranslator {
+public:
+ JavaDocConverter(int flags = 0);
+ String *makeDocumentation(Node *node);
+
+protected:
+ /*
+ * Used to properly format JavaDoc-style command
+ */
+ std::string formatCommand(std::string unformattedLine, int indent);
+
+ /*
+ * Translate every entity in a tree.
+ */
+ std::string translateSubtree(DoxygenEntity &doxygenEntity);
+
+ /*
+ * Translate one entity with the appropriate handler, according
+ * to the tagHandlers
+ */
+ void translateEntity(DoxygenEntity &tag, std::string &translatedComment);
+
+ /*
+ * Fix all endlines location, etc
+ */
+ int shiftEndlinesUpTree(DoxygenEntity &root, int level = 0);
+
+ /*
+ * Convert params in link-objects and references
+ */
+ std::string convertLink(std::string linkObject);
+
+ /*
+ * Typedef for the function that handles one tag
+ * arg - some string argument to easily pass it through lookup table
+ */
+ typedef void (JavaDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /**
+ * Copies verbatim args of the tag to output, used for commands like \f$, ...
+ */
+ void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /** Creates anchor link. */
+ void handleTagAnchor(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Wrap the command data with the html tag
+ * arg - html tag, with no braces
+ */
+ void handleTagHtml(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /* Handles HTML tags recognized by Doxygen, like <A ...>, <ul>, <table>, ... */
+ void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /* Handles HTML entities recognized by Doxygen, like &lt;, &copy;, ... */
+ void handleHtmlEntity(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Just prints new line
+ */
+ void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Print the name of tag to the output, used for escape-commands
+ * arg - html-escaped variant, if not provided the command data is used
+ */
+ void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Do not translate and print as-is
+ * arg - the new tag name, if it needs to be renamed
+ */
+ void handleTagSame(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Print only the content and strip original tag
+ */
+ void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Print only data part of code
+ */
+ void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Print extended Javadoc command, like {@code ...} or {@literal ...}
+ * arg - command name
+ */
+ void handleTagExtended(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Print the if-elseif-else-endif section
+ */
+ void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Prints the specified message, than the contents of the tag
+ * arg - message
+ */
+ void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Insert <img src=... /> tag if the 'format' field is specified as 'html'
+ */
+ void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Insert <p alt='title'>...</p>
+ */
+ void handleTagPar(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Insert \@param command, if it is really a function param
+ */
+ void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Writes link for \ref tag.
+ */
+ void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, std::string &);
+
+ /*
+ * Insert {@link...} command, and handle all the <link-object>s correctly
+ * (like converting types of params, etc)
+ */
+ void handleTagLink(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+ /*
+ * Insert @see command, and handle all the <link-object>s correctly
+ * (like converting types of params, etc)
+ */
+ void handleTagSee(DoxygenEntity &tag, std::string &translatedComment, std::string &arg);
+
+private:
+ Node *currentNode;
+ // this contains the handler pointer and one string argument
+ static std::map<std::string, std::pair<tagHandler, std::string> > tagHandlers;
+ void fillStaticTables();
+
+ bool paramExists(std::string param);
+ std::string indentAndInsertAsterisks(const std::string &doc);
+
+ void addError(int warningType, const std::string &message);
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Doxygen/pydoc.cxx b/contrib/tools/swig/Source/Doxygen/pydoc.cxx
new file mode 100644
index 00000000000..03986a49c9a
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/pydoc.cxx
@@ -0,0 +1,993 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * pydoc.cxx
+ *
+ * Module to return documentation for nodes formatted for PyDoc
+ * ----------------------------------------------------------------------------- */
+
+#include "pydoc.h"
+#include "doxyparser.h"
+#include <sstream>
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "swigmod.h"
+
+// define static tables, they are filled in PyDocConverter's constructor
+PyDocConverter::TagHandlersMap PyDocConverter::tagHandlers;
+std::map<std::string, std::string> PyDocConverter::sectionTitles;
+
+using std::string;
+
+// Helper class increasing the provided indent string in its ctor and decreasing
+// it in its dtor.
+class IndentGuard {
+public:
+ // One indent level.
+ static const char *Level() {
+ return " ";
+ }
+ // Default ctor doesn't do anything and prevents the dtor from doing anything// too and should only be used when the guard needs to be initialized// conditionally as Init() can then be called after checking some condition.// Otherwise, prefer to use the non default ctor below.
+ IndentGuard() {
+ m_initialized = false;
+ }
+
+ // Ctor takes the output to determine the current indent and to remove the
+ // extra indent added to it in the dtor and the variable containing the indent
+ // to use, which must be used after every new line by the code actually
+ // updating the output.
+ IndentGuard(string &output, string &indent) {
+ Init(output, indent);
+ }
+
+ // Really initializes the object created using the default ctor.
+ void Init(string &output, string &indent) {
+ m_output = &output;
+ m_indent = &indent;
+
+ const string::size_type lastNonSpace = m_output->find_last_not_of(' ');
+ if (lastNonSpace == string::npos) {
+ m_firstLineIndent = m_output->length();
+ } else if ((*m_output)[lastNonSpace] == '\n') {
+ m_firstLineIndent = m_output->length() - (lastNonSpace + 1);
+ } else {
+ m_firstLineIndent = 0;
+ }
+
+ // Notice that the indent doesn't include the first line indent because it's
+ // implicit, i.e. it is present in the input and so is copied into the
+ // output anyhow.
+ *m_indent = Level();
+
+ m_initialized = true;
+ }
+
+ // Get the indent for the first line of the paragraph, which is smaller than
+ // the indent for the subsequent lines.
+ string getFirstLineIndent() const {
+ return string(m_firstLineIndent, ' ');
+ }
+
+ ~IndentGuard() {
+ if (!m_initialized)
+ return;
+
+ m_indent->clear();
+
+ // Get rid of possible remaining extra indent, e.g. if there were any trailing
+ // new lines: we shouldn't add the extra indent level to whatever follows
+ // this paragraph.
+ static const size_t lenIndentLevel = strlen(Level());
+ if (m_output->length() > lenIndentLevel) {
+ const size_t start = m_output->length() - lenIndentLevel;
+ if (m_output->compare(start, string::npos, Level()) == 0)
+ m_output->erase(start);
+ }
+ }
+
+private:
+ string *m_output;
+ string *m_indent;
+ string::size_type m_firstLineIndent;
+ bool m_initialized;
+
+ IndentGuard(const IndentGuard &);
+ IndentGuard &operator=(const IndentGuard &);
+};
+
+// Return the indent of the given multiline string, i.e. the maximal number of
+// spaces present in the beginning of all its non-empty lines.
+static size_t determineIndent(const string &s) {
+ size_t minIndent = static_cast<size_t>(-1);
+
+ for (size_t lineStart = 0; lineStart < s.length();) {
+ const size_t lineEnd = s.find('\n', lineStart);
+ const size_t firstNonSpace = s.find_first_not_of(' ', lineStart);
+
+ // If inequality doesn't hold, it means that this line contains only spaces
+ // (notice that this works whether lineEnd is valid or string::npos), in
+ // which case it doesn't matter when determining the indent.
+ if (firstNonSpace < lineEnd) {
+ // Here we can be sure firstNonSpace != string::npos.
+ const size_t lineIndent = firstNonSpace - lineStart;
+ if (lineIndent < minIndent)
+ minIndent = lineIndent;
+ }
+
+ if (lineEnd == string::npos)
+ break;
+
+ lineStart = lineEnd + 1;
+ }
+
+ return minIndent;
+}
+
+static void trimWhitespace(string &s) {
+ const string::size_type lastNonSpace = s.find_last_not_of(' ');
+ if (lastNonSpace == string::npos)
+ s.clear();
+ else
+ s.erase(lastNonSpace + 1);
+}
+
+// Erase the first character in the string if it is a newline
+static void eraseLeadingNewLine(string &s) {
+ if (!s.empty() && s[0] == '\n')
+ s.erase(s.begin());
+}
+
+// Erase the last character in the string if it is a newline
+static void eraseTrailingNewLine(string &s) {
+ if (!s.empty() && s[s.size() - 1] == '\n')
+ s.erase(s.size() - 1);
+}
+
+// Check the generated docstring line by line and make sure that any
+// code and verbatim blocks have an empty line preceding them, which
+// is necessary for Sphinx. Additionally, this strips any empty lines
+// appearing at the beginning of the docstring.
+static string padCodeAndVerbatimBlocks(const string &docString) {
+ std::string result;
+
+ std::istringstream iss(docString);
+
+ // Initialize to false because there is no previous line yet
+ bool lastLineWasNonBlank = false;
+
+ for (string line; std::getline(iss, line); result += line) {
+ if (!result.empty()) {
+ // Terminate the previous line
+ result += '\n';
+ }
+
+ const size_t pos = line.find_first_not_of(" \t");
+ if (pos == string::npos) {
+ lastLineWasNonBlank = false;
+ } else {
+ if (lastLineWasNonBlank &&
+ (line.compare(pos, 13, ".. code-block") == 0 ||
+ line.compare(pos, 7, ".. math") == 0 ||
+ line.compare(pos, 3, ">>>") == 0)) {
+ // Must separate code or math blocks from the previous line
+ result += '\n';
+ }
+ lastLineWasNonBlank = true;
+ }
+ }
+ return result;
+}
+
+// Helper function to extract the option value from a command,
+// e.g. param[in] -> in
+static std::string getCommandOption(const std::string &command, char openChar, char closeChar) {
+ string option;
+
+ size_t opt_begin, opt_end;
+ opt_begin = command.find(openChar);
+ opt_end = command.find(closeChar);
+ if (opt_begin != string::npos && opt_end != string::npos)
+ option = command.substr(opt_begin+1, opt_end-opt_begin-1);
+
+ return option;
+}
+
+
+/* static */
+PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler) {
+ return make_pair(handler, std::string());
+}
+
+/* static */
+PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::make_handler(tagHandler handler, const char *arg) {
+ return make_pair(handler, arg);
+}
+
+void PyDocConverter::fillStaticTables() {
+ if (tagHandlers.size()) // fill only once
+ return;
+
+ // table of section titles, they are printed only once
+ // for each group of specified doxygen commands
+ sectionTitles["author"] = "Author: ";
+ sectionTitles["authors"] = "Authors: ";
+ sectionTitles["copyright"] = "Copyright: ";
+ sectionTitles["deprecated"] = "Deprecated: ";
+ sectionTitles["example"] = "Example: ";
+ sectionTitles["note"] = "Notes: ";
+ sectionTitles["remark"] = "Remarks: ";
+ sectionTitles["remarks"] = "Remarks: ";
+ sectionTitles["warning"] = "Warning: ";
+// sectionTitles["sa"] = "See also: ";
+// sectionTitles["see"] = "See also: ";
+ sectionTitles["since"] = "Since: ";
+ sectionTitles["todo"] = "TODO: ";
+ sectionTitles["version"] = "Version: ";
+
+ tagHandlers["a"] = make_handler(&PyDocConverter::handleTagWrap, "*");
+ tagHandlers["b"] = make_handler(&PyDocConverter::handleTagWrap, "**");
+ // \c command is translated as single quotes around next word
+ tagHandlers["c"] = make_handler(&PyDocConverter::handleTagWrap, "``");
+ tagHandlers["cite"] = make_handler(&PyDocConverter::handleTagWrap, "'");
+ tagHandlers["e"] = make_handler(&PyDocConverter::handleTagWrap, "*");
+ // these commands insert just a single char, some of them need to be escaped
+ tagHandlers["$"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["@"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["\\"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["<"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers[">"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["&"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["#"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["%"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["~"] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["\""] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["."] = make_handler(&PyDocConverter::handleTagChar);
+ tagHandlers["::"] = make_handler(&PyDocConverter::handleTagChar);
+ // these commands are stripped out, and only their content is printed
+ tagHandlers["attention"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["author"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["authors"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["brief"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["bug"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["code"] = make_handler(&PyDocConverter::handleCode);
+ tagHandlers["copyright"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["date"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["deprecated"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["details"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["em"] = make_handler(&PyDocConverter::handleTagWrap, "*");
+ tagHandlers["example"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["exception"] = tagHandlers["throw"] = tagHandlers["throws"] = make_handler(&PyDocConverter::handleTagException);
+ tagHandlers["htmlonly"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["invariant"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["latexonly"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["link"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["manonly"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["note"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["p"] = make_handler(&PyDocConverter::handleTagWrap, "``");
+ tagHandlers["partofdescription"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["rtfonly"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["remark"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["remarks"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["sa"] = make_handler(&PyDocConverter::handleTagMessage, "See also: ");
+ tagHandlers["see"] = make_handler(&PyDocConverter::handleTagMessage, "See also: ");
+ tagHandlers["since"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["short"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["todo"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["version"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["verbatim"] = make_handler(&PyDocConverter::handleVerbatimBlock);
+ tagHandlers["warning"] = make_handler(&PyDocConverter::handleParagraph);
+ tagHandlers["xmlonly"] = make_handler(&PyDocConverter::handleParagraph);
+ // these commands have special handlers
+ tagHandlers["arg"] = make_handler(&PyDocConverter::handleTagMessage, "* ");
+ tagHandlers["cond"] = make_handler(&PyDocConverter::handleTagMessage, "Conditional comment: ");
+ tagHandlers["else"] = make_handler(&PyDocConverter::handleTagIf, "Else: ");
+ tagHandlers["elseif"] = make_handler(&PyDocConverter::handleTagIf, "Else if: ");
+ tagHandlers["endcond"] = make_handler(&PyDocConverter::handleTagMessage, "End of conditional comment.");
+ tagHandlers["if"] = make_handler(&PyDocConverter::handleTagIf, "If: ");
+ tagHandlers["ifnot"] = make_handler(&PyDocConverter::handleTagIf, "If not: ");
+ tagHandlers["image"] = make_handler(&PyDocConverter::handleTagImage);
+ tagHandlers["li"] = make_handler(&PyDocConverter::handleTagMessage, "* ");
+ tagHandlers["overload"] = make_handler(&PyDocConverter::handleTagMessage,
+ "This is an overloaded member function, provided for"
+ " convenience.\nIt differs from the above function only in what" " argument(s) it accepts.");
+ tagHandlers["par"] = make_handler(&PyDocConverter::handleTagPar);
+ tagHandlers["param"] = tagHandlers["tparam"] = make_handler(&PyDocConverter::handleTagParam);
+ tagHandlers["ref"] = make_handler(&PyDocConverter::handleTagRef);
+ tagHandlers["result"] = tagHandlers["return"] = tagHandlers["returns"] = make_handler(&PyDocConverter::handleTagReturn);
+
+ // this command just prints its contents
+ // (it is internal command of swig's parser, contains plain text)
+ tagHandlers["plainstd::string"] = make_handler(&PyDocConverter::handlePlainString);
+ tagHandlers["plainstd::endl"] = make_handler(&PyDocConverter::handleNewLine);
+ tagHandlers["n"] = make_handler(&PyDocConverter::handleNewLine);
+
+ // \f commands output literal Latex formula, which is still better than nothing.
+ tagHandlers["f$"] = tagHandlers["f["] = tagHandlers["f{"] = make_handler(&PyDocConverter::handleMath);
+
+ // HTML tags
+ tagHandlers["<a"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_A);
+ tagHandlers["<b"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "**");
+ tagHandlers["<blockquote"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_A, "Quote: ");
+ tagHandlers["<body"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<br"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "\n");
+
+ // there is no formatting for this tag as it was deprecated in HTML 4.01 and
+ // not used in HTML 5
+ tagHandlers["<center"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<caption"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<code"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "``");
+
+ tagHandlers["<dl"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<dd"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, " ");
+ tagHandlers["<dt"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+
+ tagHandlers["<dfn"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<div"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<em"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "**");
+ tagHandlers["<form"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<hr"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "--------------------------------------------------------------------\n");
+ tagHandlers["<h1"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "# ");
+ tagHandlers["<h2"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "## ");
+ tagHandlers["<h3"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "### ");
+ tagHandlers["<i"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "*");
+ tagHandlers["<input"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<img"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "Image:");
+ tagHandlers["<li"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "* ");
+ tagHandlers["<meta"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<multicol"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<ol"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<p"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, "\n");
+ tagHandlers["<pre"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<small"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<span"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "'");
+ tagHandlers["<strong"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "**");
+
+ // make a space between text and super/sub script.
+ tagHandlers["<sub"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, " ");
+ tagHandlers["<sup"] = make_handler(&PyDocConverter::handleDoxyHtmlTag, " ");
+
+ tagHandlers["<table"] = make_handler(&PyDocConverter::handleDoxyHtmlTagNoParam);
+ tagHandlers["<td"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_td);
+ tagHandlers["<th"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_th);
+ tagHandlers["<tr"] = make_handler(&PyDocConverter::handleDoxyHtmlTag_tr);
+ tagHandlers["<tt"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<kbd"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<ul"] = make_handler(&PyDocConverter::handleDoxyHtmlTag);
+ tagHandlers["<var"] = make_handler(&PyDocConverter::handleDoxyHtmlTag2, "*");
+
+ // HTML entities
+ tagHandlers["&copy"] = make_handler(&PyDocConverter::handleHtmlEntity, "(C)");
+ tagHandlers["&trade"] = make_handler(&PyDocConverter::handleHtmlEntity, " TM");
+ tagHandlers["&reg"] = make_handler(&PyDocConverter::handleHtmlEntity, "(R)");
+ tagHandlers["&lt"] = make_handler(&PyDocConverter::handleHtmlEntity, "<");
+ tagHandlers["&gt"] = make_handler(&PyDocConverter::handleHtmlEntity, ">");
+ tagHandlers["&amp"] = make_handler(&PyDocConverter::handleHtmlEntity, "&");
+ tagHandlers["&apos"] = make_handler(&PyDocConverter::handleHtmlEntity, "'");
+ tagHandlers["&quot"] = make_handler(&PyDocConverter::handleHtmlEntity, "\"");
+ tagHandlers["&lsquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "`");
+ tagHandlers["&rsquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "'");
+ tagHandlers["&ldquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "\"");
+ tagHandlers["&rdquo"] = make_handler(&PyDocConverter::handleHtmlEntity, "\"");
+ tagHandlers["&ndash"] = make_handler(&PyDocConverter::handleHtmlEntity, "-");
+ tagHandlers["&mdash"] = make_handler(&PyDocConverter::handleHtmlEntity, "--");
+ tagHandlers["&nbsp"] = make_handler(&PyDocConverter::handleHtmlEntity, " ");
+ tagHandlers["&times"] = make_handler(&PyDocConverter::handleHtmlEntity, "x");
+ tagHandlers["&minus"] = make_handler(&PyDocConverter::handleHtmlEntity, "-");
+ tagHandlers["&sdot"] = make_handler(&PyDocConverter::handleHtmlEntity, ".");
+ tagHandlers["&sim"] = make_handler(&PyDocConverter::handleHtmlEntity, "~");
+ tagHandlers["&le"] = make_handler(&PyDocConverter::handleHtmlEntity, "<=");
+ tagHandlers["&ge"] = make_handler(&PyDocConverter::handleHtmlEntity, ">=");
+ tagHandlers["&larr"] = make_handler(&PyDocConverter::handleHtmlEntity, "<--");
+ tagHandlers["&rarr"] = make_handler(&PyDocConverter::handleHtmlEntity, "-->");
+}
+
+PyDocConverter::PyDocConverter(int flags):
+DoxygenTranslator(flags), m_tableLineLen(0), m_prevRowIsTH(false) {
+ fillStaticTables();
+}
+
+// Return the type as it should appear in the output documentation.
+static std::string getPyDocType(Node *n, const_String_or_char_ptr lname = "") {
+ std::string type;
+
+ String *s = Swig_typemap_lookup("doctype", n, lname, 0);
+ if (!s) {
+ if (String *t = Getattr(n, "type"))
+ s = SwigType_str(t, NULL);
+ }
+
+ if (!s)
+ return type;
+
+ if (Language::classLookup(s)) {
+ // In Python C++ namespaces are flattened, so remove all but last component
+ // of the name.
+ String *const last = Swig_scopename_last(s);
+
+ // We are not actually sure whether it's a documented class or not, but
+ // there doesn't seem to be any harm in making it a reference if it isn't,
+ // while there is a lot of benefit in having a hyperlink if it is.
+ type = ":py:class:`";
+ type += Char(last);
+ type += "`";
+
+ Delete(last);
+ } else {
+ type = Char(s);
+ }
+
+ Delete(s);
+
+ return type;
+}
+
+std::string PyDocConverter::getParamType(std::string param) {
+ std::string type;
+
+ ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
+ for (Parm *p = plist; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+ if (pname && Char(pname) == param) {
+ type = getPyDocType(p, pname);
+ break;
+ }
+ }
+ Delete(plist);
+ return type;
+}
+
+std::string PyDocConverter::getParamValue(std::string param) {
+ std::string value;
+
+ ParmList *plist = CopyParmList(Getattr(currentNode, "parms"));
+ for (Parm *p = plist; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+ if (pname && Char(pname) == param) {
+ String *pval = Getattr(p, "value");
+ if (pval)
+ value = Char(pval);
+ break;
+ }
+ }
+ Delete(plist);
+ return value;
+}
+
+std::string PyDocConverter::translateSubtree(DoxygenEntity &doxygenEntity) {
+ std::string translatedComment;
+
+ if (doxygenEntity.isLeaf)
+ return translatedComment;
+
+ std::string currentSection;
+ std::list<DoxygenEntity>::iterator p = doxygenEntity.entityList.begin();
+ while (p != doxygenEntity.entityList.end()) {
+ std::map<std::string, std::string>::iterator it;
+ it = sectionTitles.find(p->typeOfEntity);
+ if (it != sectionTitles.end()) {
+ if (it->second != currentSection) {
+ currentSection = it->second;
+ translatedComment += currentSection;
+ }
+ }
+ translateEntity(*p, translatedComment);
+ translateSubtree(*p);
+ p++;
+ }
+
+ return translatedComment;
+}
+
+void PyDocConverter::translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment) {
+ // check if we have needed handler and call it
+ std::map<std::string, std::pair<tagHandler, std::string> >::iterator it;
+ it = tagHandlers.find(getBaseCommand(doxyEntity.typeOfEntity));
+ if (it != tagHandlers.end())
+ (this->*(it->second.first)) (doxyEntity, translatedComment, it->second.second);
+}
+
+void PyDocConverter::handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += translateSubtree(tag);
+}
+
+void PyDocConverter::handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ string verb = translateSubtree(tag);
+
+ eraseLeadingNewLine(verb);
+
+ // Remove the last newline to prevent doubling the newline already present after \endverbatim
+ trimWhitespace(verb); // Needed to catch trailing newline below
+ eraseTrailingNewLine(verb);
+ translatedComment += verb;
+}
+
+void PyDocConverter::handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ IndentGuard indent;
+
+ // Only \f$ is translated to inline formulae, \f[ and \f{ are for the block ones.
+ const bool inlineFormula = tag.typeOfEntity == "f$";
+
+ string formulaNL;
+
+ if (inlineFormula) {
+ translatedComment += ":math:`";
+ } else {
+ indent.Init(translatedComment, m_indent);
+
+ trimWhitespace(translatedComment);
+
+ const string formulaIndent = indent.getFirstLineIndent();
+ translatedComment += formulaIndent;
+ translatedComment += ".. math::\n";
+
+ formulaNL = '\n';
+ formulaNL += formulaIndent;
+ formulaNL += m_indent;
+ translatedComment += formulaNL;
+ }
+
+ std::string formula;
+ handleTagVerbatim(tag, formula, arg);
+
+ // It is important to ensure that we have no spaces around the inline math
+ // contents, so strip them.
+ const size_t start = formula.find_first_not_of(" \t\n");
+ const size_t end = formula.find_last_not_of(" \t\n");
+ if (start != std::string::npos) {
+ for (size_t n = start; n <= end; n++) {
+ if (formula[n] == '\n') {
+ // New lines must be suppressed in inline maths and indented in the block ones.
+ if (!inlineFormula)
+ translatedComment += formulaNL;
+ } else {
+ // Just copy everything else.
+ translatedComment += formula[n];
+ }
+ }
+ }
+
+ if (inlineFormula) {
+ translatedComment += "`";
+ }
+}
+
+void PyDocConverter::handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ IndentGuard indent(translatedComment, m_indent);
+
+ trimWhitespace(translatedComment);
+
+ // Check for an option given to the code command (e.g. code{.py}),
+ // and try to set the code-block language accordingly.
+ string option = getCommandOption(tag.typeOfEntity, '{', '}');
+ // Set up the language option to the code-block command, which can
+ // be any language supported by pygments:
+ string codeLanguage;
+ if (option == ".py")
+ // Other possibilities here are "default" or "python3". In Sphinx
+ // 2.1.2, basic syntax doesn't render quite the same in these as
+ // with "python", which for basic keywords seems to provide
+ // slightly richer formatting. Another option would be to leave
+ // the language empty, but testing with Sphinx 1.8.5 has produced
+ // an error "1 argument required".
+ codeLanguage = "python";
+ else if (option == ".java")
+ codeLanguage = "java";
+ else if (option == ".c")
+ codeLanguage = "c";
+ else
+ // If there is not a match, or if no option was given, go out on a
+ // limb and assume that the examples in the C or C++ sources use
+ // C++.
+ codeLanguage = "c++";
+
+ std::string code;
+ handleTagVerbatim(tag, code, arg);
+
+ // Try and remove leading newline, which is present for block \code
+ // command:
+ eraseLeadingNewLine(code);
+
+ // Check for python doctest blocks, and treat them specially:
+ bool isDocTestBlock = false;
+ size_t startPos;
+ // ">>>" would normally appear at the beginning, but doxygen comment
+ // style may have space in front, so skip leading whitespace
+ if ((startPos=code.find_first_not_of(" \t")) != string::npos && code.substr(startPos,3) == ">>>")
+ isDocTestBlock = true;
+
+ string codeIndent;
+ if (! isDocTestBlock) {
+ // Use the current indent for the code-block line itself.
+ translatedComment += indent.getFirstLineIndent();
+ translatedComment += ".. code-block:: " + codeLanguage + "\n\n";
+
+ // Specify the level of extra indentation that will be used for
+ // subsequent lines within the code block. Note that the correct
+ // "starting indentation" is already present in the input, so we
+ // only need to add the desired code block indentation.
+ codeIndent = m_indent;
+ }
+
+ translatedComment += codeIndent;
+ for (size_t n = 0; n < code.length(); n++) {
+ if (code[n] == '\n') {
+ // Don't leave trailing white space, this results in PEP8 validation
+ // errors in Python code (which are performed by our own unit tests).
+ trimWhitespace(translatedComment);
+ translatedComment += '\n';
+
+ // Ensure that we indent all the lines by the code indent.
+ translatedComment += codeIndent;
+ } else {
+ // Just copy everything else.
+ translatedComment += code[n];
+ }
+ }
+
+ trimWhitespace(translatedComment);
+
+ // For block commands, the translator adds the newline after
+ // \endcode, so try and compensate by removing the last newline from
+ // the code text:
+ eraseTrailingNewLine(translatedComment);
+}
+
+void PyDocConverter::handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += tag.data;
+}
+
+void PyDocConverter::handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+ for (DoxygenEntityListCIt it = tag.entityList.begin(); it != tag.entityList.end(); it++) {
+ translatedComment += it->data;
+ }
+}
+
+void PyDocConverter::handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+ handleParagraph(tag, translatedComment);
+}
+
+void PyDocConverter::handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += tag.typeOfEntity;
+}
+
+void PyDocConverter::handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ translatedComment += arg;
+ if (tag.entityList.size()) {
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ translatedComment += " {" + translateSubtree(tag) + "}";
+ }
+}
+
+void PyDocConverter::handleTagPar(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ translatedComment += "Title: ";
+ if (tag.entityList.size())
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ handleParagraph(tag, translatedComment);
+}
+
+void PyDocConverter::handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ if (tag.entityList.size() < 2)
+ return;
+ tag.entityList.pop_front();
+ translatedComment += "Image: ";
+ translatedComment += tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ if (tag.entityList.size())
+ translatedComment += "(" + tag.entityList.begin()->data + ")";
+}
+
+void PyDocConverter::handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ if (tag.entityList.size() < 2)
+ return;
+
+ IndentGuard indent(translatedComment, m_indent);
+
+ DoxygenEntity paramNameEntity = *tag.entityList.begin();
+ tag.entityList.pop_front();
+
+ const std::string &paramName = paramNameEntity.data;
+
+ const std::string paramType = getParamType(paramName);
+ const std::string paramValue = getParamValue(paramName);
+
+ // Get command option, e.g. "in", "out", or "in,out"
+ string commandOpt = getCommandOption(tag.typeOfEntity, '[', ']');
+ if (commandOpt == "in,out") commandOpt = "in/out";
+
+ // If provided, append the parameter direction to the type
+ // information via a suffix:
+ std::string suffix;
+ if (commandOpt.size() > 0)
+ suffix = ", " + commandOpt;
+
+ // If the parameter has a default value, flag it as optional in the
+ // generated type definition. Particularly helpful when the python
+ // call is generated with *args, **kwargs.
+ if (paramValue.size() > 0)
+ suffix += ", optional";
+
+ if (!paramType.empty()) {
+ translatedComment += ":type " + paramName + ": " + paramType + suffix + "\n";
+ translatedComment += indent.getFirstLineIndent();
+ }
+
+ translatedComment += ":param " + paramName + ":";
+
+ handleParagraph(tag, translatedComment);
+}
+
+
+void PyDocConverter::handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ IndentGuard indent(translatedComment, m_indent);
+
+ const std::string pytype = getPyDocType(currentNode);
+ if (!pytype.empty()) {
+ translatedComment += ":rtype: ";
+ translatedComment += pytype;
+ translatedComment += "\n";
+ translatedComment += indent.getFirstLineIndent();
+ }
+
+ translatedComment += ":return: ";
+ handleParagraph(tag, translatedComment);
+}
+
+
+void PyDocConverter::handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ IndentGuard indent(translatedComment, m_indent);
+
+ translatedComment += ":raises: ";
+ handleParagraph(tag, translatedComment);
+}
+
+
+void PyDocConverter::handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ if (!tag.entityList.size())
+ return;
+
+ string anchor = tag.entityList.begin()->data;
+ tag.entityList.pop_front();
+ string anchorText = anchor;
+ if (!tag.entityList.empty()) {
+ anchorText = tag.entityList.begin()->data;
+ }
+ translatedComment += "'" + anchorText + "'";
+}
+
+
+void PyDocConverter::handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ if (tag.entityList.size()) { // do not include empty tags
+ std::string tagData = translateSubtree(tag);
+ // wrap the thing, ignoring whitespace
+ size_t wsPos = tagData.find_last_not_of("\n\t ");
+ if (wsPos != std::string::npos && wsPos != tagData.size() - 1)
+ translatedComment += arg + tagData.substr(0, wsPos + 1) + arg + tagData.substr(wsPos + 1);
+ else
+ translatedComment += arg + tagData + arg;
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</ul>
+ // translatedComment += "</" + arg.substr(1) + ">";
+ } else {
+ translatedComment += arg + htmlTagArgs;
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</ul>
+ } else {
+ translatedComment += arg;
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, "</a>
+ translatedComment += " (" + m_url + ')';
+ m_url.clear();
+ } else {
+ m_url.clear();
+ size_t pos = htmlTagArgs.find('=');
+ if (pos != string::npos) {
+ m_url = htmlTagArgs.substr(pos + 1);
+ }
+ translatedComment += arg;
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end html tag, for example "</em>
+ translatedComment += arg;
+ } else {
+ translatedComment += arg;
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string htmlTagArgs = tag.data;
+ size_t nlPos = translatedComment.rfind('\n');
+ if (htmlTagArgs == "/") {
+ // end tag, </tr> appends vertical table line '|'
+ translatedComment += '|';
+ if (nlPos != string::npos) {
+ size_t startOfTableLinePos = translatedComment.find_first_not_of(" \t", nlPos + 1);
+ if (startOfTableLinePos != string::npos) {
+ m_tableLineLen = translatedComment.size() - startOfTableLinePos;
+ }
+ }
+ } else {
+ if (m_prevRowIsTH) {
+ // if previous row contained <th> tag, add horizontal separator
+ // but first get leading spaces, because they'll be needed for the next row
+ size_t numLeadingSpaces = translatedComment.size() - nlPos - 1;
+
+ translatedComment += string(m_tableLineLen, '-') + '\n';
+
+ if (nlPos != string::npos) {
+ translatedComment += string(numLeadingSpaces, ' ');
+ }
+ m_prevRowIsTH = false;
+ }
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end tag, </th> is ignored
+ } else {
+ translatedComment += '|';
+ m_prevRowIsTH = true;
+ }
+}
+
+void PyDocConverter::handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &) {
+ std::string htmlTagArgs = tag.data;
+ if (htmlTagArgs == "/") {
+ // end tag, </td> is ignored
+ } else {
+ translatedComment += '|';
+ }
+}
+
+void PyDocConverter::handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg) {
+ // html entities
+ translatedComment += arg;
+}
+
+void PyDocConverter::handleNewLine(DoxygenEntity &, std::string &translatedComment, const std::string &) {
+ trimWhitespace(translatedComment);
+
+ translatedComment += "\n";
+ if (!m_indent.empty())
+ translatedComment += m_indent;
+}
+
+String *PyDocConverter::makeDocumentation(Node *n) {
+ String *documentation;
+ std::string pyDocString;
+
+ // store the node, we may need it later
+ currentNode = n;
+
+ // for overloaded functions we must concat documentation for underlying overloads
+ if (Getattr(n, "sym:overloaded")) {
+ // rewind to the first overload
+ while (Getattr(n, "sym:previousSibling"))
+ n = Getattr(n, "sym:previousSibling");
+
+ std::vector<std::string> allDocumentation;
+
+ // minimal indent of any documentation comments, not initialized yet
+ size_t minIndent = static_cast<size_t>(-1);
+
+ // for each real method (not a generated overload) append the documentation
+ string oneDoc;
+ while (n) {
+ documentation = getDoxygenComment(n);
+ if (!Swig_is_generated_overload(n) && documentation) {
+ currentNode = n;
+ if (GetFlag(n, "feature:doxygen:notranslate")) {
+ String *comment = NewString("");
+ Append(comment, documentation);
+ Replaceall(comment, "\n *", "\n");
+ oneDoc = Char(comment);
+ Delete(comment);
+ } else {
+ std::list<DoxygenEntity> entityList = parser.createTree(n, documentation);
+ DoxygenEntity root("root", entityList);
+
+ oneDoc = translateSubtree(root);
+ }
+
+ // find the minimal indent of this documentation comment, we need to
+ // ensure that the entire comment is indented by it to avoid the leading
+ // parts of the other lines being simply discarded later
+ const size_t oneIndent = determineIndent(oneDoc);
+ if (oneIndent < minIndent)
+ minIndent = oneIndent;
+
+ allDocumentation.push_back(oneDoc);
+ }
+ n = Getattr(n, "sym:nextSibling");
+ }
+
+ // construct final documentation string
+ if (allDocumentation.size() > 1) {
+ string indentStr;
+ if (minIndent != static_cast<size_t>(-1))
+ indentStr.assign(minIndent, ' ');
+
+ std::ostringstream concatDocString;
+ for (size_t realOverloadCount = 0; realOverloadCount < allDocumentation.size(); realOverloadCount++) {
+ if (realOverloadCount != 0) {
+ // separate it from the preceding one.
+ concatDocString << '\n' << indentStr << "|\n\n";
+ }
+
+ oneDoc = allDocumentation[realOverloadCount];
+ trimWhitespace(oneDoc);
+ concatDocString << indentStr << "*Overload " << (realOverloadCount + 1) << ":*\n" << oneDoc;
+ }
+ pyDocString = concatDocString.str();
+ } else if (allDocumentation.size() == 1) {
+ pyDocString = *(allDocumentation.begin());
+ }
+ }
+ // for other nodes just process as normal
+ else {
+ documentation = getDoxygenComment(n);
+ if (documentation != NULL) {
+ if (GetFlag(n, "feature:doxygen:notranslate")) {
+ String *comment = NewString("");
+ Append(comment, documentation);
+ Replaceall(comment, "\n *", "\n");
+ pyDocString = Char(comment);
+ Delete(comment);
+ } else {
+ std::list<DoxygenEntity> entityList = parser.createTree(n, documentation);
+ DoxygenEntity root("root", entityList);
+ pyDocString = translateSubtree(root);
+ }
+ }
+ }
+
+ // if we got something log the result
+ if (!pyDocString.empty()) {
+
+ // remove the last '\n' since additional one is added during writing to file
+ eraseTrailingNewLine(pyDocString);
+
+ // ensure that a blank line occurs before code or math blocks
+ pyDocString = padCodeAndVerbatimBlocks(pyDocString);
+
+ if (m_flags & debug_translator) {
+ std::cout << "\n---RESULT IN PYDOC---" << std::endl;
+ std::cout << pyDocString;
+ std::cout << std::endl;
+ }
+ }
+
+ return NewString(pyDocString.c_str());
+}
+
diff --git a/contrib/tools/swig/Source/Doxygen/pydoc.h b/contrib/tools/swig/Source/Doxygen/pydoc.h
new file mode 100644
index 00000000000..880ee3069c8
--- /dev/null
+++ b/contrib/tools/swig/Source/Doxygen/pydoc.h
@@ -0,0 +1,208 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * pydoc.h
+ *
+ * Module to return documentation for nodes formatted for PyDoc
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_PYDOC_H
+#define SWIG_PYDOC_H
+
+#include <list>
+#include <string>
+#include "swig.h"
+#include "doxyentity.h"
+#include "doxytranslator.h"
+
+#define DOC_STRING_LENGTH 64 // characters per line allowed
+#define DOC_PARAM_STRING_LENGTH 30 // characters reserved for param name / type
+
+class PyDocConverter : public DoxygenTranslator {
+public:
+ PyDocConverter(int flags = 0);
+ String *makeDocumentation(Node *node);
+
+protected:
+
+ size_t m_tableLineLen;
+ bool m_prevRowIsTH;
+ std::string m_url;
+
+ /*
+ * Translate every entity in a tree, also manages sections
+ * display. Prints title for every group of tags that have
+ * a section title associated with them
+ */
+ std::string translateSubtree(DoxygenEntity &doxygenEntity);
+
+ /*
+ * Translate one entity with the appropriate handler, according
+ * to the tagHandlers
+ */
+ void translateEntity(DoxygenEntity &doxyEntity, std::string &translatedComment);
+
+ /*
+ * Typedef for the function that handles one tag
+ * arg - some string argument to easily pass it through lookup table
+ */
+ typedef void (PyDocConverter::*tagHandler) (DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Wrap the command data with the some string
+ * arg - string to wrap with, like '_' or '*'
+ */
+ void handleTagWrap(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Just prints new line
+ */
+ void handleNewLine(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print the name of tag to the output, used for escape-commands
+ */
+ void handleTagChar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Format the contents of the \exception tag or its synonyms.
+ */
+ void handleTagException(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print only the content and strip original tag
+ */
+ void handleParagraph(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
+ * Handle Doxygen verbatim tag
+ */
+ void handleVerbatimBlock(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg = std::string());
+
+ /*
+ * Handle one of the Doxygen formula-related tags.
+ */
+ void handleMath(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Handle a code snippet.
+ */
+ void handleCode(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print only data part of code
+ */
+ void handlePlainString(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /**
+ * Copies verbatim args of the tag to output, used for commands like \f$, ...
+ */
+ void handleTagVerbatim(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Print the if-elseif-else-endif section
+ */
+ void handleTagIf(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Prints the specified message, than the contents of the tag
+ * arg - message
+ */
+ void handleTagMessage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Insert 'Title: ...'
+ */
+ void handleTagPar(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Insert 'Image: ...'
+ */
+ void handleTagImage(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Format nice param description with type information
+ */
+ void handleTagParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Format the contents of the \return tag or its synonyms.
+ */
+ void handleTagReturn(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Writes text for \ref tag.
+ */
+ void handleTagRef(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML tags recognized by Doxygen, like <A ...>, <ul>, <table>, ... */
+
+ void handleDoxyHtmlTag(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /** Does not output params of HTML tag, for example in <table border='1'>
+ * 'border=1' is not written to output.
+ */
+ void handleDoxyHtmlTagNoParam(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /** Translates tag <a href = "url">text</a> to: text ("url"). */
+ void handleDoxyHtmlTag_A(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /*
+ * Handles HTML tags, which are translated to markdown-like syntax, for example
+ * <i>text</i> --> _text_. Appends arg for start HTML tag and end HTML tag.
+ */
+ void handleDoxyHtmlTag2(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML table, tag <tr> */
+ void handleDoxyHtmlTag_tr(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML table, tag <th> */
+ void handleDoxyHtmlTag_th(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML table, tag <td> */
+ void handleDoxyHtmlTag_td(DoxygenEntity &tag, std::string &translatedComment, const std::string &arg);
+
+ /* Handles HTML entities recognized by Doxygen, like &lt;, &copy;, ... */
+ void handleHtmlEntity(DoxygenEntity &, std::string &translatedComment, const std::string &arg);
+
+
+ /*
+ * Simple helper function that calculates correct parameter type
+ * of the node stored in 'currentNode'
+ * If param with specified name is not found, empty string is returned
+ */
+ std::string getParamType(std::string name);
+
+ /*
+ * Simple helper function to retrieve the parameter value
+ */
+ std::string getParamValue(std::string name);
+
+private:
+ // temporary thing, should be refactored somehow
+ Node *currentNode;
+
+ // Extra indent for the current paragraph, must be output after each new line.
+ std::string m_indent;
+
+
+ // this contains the handler pointer and one string argument
+ typedef std::map<std::string, std::pair<tagHandler, std::string> >TagHandlersMap;
+ static TagHandlersMap tagHandlers;
+
+ // this contains the sections titles, like 'Arguments:' or 'Notes:', that are printed only once
+ static std::map<std::string, std::string> sectionTitles;
+
+ // Helper functions for fillStaticTables(): make a new tag handler object.
+ TagHandlersMap::mapped_type make_handler(tagHandler handler);
+ TagHandlersMap::mapped_type make_handler(tagHandler handler, const char *arg);
+
+ void fillStaticTables();
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Include/swigconfig.h b/contrib/tools/swig/Source/Include/swigconfig.h
new file mode 100644
index 00000000000..695d1d67d26
--- /dev/null
+++ b/contrib/tools/swig/Source/Include/swigconfig.h
@@ -0,0 +1,102 @@
+/* Source/Include/swigconfig.h. Generated from swigconfig.h.in by configure. */
+/* Source/Include/swigconfig.h.in. Generated from configure.ac by autoheader. */
+
+/* define if the Boost library is available */
+/* #undef HAVE_BOOST */
+
+/* define if the compiler supports basic C++11 syntax */
+/* #undef HAVE_CXX11 */
+
+/* define if the compiler supports basic C++14 syntax */
+/* #undef HAVE_CXX14 */
+
+/* define if the compiler supports basic C++17 syntax */
+/* #undef HAVE_CXX17 */
+
+/* define if the compiler supports basic C++20 syntax */
+#define HAVE_CXX20 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the 'dl' library (-ldl). */
+#define HAVE_LIBDL 1
+
+/* Define to 1 if you have the 'dld' library (-ldld). */
+/* #undef HAVE_LIBDLD */
+
+/* Define if you have PCRE2 library */
+#define HAVE_PCRE 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdio.h> header file. */
+/* #undef HAVE_STDIO_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+/* #undef HAVE_STDLIB_H */
+
+/* Define to 1 if you have the <strings.h> header file. */
+/* #undef HAVE_STRINGS_H */
+
+/* Define to 1 if you have the <string.h> header file. */
+/* #undef HAVE_STRING_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+/* #undef HAVE_SYS_STAT_H */
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+/* #undef HAVE_SYS_TYPES_H */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+/* #undef HAVE_UNISTD_H */
+
+/* Name of package */
+#define PACKAGE "swig"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://www.swig.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "swig"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "swig 4.3.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "swig"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.3.1"
+
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+/* #undef STDC_HEADERS */
+
+/* Compiler that built SWIG */
+#define SWIG_CXX "g++"
+
+/* Directory for SWIG system-independent libraries */
+#define SWIG_LIB "/var/empty/swig-4.3.1/share/swig/4.3.1"
+
+/* Directory for SWIG system-independent libraries (Unix install on native
+ Windows) */
+#define SWIG_LIB_WIN_UNIX ""
+
+/* Platform that SWIG is built for */
+#define SWIG_PLATFORM "x86_64-pc-linux-gnu"
+
+/* Version number of package */
+#define VERSION "4.3.1"
+
+
+/* Deal with attempt by Microsoft to deprecate C standard runtime functions */
+#if defined(_MSC_VER)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
diff --git a/contrib/tools/swig/Source/Include/swigwarn.h b/contrib/tools/swig/Source/Include/swigwarn.h
new file mode 100644
index 00000000000..faf2e0431f4
--- /dev/null
+++ b/contrib/tools/swig/Source/Include/swigwarn.h
@@ -0,0 +1,342 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigwarn.h
+ *
+ * SWIG warning message numbers
+ * This file serves as the main registry of warning message numbers. Some of these
+ * numbers are used internally in the C/C++ source code of SWIG. However, some
+ * of the numbers are used in SWIG configuration files (swig.swg and others).
+ *
+ * The numbers are roughly organized into a few different classes by functionality.
+ *
+ * Even though symbolic constants are used in the SWIG source, this is
+ * not always the case in SWIG interface files. Do not change the
+ * numbers in this file.
+ *
+ * This file is used as the input for generating Lib/swigwarn.swg.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_SWIGWARN_H
+#define SWIG_SWIGWARN_H
+
+#define WARN_NONE 0
+
+/* -- Deprecated features -- */
+
+/* Unused since 4.2.0: #define WARN_DEPRECATED_EXTERN 101 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_VAL 102 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_OUT 103 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_DISABLEDOC 104 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_ENABLEDOC 105 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_DOCONLY 106 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_STYLE 107 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_LOCALSTYLE 108 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_TITLE 109 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_SECTION 110 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_SUBSECTION 111 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_SUBSUBSECTION 112 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_ADDMETHODS 113 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_READONLY 114 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_READWRITE 115 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_EXCEPT 116 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NEW 117 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_EXCEPT_TM 118 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_IGNORE_TM 119 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_OPTC 120 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NAME 121 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NOEXTERN 122 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_NODEFAULT 123 */
+/* Unused since 4.1.0: #define WARN_DEPRECATED_TYPEMAP_LANG 124 */
+/* Unused since 4.2.0: #define WARN_DEPRECATED_INPUT_FILE 125 */
+/* Unused since 4.3.0: #define WARN_DEPRECATED_NESTED_WORKAROUND 126 */
+
+/* -- Preprocessor -- */
+
+#define WARN_PP_MISSING_FILE 201
+#define WARN_PP_EVALUATION 202
+#define WARN_PP_INCLUDEALL_IMPORTALL 203
+#define WARN_PP_CPP_WARNING 204
+#define WARN_PP_CPP_ERROR 205
+#define WARN_PP_UNEXPECTED_TOKENS 206
+
+/* -- C/C++ Parser -- */
+
+#define WARN_PARSE_CLASS_KEYWORD 301
+#define WARN_PARSE_REDEFINED 302
+#define WARN_PARSE_EXTEND_UNDEF 303
+#define WARN_PARSE_UNSUPPORTED_VALUE 304
+#define WARN_PARSE_BAD_VALUE 305
+/* Unused since 1.3.32: #define WARN_PARSE_PRIVATE 306 */
+/* Unused since 4.2.0: #define WARN_PARSE_BAD_DEFAULT 307 */
+#define WARN_PARSE_NAMESPACE_ALIAS 308
+#define WARN_PARSE_PRIVATE_INHERIT 309
+/* Unused since 1.3.18: #define WARN_PARSE_TEMPLATE_REPEAT 310 */
+/* Unused since 1.3.18: #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
+/* Unused since 1.3.18: #define WARN_PARSE_MODULE_REPEAT 316 */
+#define WARN_PARSE_TEMPLATE_SP_UNDEF 317
+#define WARN_PARSE_TEMPLATE_AMBIG 318
+#define WARN_PARSE_NO_ACCESS 319
+#define WARN_PARSE_EXPLICIT_TEMPLATE 320
+#define WARN_PARSE_BUILTIN_NAME 321
+#define WARN_PARSE_REDUNDANT 322
+#define WARN_PARSE_REC_INHERITANCE 323
+#define WARN_PARSE_NESTED_TEMPLATE 324
+#define WARN_PARSE_NAMED_NESTED_CLASS 325
+#define WARN_PARSE_EXTEND_NAME 326
+#define WARN_PARSE_EXTERN_TEMPLATE 327
+#define WARN_PARSE_ASSIGNED_VALUE 328
+#define WARN_PARSE_USING_CONSTRUCTOR 329
+#define WARN_PARSE_TEMPLATE_FORWARD 330
+#define WARN_PARSE_TEMPLATE_NESTED 331
+
+#define WARN_CPP11_LAMBDA 340
+/* Unused since 3.0.11: #define WARN_CPP11_ALIAS_DECLARATION 341 */
+/* Unused since 3.0.11: #define WARN_CPP11_ALIAS_TEMPLATE 342 */
+/* Unused since 4.2.0: #define WARN_CPP11_VARIADIC_TEMPLATE 343 */
+#define WARN_CPP11_DECLTYPE 344
+#define WARN_CPP14_AUTO 345
+#define WARN_CPP11_AUTO 346
+
+#define WARN_IGNORE_OPERATOR_NEW 350 /* new */
+#define WARN_IGNORE_OPERATOR_DELETE 351 /* delete */
+#define WARN_IGNORE_OPERATOR_PLUS 352 /* + */
+#define WARN_IGNORE_OPERATOR_MINUS 353 /* - */
+#define WARN_IGNORE_OPERATOR_MUL 354 /* * */
+#define WARN_IGNORE_OPERATOR_DIV 355 /* / */
+#define WARN_IGNORE_OPERATOR_MOD 356 /* % */
+#define WARN_IGNORE_OPERATOR_XOR 357 /* ^ */
+#define WARN_IGNORE_OPERATOR_AND 358 /* & */
+#define WARN_IGNORE_OPERATOR_OR 359 /* | */
+#define WARN_IGNORE_OPERATOR_NOT 360 /* ~ */
+#define WARN_IGNORE_OPERATOR_LNOT 361 /* ! */
+#define WARN_IGNORE_OPERATOR_EQ 362 /* = */
+#define WARN_IGNORE_OPERATOR_LT 363 /* < */
+#define WARN_IGNORE_OPERATOR_GT 364 /* > */
+#define WARN_IGNORE_OPERATOR_PLUSEQ 365 /* += */
+#define WARN_IGNORE_OPERATOR_MINUSEQ 366 /* -= */
+#define WARN_IGNORE_OPERATOR_MULEQ 367 /* *= */
+#define WARN_IGNORE_OPERATOR_DIVEQ 368 /* /= */
+#define WARN_IGNORE_OPERATOR_MODEQ 369 /* %= */
+#define WARN_IGNORE_OPERATOR_XOREQ 370 /* ^= */
+#define WARN_IGNORE_OPERATOR_ANDEQ 371 /* &= */
+#define WARN_IGNORE_OPERATOR_OREQ 372 /* |= */
+#define WARN_IGNORE_OPERATOR_LSHIFT 373 /* << */
+#define WARN_IGNORE_OPERATOR_RSHIFT 374 /* >> */
+#define WARN_IGNORE_OPERATOR_LSHIFTEQ 375 /* <<= */
+#define WARN_IGNORE_OPERATOR_RSHIFTEQ 376 /* >>= */
+#define WARN_IGNORE_OPERATOR_EQUALTO 377 /* == */
+#define WARN_IGNORE_OPERATOR_NOTEQUAL 378 /* != */
+#define WARN_IGNORE_OPERATOR_LTEQUAL 379 /* <= */
+#define WARN_IGNORE_OPERATOR_GTEQUAL 380 /* >= */
+#define WARN_IGNORE_OPERATOR_LAND 381 /* && */
+#define WARN_IGNORE_OPERATOR_LOR 382 /* || */
+#define WARN_IGNORE_OPERATOR_PLUSPLUS 383 /* ++ */
+#define WARN_IGNORE_OPERATOR_MINUSMINUS 384 /* -- */
+#define WARN_IGNORE_OPERATOR_COMMA 385 /* , */
+#define WARN_IGNORE_OPERATOR_ARROWSTAR 386 /* ->* */
+#define WARN_IGNORE_OPERATOR_ARROW 387 /* -> */
+#define WARN_IGNORE_OPERATOR_CALL 388 /* () */
+#define WARN_IGNORE_OPERATOR_INDEX 389 /* [] */
+#define WARN_IGNORE_OPERATOR_UPLUS 390 /* + */
+#define WARN_IGNORE_OPERATOR_UMINUS 391 /* - */
+#define WARN_IGNORE_OPERATOR_UMUL 392 /* * */
+#define WARN_IGNORE_OPERATOR_UAND 393 /* & */
+#define WARN_IGNORE_OPERATOR_NEWARR 394 /* new [] */
+#define WARN_IGNORE_OPERATOR_DELARR 395 /* delete [] */
+#define WARN_IGNORE_OPERATOR_REF 396 /* operator *() */
+#define WARN_IGNORE_OPERATOR_LTEQUALGT 397 /* <=> */
+
+/* please leave 350-399 free for WARN_IGNORE_OPERATOR_* */
+
+/* -- Type system and typemaps -- */
+
+#define WARN_TYPE_UNDEFINED_CLASS 401
+#define WARN_TYPE_INCOMPLETE 402
+#define WARN_TYPE_ABSTRACT 403
+#define WARN_TYPE_REDEFINED 404
+#define WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405
+#define WARN_TYPE_NSPACE_SETTING 406
+
+/* Unused since 4.1.0: #define WARN_TYPEMAP_SOURCETARGET 450 */
+#define WARN_TYPEMAP_CHARLEAK 451
+/* Unused since 1.3.32: #define WARN_TYPEMAP_SWIGTYPE 452 */
+#define WARN_TYPEMAP_APPLY_UNDEF 453
+#define WARN_TYPEMAP_SWIGTYPELEAK 454
+#define WARN_TYPEMAP_WCHARLEAK 455
+
+#define WARN_TYPEMAP_IN_UNDEF 460
+#define WARN_TYPEMAP_OUT_UNDEF 461
+#define WARN_TYPEMAP_VARIN_UNDEF 462
+#define WARN_TYPEMAP_VAROUT_UNDEF 463
+#define WARN_TYPEMAP_CONST_UNDEF 464
+#define WARN_TYPEMAP_UNDEF 465
+#define WARN_TYPEMAP_VAR_UNDEF 466
+#define WARN_TYPEMAP_TYPECHECK 467
+#define WARN_TYPEMAP_THROW 468
+#define WARN_TYPEMAP_DIRECTORIN_UNDEF 469
+#define WARN_TYPEMAP_THREAD_UNSAFE 470 /* mostly used in directorout typemaps */
+#define WARN_TYPEMAP_DIRECTOROUT_UNDEF 471
+#define WARN_TYPEMAP_TYPECHECK_UNDEF 472
+#define WARN_TYPEMAP_DIRECTOROUT_PTR 473
+#define WARN_TYPEMAP_OUT_OPTIMAL_IGNORED 474
+#define WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE 475
+#define WARN_TYPEMAP_INITIALIZER_LIST 476
+#define WARN_TYPEMAP_DIRECTORTHROWS_UNDEF 477
+
+/* -- Fragments -- */
+#define WARN_FRAGMENT_NOT_FOUND 490
+
+/* -- General code generation -- */
+
+#define WARN_LANG_OVERLOAD_DECL 501
+#define WARN_LANG_OVERLOAD_CONSTRUCT 502
+#define WARN_LANG_IDENTIFIER 503
+#define WARN_LANG_RETURN_TYPE 504
+#define WARN_LANG_VARARGS 505
+#define WARN_LANG_VARARGS_KEYWORD 506
+#define WARN_LANG_NATIVE_UNIMPL 507
+#define WARN_LANG_DEREF_SHADOW 508
+#define WARN_LANG_OVERLOAD_SHADOW 509
+#define WARN_LANG_FRIEND_IGNORE 510 /* No longer issued */
+#define WARN_LANG_OVERLOAD_KEYWORD 511
+#define WARN_LANG_OVERLOAD_CONST 512
+#define WARN_LANG_CLASS_UNNAMED 513
+#define WARN_LANG_DIRECTOR_VDESTRUCT 514
+#define WARN_LANG_DISCARD_CONST 515
+#define WARN_LANG_OVERLOAD_IGNORED 516
+#define WARN_LANG_DIRECTOR_ABSTRACT 517
+#define WARN_LANG_PORTABILITY_FILENAME 518
+#define WARN_LANG_TEMPLATE_METHOD_IGNORE 519
+#define WARN_LANG_SMARTPTR_MISSING 520
+#define WARN_LANG_ILLEGAL_DESTRUCTOR 521
+#define WARN_LANG_EXTEND_CONSTRUCTOR 522
+#define WARN_LANG_EXTEND_DESTRUCTOR 523
+#define WARN_LANG_EXPERIMENTAL 524
+#define WARN_LANG_DIRECTOR_FINAL 525
+#define WARN_LANG_USING_NAME_DIFFERENT 526
+#define WARN_LANG_DEPRECATED 527
+
+/* -- Doxygen comments -- */
+
+#define WARN_DOXYGEN_UNKNOWN_COMMAND 560
+#define WARN_DOXYGEN_UNEXPECTED_END_OF_COMMENT 561
+#define WARN_DOXYGEN_COMMAND_EXPECTED 562
+#define WARN_DOXYGEN_HTML_ERROR 563
+#define WARN_DOXYGEN_COMMAND_ERROR 564
+#define WARN_DOXYGEN_UNKNOWN_CHARACTER 565
+#define WARN_DOXYGEN_UNEXPECTED_ITERATOR_VALUE 566
+
+/* -- Reserved (600-699) -- */
+
+/* -- Language module specific warnings (700 - 899) -- */
+
+/* Feel free to claim any number in this space that's not currently being used. Just make sure you
+ add an entry here */
+
+#define WARN_D_TYPEMAP_CTYPE_UNDEF 700
+#define WARN_D_TYPEMAP_IMTYPE_UNDEF 701
+#define WARN_D_TYPEMAP_DTYPE_UNDEF 702
+#define WARN_D_MULTIPLE_INHERITANCE 703
+#define WARN_D_TYPEMAP_CLASSMOD_UNDEF 704
+#define WARN_D_TYPEMAP_DBODY_UNDEF 705
+#define WARN_D_TYPEMAP_DOUT_UNDEF 706
+#define WARN_D_TYPEMAP_DIN_UNDEF 707
+#define WARN_D_TYPEMAP_DDIRECTORIN_UNDEF 708
+#define WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF 709
+#define WARN_D_EXCODE_MISSING 710
+#define WARN_D_CANTHROW_MISSING 711
+#define WARN_D_NO_DIRECTORCONNECT_ATTR 712
+#define WARN_D_NAME_COLLISION 713
+
+/* please leave 700-719 free for D */
+
+#define WARN_SCILAB_TRUNCATED_NAME 720
+
+/* please leave 720-739 free for Scilab */
+
+#define WARN_PYTHON_INDENT_MISMATCH 740
+
+/* please leave 740-749 free for Python */
+
+/* Unused since 4.2.0: #define WARN_R_MISSING_RTYPECHECK_TYPEMAP 750 */
+#define WARN_R_TYPEMAP_RTYPECHECK_UNDEF 751
+
+/* please leave 750-759 free for R */
+
+#define WARN_C_TYPEMAP_CTYPE_UNDEF 760
+#define WARN_C_UNSUPPORTTED 761
+
+/* please leave 760-779 free for C */
+
+#define WARN_RUBY_WRONG_NAME 801
+#define WARN_RUBY_MULTIPLE_INHERITANCE 802
+
+/* please leave 800-809 free for Ruby */
+
+#define WARN_JAVA_TYPEMAP_JNI_UNDEF 810
+#define WARN_JAVA_TYPEMAP_JTYPE_UNDEF 811
+#define WARN_JAVA_TYPEMAP_JSTYPE_UNDEF 812
+#define WARN_JAVA_MULTIPLE_INHERITANCE 813
+#define WARN_JAVA_TYPEMAP_GETCPTR_UNDEF 814
+#define WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF 815
+#define WARN_JAVA_TYPEMAP_JAVABODY_UNDEF 816
+#define WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF 817
+#define WARN_JAVA_TYPEMAP_JAVAIN_UNDEF 818
+#define WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF 819
+#define WARN_JAVA_TYPEMAP_JAVADIRECTOROUT_UNDEF 820
+#define WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF 821
+#define WARN_JAVA_COVARIANT_RET 822
+#define WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF 823
+#define WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC 824
+#define WARN_JAVA_NO_DIRECTORCONNECT_ATTR 825
+#define WARN_JAVA_NSPACE_WITHOUT_PACKAGE 826
+#define WARN_JAVA_TYPEMAP_INTERFACEMODIFIERS_UNDEF 827
+
+/* please leave 810-829 free for Java */
+
+#define WARN_CSHARP_TYPEMAP_CTYPE_UNDEF 830
+#define WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF 831
+#define WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF 832
+#define WARN_CSHARP_MULTIPLE_INHERITANCE 833
+#define WARN_CSHARP_TYPEMAP_GETCPTR_UNDEF 834
+#define WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF 835
+#define WARN_CSHARP_TYPEMAP_CSBODY_UNDEF 836
+#define WARN_CSHARP_TYPEMAP_CSOUT_UNDEF 837
+#define WARN_CSHARP_TYPEMAP_CSIN_UNDEF 838
+#define WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF 839
+#define WARN_CSHARP_TYPEMAP_CSDIRECTOROUT_UNDEF 840
+#define WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF 841
+#define WARN_CSHARP_COVARIANT_RET 842
+#define WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF 843
+#define WARN_CSHARP_EXCODE 844
+#define WARN_CSHARP_CANTHROW 845
+#define WARN_CSHARP_NO_DIRECTORCONNECT_ATTR 846
+#define WARN_CSHARP_TYPEMAP_INTERFACEMODIFIERS_UNDEF 847
+
+/* please leave 830-849 free for C# */
+
+/* 850-860 were used by Modula 3 (removed in SWIG 4.1.0) - avoid reusing for now */
+
+#define WARN_PHP_MULTIPLE_INHERITANCE 870
+#define WARN_PHP_UNKNOWN_PRAGMA 871
+/* Unused since 4.1.0: define WARN_PHP_PUBLIC_BASE 872 */
+
+/* please leave 870-889 free for PHP */
+
+#define WARN_GO_NAME_CONFLICT 890
+
+/* please leave 890-899 free for Go */
+
+/* -- User defined warnings (900 - 999) -- */
+
+#endif
diff --git a/contrib/tools/swig/Source/Modules/README b/contrib/tools/swig/Source/Modules/README
new file mode 100644
index 00000000000..058779d227d
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/README
@@ -0,0 +1,9 @@
+06/25/2002
+
+This directory contains all of the SWIG language modules. Many of these
+modules contain code that dates back to SWIG1.0. The module API has changed
+a lot in the development releases so this is fairly messy. We're working on
+cleaning it up, but you'll have to bear with us until it's done.
+
+-- Dave
+
diff --git a/contrib/tools/swig/Source/Modules/allocate.cxx b/contrib/tools/swig/Source/Modules/allocate.cxx
new file mode 100644
index 00000000000..efc57772aeb
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/allocate.cxx
@@ -0,0 +1,1605 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * allocate.cxx
+ *
+ * This module also has two main purposes modifying the parse tree.
+ *
+ * First, it is responsible for adding in using declarations from base class
+ * members into the parse tree.
+ *
+ * Second, after each class declaration, it analyses if the class/struct supports
+ * default constructors and destructors in C++. There are several rules that
+ * define this behavior including pure abstract methods, private sections,
+ * and non-default constructors in base classes. See the ARM or
+ * Doc/Manual/SWIGPlus.html for details.
+ *
+ * Once the analysis is complete, the non-explicit/implied default constructors
+ * and destructors are added to the parse tree. Implied copy constructors are
+ * added too if requested via the copyctor feature. Detection of implied
+ * assignment operators is also handled as assigment is required in the generated
+ * code for variable setters.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static int virtual_elimination_mode = 0; /* set to 0 on default */
+
+/* Set virtual_elimination_mode */
+void Wrapper_virtual_elimination_mode_set(int flag) {
+ virtual_elimination_mode = flag;
+}
+
+/* Helper function to assist with abstract class checking.
+ This is a major hack. Sorry. */
+
+extern "C" {
+ static String *search_decl = 0; /* Declarator being searched */
+ static Node *check_implemented(Node *n) {
+ String *decl;
+ if (!n)
+ return 0;
+ while (n) {
+ if (Strcmp(nodeType(n), "cdecl") == 0) {
+ decl = Getattr(n, "decl");
+ if (SwigType_isfunction(decl)) {
+ SwigType *decl1 = SwigType_typedef_resolve_all(decl);
+ SwigType *decl2 = SwigType_pop_function(decl1);
+ if (Strcmp(decl2, search_decl) == 0) {
+ if (!GetFlag(n, "abstract")) {
+ Delete(decl1);
+ Delete(decl2);
+ return n;
+ }
+ }
+ Delete(decl1);
+ Delete(decl2);
+ }
+ }
+ n = Getattr(n, "csym:nextSibling");
+ }
+ return 0;
+ }
+}
+
+class Allocate:public Dispatcher {
+ Node *inclass;
+ int extendmode;
+
+ /* Checks if a function, n, is the same as any in the base class, ie if the method is polymorphic.
+ * Also checks for methods which will be hidden (ie a base has an identical non-virtual method).
+ * Both methods must have public access for a match to occur. */
+ int function_is_defined_in_bases(Node *n, Node *bases) {
+
+ if (!bases)
+ return 0;
+
+ String *this_decl = Getattr(n, "decl");
+ if (!this_decl)
+ return 0;
+
+ String *name = Getattr(n, "name");
+ String *this_type = Getattr(n, "type");
+ String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
+
+ // Search all base classes for methods with same signature
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ Node *base = firstChild(b);
+ while (base) {
+ if (Strcmp(nodeType(base), "extend") == 0) {
+ // Loop through all the %extend methods
+ Node *extend = firstChild(base);
+ while (extend) {
+ if (function_is_defined_in_bases_seek(n, b, extend, this_decl, name, this_type, resolved_decl)) {
+ Delete(resolved_decl);
+ return 1;
+ }
+ extend = nextSibling(extend);
+ }
+ } else if (Strcmp(nodeType(base), "using") == 0) {
+ // Loop through all the using declaration methods
+ Node *usingdecl = firstChild(base);
+ while (usingdecl) {
+ if (function_is_defined_in_bases_seek(n, b, usingdecl, this_decl, name, this_type, resolved_decl)) {
+ Delete(resolved_decl);
+ return 1;
+ }
+ usingdecl = nextSibling(usingdecl);
+ }
+ } else {
+ // normal methods
+ if (function_is_defined_in_bases_seek(n, b, base, this_decl, name, this_type, resolved_decl)) {
+ Delete(resolved_decl);
+ return 1;
+ }
+ }
+ base = nextSibling(base);
+ }
+ }
+ Delete(resolved_decl);
+ resolved_decl = 0;
+ for (int j = 0; j < Len(bases); j++) {
+ Node *b = Getitem(bases, j);
+ if (function_is_defined_in_bases(n, Getattr(b, "allbases")))
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Helper function for function_is_defined_in_bases */
+ int function_is_defined_in_bases_seek(Node *n, Node *b, Node *base, String *this_decl, String *name, String *this_type, String *resolved_decl) {
+
+ String *base_decl = Getattr(base, "decl");
+ SwigType *base_type = Getattr(base, "type");
+ if (base_decl && base_type) {
+ if (checkAttribute(base, "name", name) && !GetFlag(b, "feature:ignore") /* whole class is ignored */ ) {
+ if (SwigType_isfunction(resolved_decl) && SwigType_isfunction(base_decl)) {
+ // We have found a method that has the same name as one in a base class
+ bool covariant_returntype = false;
+ bool returntype_match = Strcmp(base_type, this_type) == 0 ? true : false;
+ bool decl_match = Strcmp(base_decl, this_decl) == 0 ? true : false;
+ if (returntype_match && decl_match) {
+ // Exact match - we have found a method with identical signature
+ // No typedef resolution was done, but skipping it speeds things up slightly
+ } else {
+ // Either we have:
+ // 1) matching methods but are one of them uses a different typedef (return type or parameter) to the one in base class' method
+ // 2) matching polymorphic methods with covariant return type
+ // 3) a non-matching method (ie an overloaded method of some sort)
+ // 4) a matching method which is not polymorphic, ie it hides the base class' method
+
+ // Check if fully resolved return types match (including
+ // covariant return types)
+ if (!returntype_match) {
+ String *this_returntype = function_return_type(n);
+ String *base_returntype = function_return_type(base);
+ returntype_match = Strcmp(this_returntype, base_returntype) == 0 ? true : false;
+ if (!returntype_match) {
+ covariant_returntype = SwigType_issubtype(this_returntype, base_returntype) ? true : false;
+ returntype_match = covariant_returntype;
+ }
+ Delete(this_returntype);
+ Delete(base_returntype);
+ }
+ // The return types must match at this point, for the whole method to match
+ if (returntype_match && !decl_match) {
+ // Now need to check the parameter list
+ // First do an inexpensive parameter count
+ ParmList *this_parms = Getattr(n, "parms");
+ ParmList *base_parms = Getattr(base, "parms");
+ if (ParmList_len(this_parms) == ParmList_len(base_parms)) {
+ // Number of parameters are the same, now check that all the parameters match
+ SwigType *base_fn = NewString("");
+ SwigType *this_fn = NewString("");
+ SwigType_add_function(base_fn, base_parms);
+ SwigType_add_function(this_fn, this_parms);
+ base_fn = SwigType_typedef_resolve_all(base_fn);
+ this_fn = SwigType_typedef_resolve_all(this_fn);
+ if (Strcmp(base_fn, this_fn) == 0) {
+ // Finally check that the qualifiers match
+ int base_qualifier = SwigType_isqualifier(resolved_decl);
+ int this_qualifier = SwigType_isqualifier(base_decl);
+ if (base_qualifier == this_qualifier) {
+ decl_match = true;
+ }
+ }
+ Delete(base_fn);
+ Delete(this_fn);
+ }
+ }
+ }
+ //Printf(stderr,"look %s %s %d %d\n",base_decl, this_decl, returntype_match, decl_match);
+
+ if (decl_match && returntype_match) {
+ // Found an identical method in the base class
+ bool this_wrapping_protected_members = is_member_director(n) ? true : false; // This should really check for dirprot rather than just being a director method
+ bool base_wrapping_protected_members = is_member_director(base) ? true : false; // This should really check for dirprot rather than just being a director method
+ bool both_have_public_access = is_public(n) && is_public(base);
+ bool both_have_protected_access = (is_protected(n) && this_wrapping_protected_members) && (is_protected(base) && base_wrapping_protected_members);
+ bool both_have_private_access = is_private(n) && is_private(base);
+ if (checkAttribute(base, "storage", "virtual")) {
+ // Found a polymorphic method.
+ // Mark the polymorphic method, in case the virtual keyword was not used.
+ Setattr(n, "storage", "virtual");
+ if (!GetFlag(b, "feature:interface")) { // interface implementation neither hides nor overrides
+ if (both_have_public_access || both_have_protected_access) {
+ if (!is_non_public_base(inclass, b))
+ Setattr(n, "override", base); // Note C# definition of override, ie access must be the same
+ }
+ else if (!both_have_private_access) {
+ // Different access
+ if (this_wrapping_protected_members || base_wrapping_protected_members)
+ if (!is_non_public_base(inclass, b))
+ Setattr(n, "hides", base); // Note C# definition of hiding, ie hidden if access is different
+ }
+ }
+ // Try and find the most base's covariant return type
+ SwigType *most_base_covariant_type = Getattr(base, "covariant");
+ if (!most_base_covariant_type && covariant_returntype)
+ most_base_covariant_type = function_return_type(base, false);
+
+ if (!most_base_covariant_type) {
+ // Eliminate the derived virtual method.
+ if (virtual_elimination_mode && !is_member_director(n))
+ if (both_have_public_access)
+ if (!is_non_public_base(inclass, b))
+ if (!Swig_symbol_isoverloaded(n)) {
+ // Don't eliminate if an overloaded method as this hides the method
+ // in the scripting languages: the dispatch function will hide the base method if ignored.
+ SetFlag(n, "feature:ignore");
+ SetFlag(n, "fvirtual:ignore");
+ }
+ } else {
+ // Some languages need to know about covariant return types
+ Setattr(n, "covariant", most_base_covariant_type);
+ }
+
+ } else {
+ // Found an identical method in the base class, but it is not polymorphic.
+ if (both_have_public_access || both_have_protected_access)
+ if (!is_non_public_base(inclass, b))
+ Setattr(n, "hides", base);
+ }
+ if (both_have_public_access || both_have_protected_access)
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+ /* Determines whether the base class, b, is in the list of private
+ * or protected base classes for class n. */
+ bool is_non_public_base(Node *n, Node *b) {
+ bool non_public_base = false;
+ Node *bases = Getattr(n, "privatebases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *base = Getitem(bases, i);
+ if (base == b)
+ non_public_base = true;
+ }
+ }
+ bases = Getattr(n, "protectedbases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *base = Getitem(bases, i);
+ if (base == b)
+ non_public_base = true;
+ }
+ }
+ return non_public_base;
+ }
+
+ /* Returns the return type for a function. The node n should be a function.
+ If resolve is true the fully returned type is fully resolved.
+ Caller is responsible for deleting returned string. */
+ String *function_return_type(Node *n, bool resolve = true) {
+ String *decl = Getattr(n, "decl");
+ SwigType *type = Getattr(n, "type");
+ String *ty = NewString(type);
+ SwigType_push(ty, decl);
+ if (SwigType_isqualifier(ty))
+ Delete(SwigType_pop(ty));
+ Delete(SwigType_pop_function(ty));
+ if (resolve) {
+ String *unresolved = ty;
+ ty = SwigType_typedef_resolve_all(unresolved);
+ Delete(unresolved);
+ }
+ return ty;
+ }
+
+ /* Checks if a class member is the same as inherited from the class bases */
+ int class_member_is_defined_in_bases(Node *member, Node *classnode) {
+ Node *bases; /* bases is the closest ancestors of classnode */
+ int defined = 0;
+
+ bases = Getattr(classnode, "allbases");
+ if (!bases)
+ return 0;
+
+ {
+ int old_mode = virtual_elimination_mode;
+ if (is_member_director(classnode, member))
+ virtual_elimination_mode = 0;
+
+ if (function_is_defined_in_bases(member, bases)) {
+ defined = 1;
+ }
+
+ virtual_elimination_mode = old_mode;
+ }
+
+ if (defined)
+ return 1;
+ else
+ return 0;
+ }
+
+ /* Checks to see if a class is abstract through inheritance,
+ and saves the first node that seems to be abstract.
+ */
+ int is_abstract_inherit(Node *n, Node *base = 0, int first = 0) {
+ if (!first && (base == n))
+ return 0;
+ if (!base) {
+ /* Root node */
+ Symtab *stab = Getattr(n, "symtab"); /* Get symbol table for node */
+ Symtab *oldtab = Swig_symbol_setscope(stab);
+ int ret = is_abstract_inherit(n, n, 1);
+ Swig_symbol_setscope(oldtab);
+ return ret;
+ }
+ List *abstracts = Getattr(base, "abstracts");
+ if (abstracts) {
+ int dabstract = 0;
+ int len = Len(abstracts);
+ for (int i = 0; i < len; i++) {
+ Node *nn = Getitem(abstracts, i);
+ String *name = Getattr(nn, "name");
+ if (!name)
+ continue;
+ if (Strchr(name, '~'))
+ continue; /* Don't care about destructors */
+ String *base_decl = Getattr(nn, "decl");
+ if (base_decl)
+ base_decl = SwigType_typedef_resolve_all(base_decl);
+ if (SwigType_isfunction(base_decl))
+ search_decl = SwigType_pop_function(base_decl);
+ Node *dn = Swig_symbol_clookup_local_check(name, 0, check_implemented);
+ Delete(search_decl);
+ Delete(base_decl);
+
+ if (!dn) {
+ List *nabstracts = Getattr(n, "abstracts");
+ if (!nabstracts) {
+ nabstracts = NewList();
+ Setattr(n, "abstracts", nabstracts);
+ Delete(nabstracts);
+ }
+ Append(nabstracts, nn);
+ if (!Getattr(n, "abstracts:firstnode")) {
+ Setattr(n, "abstracts:firstnode", nn);
+ }
+ dabstract = base != n;
+ }
+ }
+ if (dabstract)
+ return 1;
+ }
+ List *bases = Getattr(base, "allbases");
+ if (!bases)
+ return 0;
+ for (int i = 0; i < Len(bases); i++) {
+ if (is_abstract_inherit(n, Getitem(bases, i))) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+
+ /* Grab methods used by smart pointers */
+
+ List *smart_pointer_methods(Node *cls, List *methods, int isconst, String *classname = 0) {
+ if (!methods) {
+ methods = NewList();
+ }
+
+ Node *c = firstChild(cls);
+
+ while (c) {
+ if (Getattr(c, "error") || GetFlag(c, "feature:ignore")) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (!isconst && (Strcmp(nodeType(c), "extend") == 0)) {
+ methods = smart_pointer_methods(c, methods, isconst, Getattr(cls, "name"));
+ } else if (Strcmp(nodeType(c), "cdecl") == 0) {
+ if (!GetFlag(c, "feature:ignore")) {
+ String *storage = Getattr(c, "storage");
+ if (!((Cmp(storage, "typedef") == 0))
+ && !Strstr(storage, "friend")) {
+ String *name = Getattr(c, "name");
+ String *symname = Getattr(c, "sym:name");
+ Node *e = Swig_symbol_clookup_local(name, 0);
+ if (e && is_public(e) && !GetFlag(e, "feature:ignore") && (Cmp(symname, Getattr(e, "sym:name")) == 0)) {
+ Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(e), Getline(e), "Declaration of '%s' shadows declaration accessible via operator->(),\n", name);
+ Swig_warning(WARN_LANG_DEREF_SHADOW, Getfile(c), Getline(c), "previous declaration of '%s'.\n", name);
+ } else {
+ /* Make sure node with same name doesn't already exist */
+ int k;
+ int match = 0;
+ for (k = 0; k < Len(methods); k++) {
+ e = Getitem(methods, k);
+ if (Cmp(symname, Getattr(e, "sym:name")) == 0) {
+ match = 1;
+ break;
+ }
+ if (!Getattr(e, "sym:name") && (Cmp(name, Getattr(e, "name")) == 0)) {
+ match = 1;
+ break;
+ }
+ }
+ if (!match) {
+ Node *cc = c;
+ while (cc) {
+ Node *cp = cc;
+ if (classname) {
+ Setattr(cp, "extendsmartclassname", classname);
+ }
+ Setattr(cp, "allocate:smartpointeraccess", "1");
+ /* If constant, we have to be careful */
+ if (isconst) {
+ SwigType *decl = Getattr(cp, "decl");
+ if (decl) {
+ if (SwigType_isfunction(decl)) { /* If method, we only add if it's a const method */
+ if (SwigType_isconst(decl)) {
+ Append(methods, cp);
+ }
+ } else {
+ Append(methods, cp);
+ }
+ } else {
+ Append(methods, cp);
+ }
+ } else {
+ Append(methods, cp);
+ }
+ cc = Getattr(cc, "sym:nextSibling");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ c = nextSibling(c);
+ }
+ /* Look for methods in base classes */
+ {
+ Node *bases = Getattr(cls, "bases");
+ int k;
+ for (k = 0; k < Len(bases); k++) {
+ smart_pointer_methods(Getitem(bases, k), methods, isconst);
+ }
+ }
+ /* Remove protected/private members */
+ {
+ for (int i = 0; i < Len(methods);) {
+ Node *n = Getitem(methods, i);
+ if (!is_public(n)) {
+ Delitem(methods, i);
+ continue;
+ }
+ i++;
+ }
+ }
+ return methods;
+ }
+
+ void mark_exception_classes(ParmList *p) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ SwigType *t = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isreference(t) || SwigType_ispointer(t) || SwigType_isarray(t)) {
+ Delete(SwigType_pop(t));
+ }
+ Node *c = Swig_symbol_clookup(t, 0);
+ if (c) {
+ if (!GetFlag(c, "feature:exceptionclass")) {
+ SetFlag(c, "feature:exceptionclass");
+ }
+ }
+ p = nextSibling(p);
+ Delete(t);
+ }
+ }
+
+
+ void process_exceptions(Node *n) {
+ ParmList *catchlist = 0;
+ /*
+ the "catchlist" attribute is used to emit the block
+
+ try {$action;}
+ catch <list of catches>;
+
+ in emit.cxx
+
+ and is either constructed from the "feature:catches" feature
+ or copied from the node "throws" list.
+ */
+ String *scatchlist = Getattr(n, "feature:catches");
+ if (scatchlist) {
+ catchlist = Swig_cparse_parms(scatchlist, n);
+ if (catchlist) {
+ Setattr(n, "catchlist", catchlist);
+ mark_exception_classes(catchlist);
+ Delete(catchlist);
+ }
+ }
+ ParmList *throws = Getattr(n, "throws");
+ if (throws) {
+ /* if there is no explicit catchlist, we catch everything in the throws list */
+ if (!catchlist) {
+ Setattr(n, "catchlist", throws);
+ }
+ mark_exception_classes(throws);
+ }
+ }
+
+/* -----------------------------------------------------------------------------
+ * clone_member_for_using_declaration()
+ *
+ * Create a new member (constructor or method) by copying it from member c, ready
+ * for adding as a child to the using declaration node n.
+ * ----------------------------------------------------------------------------- */
+
+ Node *clone_member_for_using_declaration(Node *c, Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(c, "decl");
+ String *symname = Getattr(n, "sym:name");
+ int match = 0;
+
+ Node *over = Getattr(n, "sym:overloaded");
+ while (over) {
+ String *odecl = Getattr(over, "decl");
+ if (Cmp(decl, odecl) == 0) {
+ match = 1;
+ break;
+ }
+ over = Getattr(over, "sym:nextSibling");
+ }
+
+ if (match) {
+ /* Don't generate a method if the method is overridden in this class,
+ * for example don't generate another m(bool) should there be a Base::m(bool) :
+ * struct Derived : Base {
+ * void m(bool);
+ * using Base::m;
+ * };
+ */
+ return 0;
+ }
+
+ Node *nn = copyNode(c);
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ if (!Getattr(nn, "sym:name"))
+ Setattr(nn, "sym:name", symname);
+ Symtab *st = Getattr(n, "sym:symtab");
+ assert(st);
+ Setattr(nn, "sym:symtab", st);
+ // The real parent is the "using" declaration node, but subsequent code generally handles
+ // and expects a class member to point to the parent class node
+ Setattr(nn, "parentNode", parent);
+
+ if (Equal(nodeType(c), "constructor")) {
+ Setattr(nn, "name", Getattr(n, "name"));
+ Setattr(nn, "sym:name", Getattr(n, "sym:name"));
+ // Note that the added constructor's access is the same as that of
+ // the base class' constructor not of the using declaration.
+ // It has already been set correctly and should not be changed.
+ } else {
+ // Access might be different from the method in the base class
+ Delattr(nn, "access");
+ Setattr(nn, "access", Getattr(n, "access"));
+ }
+
+ if (!GetFlag(nn, "feature:ignore")) {
+ ParmList *parms = CopyParmList(Getattr(c, "parms"));
+ int is_pointer = SwigType_ispointer_return(Getattr(nn, "decl"));
+ int is_void = checkAttribute(nn, "type", "void") && !is_pointer;
+ Setattr(nn, "parms", parms);
+ Delete(parms);
+ if (Getattr(n, "feature:extend")) {
+ String *ucode = is_void ? NewStringf("{ self->%s(", Getattr(n, "uname")) : NewStringf("{ return self->%s(", Getattr(n, "uname"));
+
+ for (ParmList *p = parms; p;) {
+ Append(ucode, Getattr(p, "name"));
+ p = nextSibling(p);
+ if (p)
+ Append(ucode, ",");
+ }
+ Append(ucode, "); }");
+ Setattr(nn, "code", ucode);
+ Delete(ucode);
+ }
+ ParmList *throw_parm_list = Getattr(c, "throws");
+ if (throw_parm_list)
+ Setattr(nn, "throws", CopyParmList(throw_parm_list));
+ } else {
+ Delete(nn);
+ nn = 0;
+ }
+ return nn;
+ }
+
+/* -----------------------------------------------------------------------------
+ * add_member_for_using_declaration()
+ *
+ * Add a new member (constructor or method) by copying it from member c.
+ * Add it into the linked list of members under the using declaration n (ccount,
+ * unodes and last_unodes are used for this).
+ * ----------------------------------------------------------------------------- */
+
+ void add_member_for_using_declaration(Node *c, Node *n, int &ccount, Node *&unodes, Node *&last_unodes) {
+ if (GetFlag(c, "fvirtual:ignore")) {
+ // This node was ignored by fvirtual. Thus, it has feature:ignore set.
+ // However, we may have new sibling overrides that will make us want to keep it.
+ // Hence, temporarily unset the feature:ignore flag.
+ UnsetFlag(c, "feature:ignore");
+ }
+
+ if (!(Swig_storage_isstatic(c)
+ || checkAttribute(c, "storage", "typedef")
+ || Strstr(Getattr(c, "storage"), "friend")
+ || (Getattr(c, "feature:extend") && !Getattr(c, "code"))
+ || GetFlag(c, "feature:ignore"))) {
+
+ String *symname = Getattr(n, "sym:name");
+ String *csymname = Getattr(c, "sym:name");
+ Node *parent = parentNode(n);
+ bool using_inherited_constructor_symname_okay = Equal(nodeType(c), "constructor") && Equal(symname, Getattr(parent, "sym:name"));
+ if (!csymname || Equal(csymname, symname) || using_inherited_constructor_symname_okay) {
+ Node *nn = clone_member_for_using_declaration(c, n);
+ if (nn) {
+ ccount++;
+ if (!last_unodes) {
+ last_unodes = nn;
+ unodes = nn;
+ } else {
+ Setattr(nn, "previousSibling", last_unodes);
+ Setattr(last_unodes, "nextSibling", nn);
+ Setattr(nn, "sym:previousSibling", last_unodes);
+ Setattr(last_unodes, "sym:nextSibling", nn);
+ Setattr(nn, "sym:overloaded", unodes);
+ Setattr(unodes, "sym:overloaded", unodes);
+ last_unodes = nn;
+ }
+ }
+ } else {
+ Swig_warning(WARN_LANG_USING_NAME_DIFFERENT, Getfile(n), Getline(n), "Using declaration %s, with name '%s', is not actually using\n", SwigType_namestr(Getattr(n, "uname")), symname);
+ Swig_warning(WARN_LANG_USING_NAME_DIFFERENT, Getfile(c), Getline(c), "the method from %s, with name '%s', as the names are different.\n", Swig_name_decl(c), csymname);
+ }
+ }
+ if (GetFlag(c, "fvirtual:ignore")) {
+ SetFlag(c, "feature:ignore");
+ }
+ }
+
+ bool is_assignable_type(const SwigType *type) {
+ bool assignable = true;
+ if (SwigType_type(type) == T_USER) {
+ Node *cn = Swig_symbol_clookup(type, 0);
+ if (cn) {
+ if ((Strcmp(nodeType(cn), "class") == 0)) {
+ if (Getattr(cn, "allocate:noassign")) {
+ assignable = false;
+ }
+ }
+ }
+ } else if (SwigType_isarray(type)) {
+ SwigType *array_type = SwigType_array_type(type);
+ assignable = is_assignable_type(array_type);
+ } else if (SwigType_isreference(type) || SwigType_isrvalue_reference(type)) {
+ SwigType *base_type = Copy(type);
+ SwigType_del_element(base_type);
+ assignable = is_assignable_type(base_type);
+ Delete(base_type);
+ }
+ return assignable;
+ }
+
+ bool is_assignable(Node *n, bool &is_reference, bool &is_const) {
+ SwigType *ty = Copy(Getattr(n, "type"));
+ SwigType_push(ty, Getattr(n, "decl"));
+ SwigType *ftd = SwigType_typedef_resolve_all(ty);
+ SwigType *td = SwigType_strip_qualifiers(ftd);
+
+ bool assignable = is_assignable_type(td);
+ is_reference = SwigType_isreference(td) || SwigType_isrvalue_reference(td);
+ is_const = !SwigType_ismutable(ftd);
+ if (GetFlag(n, "hasconsttype"))
+ is_const = true;
+
+ Delete(ty);
+ Delete(ftd);
+ Delete(td);
+ return assignable;
+ }
+
+public:
+Allocate():
+ inclass(NULL), extendmode(0) {
+ }
+
+ virtual int top(Node *n) {
+ cplus_mode = PUBLIC;
+ inclass = 0;
+ extendmode = 0;
+ emit_children(n);
+ return SWIG_OK;
+ }
+
+ virtual int importDirective(Node *n) {
+ return emit_children(n);
+ }
+ virtual int includeDirective(Node *n) {
+ return emit_children(n);
+ }
+ virtual int externDeclaration(Node *n) {
+ return emit_children(n);
+ }
+ virtual int namespaceDeclaration(Node *n) {
+ return emit_children(n);
+ }
+ virtual int extendDirective(Node *n) {
+ extendmode = 1;
+ emit_children(n);
+ extendmode = 0;
+ return SWIG_OK;
+ }
+
+ virtual int classDeclaration(Node *n) {
+ Symtab *symtab = Swig_symbol_current();
+ Swig_symbol_setscope(Getattr(n, "symtab"));
+ save_value<Node*> oldInclass(inclass);
+ save_value<AccessMode> oldAcessMode(cplus_mode);
+ save_value<int> oldExtendMode(extendmode);
+ if (Getattr(n, "template"))
+ extendmode = 0;
+ if (!CPlusPlus) {
+ /* Always have default constructors/destructors in C */
+ Setattr(n, "allocate:default_constructor", "1");
+ Setattr(n, "allocate:default_destructor", "1");
+ }
+
+ if (Getattr(n, "allocate:visit")) {
+ Swig_symbol_setscope(symtab);
+ return SWIG_OK;
+ }
+ Setattr(n, "allocate:visit", "1");
+
+ /* Always visit base classes first */
+ {
+ List *bases = Getattr(n, "bases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ classDeclaration(b);
+ }
+ }
+ }
+ inclass = n;
+ String *kind = Getattr(n, "kind");
+ if (Strcmp(kind, "class") == 0) {
+ cplus_mode = PRIVATE;
+ } else {
+ cplus_mode = PUBLIC;
+ }
+
+ emit_children(n);
+
+ /* Check if the class is abstract via inheritance. This might occur if a class didn't have
+ any pure virtual methods of its own, but it didn't implement all of the pure methods in
+ a base class */
+ if (!Getattr(n, "abstracts") && is_abstract_inherit(n)) {
+ if (((Getattr(n, "allocate:public_constructor") || (!GetFlag(n, "feature:nodefault") && !Getattr(n, "allocate:has_constructor"))))) {
+ if (!GetFlag(n, "feature:notabstract")) {
+ Node *na = Getattr(n, "abstracts:firstnode");
+ if (na) {
+ Swig_warning(WARN_TYPE_ABSTRACT, Getfile(n), Getline(n),
+ "Class '%s' might be abstract, " "no constructors generated,\n", SwigType_namestr(Getattr(n, "name")));
+ Swig_warning(WARN_TYPE_ABSTRACT, Getfile(na), Getline(na), "Method %s might not be implemented.\n", Swig_name_decl(na));
+ if (!Getattr(n, "abstracts")) {
+ List *abstracts = NewList();
+ Append(abstracts, na);
+ Setattr(n, "abstracts", abstracts);
+ Delete(abstracts);
+ }
+ }
+ }
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_constructor")) {
+ /* No constructor is defined. We need to check a few things */
+ /* If class is abstract. No default constructor. Sorry */
+ if (Getattr(n, "abstracts")) {
+ Delattr(n, "allocate:default_constructor");
+ }
+ if (!Getattr(n, "allocate:default_constructor")) {
+ // No default constructor if either the default constructor or copy constructor is declared as deleted
+ if (!GetFlag(n, "allocate:deleted_default_constructor") && !GetFlag(n, "allocate:deleted_copy_constructor")) {
+ /* Check base classes */
+ List *bases = Getattr(n, "allbases");
+ int allows_default = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow default constructor, we don't allow it either */
+ if (!Getattr(n, "allocate:default_constructor") && (!Getattr(n, "allocate:default_base_constructor"))) {
+ allows_default = 0;
+ }
+ /* not constructible if base destructor is deleted */
+ if (Getattr(n, "allocate:deleted_default_destructor")) {
+ allows_default = 0;
+ }
+ }
+ if (allows_default) {
+ Setattr(n, "allocate:default_constructor", "1");
+ }
+ }
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_copy_constructor")) {
+ if (Getattr(n, "abstracts")) {
+ Delattr(n, "allocate:copy_constructor");
+ Delattr(n, "allocate:copy_constructor_non_const");
+ }
+ if (!Getattr(n, "allocate:copy_constructor")) {
+ // No copy constructor if the copy constructor is declared as deleted
+ if (!GetFlag(n, "allocate:deleted_copy_constructor")) {
+ /* Check base classes */
+ List *bases = Getattr(n, "allbases");
+ int allows_copy = 1;
+ int must_be_copy_non_const = 0;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow copy constructor, we don't allow it either */
+ if (!Getattr(n, "allocate:copy_constructor") && (!Getattr(n, "allocate:copy_base_constructor"))) {
+ allows_copy = 0;
+ }
+ /* not constructible if base destructor is deleted */
+ if (Getattr(n, "allocate:deleted_default_destructor")) {
+ allows_copy = 0;
+ }
+ if (Getattr(n, "allocate:copy_constructor_non_const") || (Getattr(n, "allocate:copy_base_constructor_non_const"))) {
+ must_be_copy_non_const = 1;
+ }
+ }
+ if (allows_copy) {
+ Setattr(n, "allocate:copy_constructor", "1");
+ }
+ if (must_be_copy_non_const) {
+ Setattr(n, "allocate:copy_constructor_non_const", "1");
+ }
+ }
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_destructor")) {
+ /* No destructor was defined */
+ /* No destructor if the destructor is declared as deleted */
+ if (!GetFlag(n, "allocate:deleted_default_destructor")) {
+ /* Check base classes */
+ List *bases = Getattr(n, "allbases");
+ int allows_destruct = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow default destructor, we don't allow it either */
+ if (!Getattr(n, "allocate:default_destructor") && (!Getattr(n, "allocate:default_base_destructor"))) {
+ allows_destruct = 0;
+ }
+ }
+ if (allows_destruct) {
+ Setattr(n, "allocate:default_destructor", "1");
+ }
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_assign")) {
+ /* No assignment operator was defined */
+ List *bases = Getattr(n, "allbases");
+ int allows_assign = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow assignment, we don't allow it either */
+ if (Getattr(n, "allocate:noassign")) {
+ allows_assign = 0;
+ }
+ }
+ /* If any member variables are non assignable, this class is also non assignable by default */
+ if (GetFlag(n, "allocate:has_nonassignable")) {
+ allows_assign = 0;
+ }
+ if (!allows_assign) {
+ Setattr(n, "allocate:noassign", "1");
+ }
+ }
+
+ if (!Getattr(n, "allocate:has_new")) {
+ /* No new operator was defined */
+ List *bases = Getattr(n, "allbases");
+ int allows_new = 1;
+
+ for (int i = 0; i < Len(bases); i++) {
+ Node *n = Getitem(bases, i);
+ /* If base class does not allow new operator, we don't allow it either */
+ if (Getattr(n, "allocate:has_new")) {
+ allows_new = !Getattr(n, "allocate:nonew");
+ }
+ }
+ if (!allows_new) {
+ Setattr(n, "allocate:nonew", "1");
+ }
+ }
+
+ /* Check if base classes allow smart pointers, but might be hidden */
+ if (!Getattr(n, "allocate:smartpointer")) {
+ Node *sp = Swig_symbol_clookup("operator ->", 0);
+ if (sp) {
+ /* Look for parent */
+ Node *p = parentNode(sp);
+ if (Strcmp(nodeType(p), "extend") == 0) {
+ p = parentNode(p);
+ }
+ if (Strcmp(nodeType(p), "class") == 0) {
+ if (GetFlag(p, "feature:ignore")) {
+ Setattr(n, "allocate:smartpointer", Getattr(p, "allocate:smartpointer"));
+ }
+ }
+ }
+ }
+
+ Swig_interface_propagate_methods(n);
+
+ /* Only care about default behavior. Remove temporary values */
+ Setattr(n, "allocate:visit", "1");
+ Swig_symbol_setscope(symtab);
+
+ /* Now we can add the additional implied constructors and destructors to the parse tree */
+ if (!ImportMode && !GetFlag(n, "feature:ignore")) {
+ int dir = 0;
+ if (Swig_directors_enabled()) {
+ int ndir = GetFlag(n, "feature:director");
+ int nndir = GetFlag(n, "feature:nodirector");
+ /* 'nodirector' has precedence over 'director' */
+ dir = (ndir || nndir) ? (ndir && !nndir) : 0;
+ }
+ int abstract = !dir && abstractClassTest(n);
+ int odefault = !GetFlag(n, "feature:nodefault");
+
+ /* default constructor */
+ if (!abstract && !GetFlag(n, "feature:nodefaultctor") && odefault) {
+ if (!Getattr(n, "allocate:has_constructor") && Getattr(n, "allocate:default_constructor")) {
+ addDefaultConstructor(n);
+ }
+ }
+ /* copy constructor */
+ if (CPlusPlus && !abstract && GetFlag(n, "feature:copyctor")) {
+ if (!Getattr(n, "allocate:has_copy_constructor") && Getattr(n, "allocate:copy_constructor")) {
+ addCopyConstructor(n);
+ }
+ }
+ /* default destructor */
+ if (!GetFlag(n, "feature:nodefaultdtor") && odefault) {
+ if (!Getattr(n, "allocate:has_destructor") && Getattr(n, "allocate:default_destructor")) {
+ addDestructor(n);
+ }
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int accessDeclaration(Node *n) {
+ cplus_mode = accessModeFromString(Getattr(n, "kind"));
+ return SWIG_OK;
+ }
+
+ virtual int usingDeclaration(Node *n) {
+
+ if (GetFlag(n, "feature:ignore"))
+ return SWIG_OK;
+
+ if (!Getattr(n, "namespace")) {
+ Node *ns;
+ /* using id */
+ Symtab *stab = Getattr(n, "sym:symtab");
+ if (stab) {
+ String *uname = Getattr(n, "uname");
+ ns = Swig_symbol_clookup(uname, stab);
+ if (!ns && SwigType_istemplate(uname)) {
+ String *tmp = Swig_symbol_template_deftype(uname, 0);
+ if (!Equal(tmp, uname)) {
+ ns = Swig_symbol_clookup(tmp, stab);
+ }
+ Delete(tmp);
+ }
+ } else {
+ ns = 0;
+ }
+ if (!ns) {
+ if (is_public(n)) {
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(n), Getline(n), "Nothing known about '%s'.\n", SwigType_namestr(Getattr(n, "uname")));
+ }
+ } else if (Equal(nodeType(ns), "constructor") && !GetFlag(n, "usingctor")) {
+ Swig_warning(WARN_PARSE_USING_CONSTRUCTOR, Getfile(n), Getline(n), "Using declaration '%s' for inheriting constructors uses base '%s' which is not an immediate base of '%s'.\n", SwigType_namestr(Getattr(n, "uname")), SwigType_namestr(Getattr(ns, "name")), SwigType_namestr(Getattr(parentNode(n), "name")));
+ } else {
+ if (inclass && Getattr(n, "sym:name")) {
+ {
+ String *ntype = nodeType(ns);
+ if (Equal(ntype, "cdecl") || Equal(ntype, "constructor") || Equal(ntype, "template") || Equal(ntype, "using")) {
+ /* Add a new class member to the parse tree (copy it from the base class member pointed to by the using declaration in node n) */
+ Node *c = ns;
+ Node *unodes = 0, *last_unodes = 0;
+ int ccount = 0;
+
+ while (c) {
+ String *cnodetype = nodeType(c);
+ if (Equal(cnodetype, "cdecl")) {
+ add_member_for_using_declaration(c, n, ccount, unodes, last_unodes);
+ } else if (Equal(cnodetype, "constructor")) {
+ add_member_for_using_declaration(c, n, ccount, unodes, last_unodes);
+ } else if (Equal(cnodetype, "template")) {
+ // A templated member (in a non-template class or in a template class that where the member has a separate template declaration)
+ // Find the template instantiations in the using declaration (base class)
+ for (Node *member = ns; member; member = nextSibling(member)) {
+ /* Constructors have already been handled, only add member functions
+ * This adds an implicit template instantiation and is a bit unusual as SWIG requires explicit %template for other template instantiations.
+ * However, of note, is that there is no valid C++ syntax for a template instantiation to introduce a name via a using declaration...
+ *
+ * struct Base { template <typename T> void template_method(T, T) {} };
+ * struct Derived : Base { using Base::template_method; };
+ * %template() Base::template_method<int>; // SWIG template instantiation
+ * template void Base::template_method<int>(int, int); // C++ template instantiation
+ * template void Derived::template_method<int>(int, int); // Not valid C++
+ */
+ if (Getattr(member, "template") == ns && checkAttribute(ns, "templatetype", "cdecl")) {
+ if (!GetFlag(member, "feature:ignore") && !Getattr(member, "error")) {
+ add_member_for_using_declaration(member, n, ccount, unodes, last_unodes);
+ }
+ }
+ }
+ } else if (Equal(cnodetype, "using")) {
+ for (Node *member = firstChild(c); member; member = nextSibling(member)) {
+ add_member_for_using_declaration(member, n, ccount, unodes, last_unodes);
+ }
+ }
+ c = Getattr(c, "csym:nextSibling");
+ }
+ if (unodes) {
+ set_firstChild(n, unodes);
+ if (ccount > 1) {
+ if (!Getattr(n, "sym:overloaded")) {
+ Setattr(n, "sym:overloaded", n);
+ Setattr(n, "sym:overname", "_SWIG_0");
+ }
+ }
+ }
+
+ /* Hack the parse tree symbol table for overloaded methods. Replace the "using" node with the
+ * 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")) {
+ int cnt = 0;
+ Node *ps = Getattr(n, "sym:previousSibling");
+ Node *ns = Getattr(n, "sym:nextSibling");
+ Node *fc = firstChild(n);
+ Node *firstoverloaded = Getattr(n, "sym:overloaded");
+#ifdef DEBUG_OVERLOADED
+ show_overloaded(firstoverloaded);
+#endif
+
+ if (firstoverloaded == n) {
+ // This 'using' node we are cutting out was the first node in the overloaded list.
+ // Change the first node in the list
+ Delattr(firstoverloaded, "sym:overloaded");
+ firstoverloaded = fc ? fc : ns;
+
+ // Correct all the sibling overloaded methods (before adding in new methods)
+ Node *nnn = ns;
+ while (nnn) {
+ Setattr(nnn, "sym:overloaded", firstoverloaded);
+ nnn = Getattr(nnn, "sym:nextSibling");
+ }
+ }
+
+ if (!fc) {
+ // Remove from overloaded list ('using' node does not actually end up adding in any methods)
+ if (ps) {
+ Setattr(ps, "sym:nextSibling", ns);
+ }
+ if (ns) {
+ Setattr(ns, "sym:previousSibling", ps);
+ }
+ } else {
+ // The 'using' node results in methods being added in - slot in these methods here
+ Node *pp = fc;
+ while (pp) {
+ Node *ppn = Getattr(pp, "sym:nextSibling");
+ Setattr(pp, "sym:overloaded", firstoverloaded);
+ Setattr(pp, "sym:overname", NewStringf("%s_%d", Getattr(n, "sym:overname"), cnt++));
+ if (ppn)
+ pp = ppn;
+ else
+ break;
+ }
+ if (ps) {
+ Setattr(ps, "sym:nextSibling", fc);
+ Setattr(fc, "sym:previousSibling", ps);
+ }
+ if (ns) {
+ Setattr(ns, "sym:previousSibling", pp);
+ Setattr(pp, "sym:nextSibling", ns);
+ }
+ }
+ Delattr(n, "sym:previousSibling");
+ Delattr(n, "sym:nextSibling");
+ Delattr(n, "sym:overloaded");
+ Delattr(n, "sym:overname");
+ clean_overloaded(firstoverloaded);
+#ifdef DEBUG_OVERLOADED
+ show_overloaded(firstoverloaded);
+#endif
+ }
+ }
+ }
+ }
+ }
+
+ Node *c = 0;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ if (Equal(nodeType(c), "cdecl")) {
+ process_exceptions(c);
+
+ if (inclass)
+ class_member_is_defined_in_bases(c, inclass);
+ } else if (Equal(nodeType(c), "constructor")) {
+ constructorDeclaration(c);
+ }
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int cDeclaration(Node *n) {
+
+ process_exceptions(n);
+
+ if (inclass) {
+ /* check whether the member node n is defined in class node in class's bases */
+ class_member_is_defined_in_bases(n, inclass);
+
+ /* Check to see if this is a static member or not. If so, we add an attribute
+ cplus:staticbase that saves the current class */
+
+ int is_static = Swig_storage_isstatic(n);
+ if (is_static) {
+ Setattr(n, "cplus:staticbase", inclass);
+ }
+
+ if (Cmp(Getattr(n, "kind"), "variable") == 0) {
+ /* Check member variable to determine whether assignment is valid */
+ bool is_reference;
+ bool is_const;
+ bool assignable = is_assignable(n, is_reference, is_const);
+ if (!assignable || is_const) {
+ SetFlag(n, "feature:immutable");
+ }
+ if (!is_static) {
+ if (!assignable || is_reference || is_const)
+ SetFlag(inclass, "allocate:has_nonassignable"); // The class has a variable that cannot be assigned to
+ }
+ }
+
+ String *name = Getattr(n, "name");
+ if (cplus_mode != PUBLIC) {
+ if (Strcmp(name, "operator =") == 0) {
+ /* Look for a private assignment operator */
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_assign", "1");
+ Setattr(inclass, "allocate:noassign", "1");
+ } else if (Strcmp(name, "operator new") == 0) {
+ /* Look for a private new operator */
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_new", "1");
+ Setattr(inclass, "allocate:nonew", "1");
+ }
+ } else {
+ if (Strcmp(name, "operator =") == 0) {
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_assign", "1");
+ else
+ Setattr(inclass, "allocate:noassign", "1");
+ } else if (Strcmp(name, "operator new") == 0) {
+ if (!GetFlag(n, "deleted"))
+ Setattr(inclass, "allocate:has_new", "1");
+ else
+ Setattr(inclass, "allocate:nonew", "1");
+ }
+ /* Look for smart pointer operator */
+ if ((Strcmp(name, "operator ->") == 0) && (!GetFlag(n, "feature:ignore"))) {
+ /* Look for version with no parameters */
+ Node *sn = n;
+ while (sn) {
+ if (!Getattr(sn, "parms")) {
+ SwigType *type = SwigType_typedef_resolve_all(Getattr(sn, "type"));
+ SwigType_push(type, Getattr(sn, "decl"));
+ Delete(SwigType_pop_function(type));
+ SwigType *base = SwigType_base(type);
+ Node *sc = Swig_symbol_clookup(base, 0);
+ if ((sc) && (Strcmp(nodeType(sc), "class") == 0)) {
+ if (SwigType_check_decl(type, "p.")) {
+ /* Need to check if type is a const pointer */
+ int isconst = 0;
+ Delete(SwigType_pop(type));
+ if (SwigType_isconst(type)) {
+ isconst = !Getattr(inclass, "allocate:smartpointermutable");
+ Setattr(inclass, "allocate:smartpointerconst", "1");
+ }
+ else {
+ Setattr(inclass, "allocate:smartpointermutable", "1");
+ }
+ List *methods = smart_pointer_methods(sc, 0, isconst);
+ Setattr(inclass, "allocate:smartpointer", methods);
+ Setattr(inclass, "allocate:smartpointerpointeeclassname", Getattr(sc, "name"));
+ } else {
+ /* Hmmm. The return value is not a pointer. If the type is a value
+ or reference. We're going to chase it to see if another operator->()
+ can be found */
+ if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) {
+ Node *nn = Swig_symbol_clookup("operator ->", Getattr(sc, "symtab"));
+ if (nn) {
+ Delete(base);
+ Delete(type);
+ sn = nn;
+ continue;
+ }
+ }
+ }
+ }
+ Delete(base);
+ Delete(type);
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ if (Cmp(Getattr(n, "kind"), "variable") == 0) {
+ bool is_reference;
+ bool is_const;
+ bool assignable = is_assignable(n, is_reference, is_const);
+ if (!assignable || is_const) {
+ SetFlag(n, "feature:immutable");
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ virtual int templateDeclaration(Node *n) {
+ String *ttype = Getattr(n, "templatetype");
+ if (Equal(ttype, "constructor")) {
+ // Templated constructors need to be taken account of even if not instantiated with %template
+ constructorDeclaration(n);
+ }
+ return SWIG_OK;
+ }
+
+ virtual int constructorDeclaration(Node *n) {
+ if (!inclass)
+ return SWIG_OK;
+
+ Parm *parms = Getattr(n, "parms");
+ bool deleted_constructor = (GetFlag(n, "deleted"));
+ bool default_constructor = !ParmList_numrequired(parms);
+ AccessMode access_mode = accessModeFromString(Getattr(n, "access"));
+ process_exceptions(n);
+
+ if (!deleted_constructor) {
+ if (!extendmode) {
+ if (default_constructor) {
+ /* Class does define a default constructor */
+ /* However, we had better see where it is defined */
+ if (access_mode == PUBLIC) {
+ Setattr(inclass, "allocate:default_constructor", "1");
+ } else if (access_mode == PROTECTED) {
+ Setattr(inclass, "allocate:default_base_constructor", "1");
+ }
+ }
+ /* Class defines some kind of constructor. May or may not be public */
+ Setattr(inclass, "allocate:has_constructor", "1");
+ if (access_mode == PUBLIC) {
+ Setattr(inclass, "allocate:public_constructor", "1");
+ }
+ } else {
+ Setattr(inclass, "allocate:has_constructor", "1");
+ Setattr(inclass, "allocate:public_constructor", "1");
+ }
+ } else {
+ if (default_constructor && !extendmode)
+ SetFlag(inclass, "allocate:deleted_default_constructor");
+ }
+
+ /* See if this is a copy constructor */
+ if (parms && (ParmList_numrequired(parms) == 1)) {
+ /* Look for a few cases. X(const X &), X(X &), X(X *) */
+ int copy_constructor = 0;
+ int copy_constructor_non_const = 0;
+ SwigType *type = Getattr(inclass, "name");
+ String *tn = NewStringf("r.q(const).%s", type);
+ String *cc = SwigType_typedef_resolve_all(tn);
+ SwigType *rt = SwigType_typedef_resolve_all(Getattr(parms, "type"));
+ if (SwigType_istemplate(type)) {
+ String *tmp = Swig_symbol_template_deftype(cc, 0);
+ Delete(cc);
+ cc = tmp;
+ tmp = Swig_symbol_template_deftype(rt, 0);
+ Delete(rt);
+ rt = tmp;
+ }
+ if (Strcmp(cc, rt) == 0) {
+ copy_constructor = 1;
+ } else {
+ Delete(cc);
+ cc = NewStringf("r.%s", Getattr(inclass, "name"));
+ if (Strcmp(cc, Getattr(parms, "type")) == 0) {
+ copy_constructor = 1;
+ copy_constructor_non_const = 1;
+ } else {
+ Delete(cc);
+ cc = NewStringf("p.%s", Getattr(inclass, "name"));
+ String *ty = SwigType_strip_qualifiers(Getattr(parms, "type"));
+ if (Strcmp(cc, ty) == 0) {
+ copy_constructor = 1;
+ }
+ Delete(ty);
+ }
+ }
+ Delete(cc);
+ Delete(rt);
+ Delete(tn);
+
+ if (copy_constructor) {
+ if (!deleted_constructor) {
+ Setattr(n, "copy_constructor", "1");
+ Setattr(inclass, "allocate:has_copy_constructor", "1");
+ if (access_mode == PUBLIC) {
+ Setattr(inclass, "allocate:copy_constructor", "1");
+ } else if (access_mode == PROTECTED) {
+ Setattr(inclass, "allocate:copy_base_constructor", "1");
+ }
+ if (copy_constructor_non_const) {
+ Setattr(n, "copy_constructor_non_const", "1");
+ Setattr(inclass, "allocate:has_copy_constructor_non_const", "1");
+ if (access_mode == PUBLIC) {
+ Setattr(inclass, "allocate:copy_constructor_non_const", "1");
+ } else if (access_mode == PROTECTED) {
+ Setattr(inclass, "allocate:copy_base_constructor_non_const", "1");
+ }
+ }
+ } else {
+ if (!extendmode)
+ SetFlag(inclass, "allocate:deleted_copy_constructor");
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ virtual int destructorDeclaration(Node *n) {
+ (void) n;
+ if (!inclass)
+ return SWIG_OK;
+
+ if (!GetFlag(n, "deleted")) {
+ if (!extendmode) {
+ Setattr(inclass, "allocate:has_destructor", "1");
+ if (cplus_mode == PUBLIC) {
+ Setattr(inclass, "allocate:default_destructor", "1");
+ } else if (cplus_mode == PROTECTED) {
+ Setattr(inclass, "allocate:default_base_destructor", "1");
+ } else if (cplus_mode == PRIVATE) {
+ Setattr(inclass, "allocate:private_destructor", "1");
+ }
+ } else {
+ Setattr(inclass, "allocate:has_destructor", "1");
+ Setattr(inclass, "allocate:default_destructor", "1");
+ }
+ } else {
+ if (!extendmode)
+ SetFlag(inclass, "allocate:deleted_default_destructor");
+ }
+
+ return SWIG_OK;
+ }
+
+static void addCopyConstructor(Node *n) {
+ Node *cn = NewHash();
+ set_nodeType(cn, "constructor");
+ Setattr(cn, "access", "public");
+ Setfile(cn, Getfile(n));
+ Setline(cn, Getline(n));
+
+ int copy_constructor_non_const = GetFlag(n, "allocate:copy_constructor_non_const");
+ String *cname = Getattr(n, "name");
+ SwigType *type = Copy(cname);
+ String *lastname = Swig_scopename_last(cname);
+ String *name = SwigType_templateprefix(lastname);
+ String *cc = NewStringf(copy_constructor_non_const ? "r.%s" : "r.q(const).%s", type);
+ String *decl = NewStringf("f(%s).", cc);
+ String *oldname = Getattr(n, "sym:name");
+
+ if (Getattr(n, "allocate:has_constructor")) {
+ // to work properly with '%rename Class', we must look
+ // for any other constructor in the class, which has not been
+ // renamed, and use its name as oldname.
+ Node *c;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ if (Equal(nodeType(c), "constructor")) {
+ String *csname = Getattr(c, "sym:name");
+ String *clast = Swig_scopename_last(Getattr(c, "name"));
+ if (Equal(csname, clast)) {
+ oldname = csname;
+ Delete(clast);
+ break;
+ }
+ Delete(clast);
+ }
+ }
+ }
+
+ String *symname = Swig_name_make(cn, cname, name, decl, oldname);
+ if (Strcmp(symname, "$ignore") != 0) {
+ Parm *p = NewParm(cc, "other", n);
+
+ Setattr(cn, "name", name);
+ Setattr(cn, "sym:name", symname);
+ SetFlag(cn, "feature:new");
+ Setattr(cn, "decl", decl);
+ Setattr(cn, "ismember", "1");
+ Setattr(cn, "parentNode", n);
+ Setattr(cn, "parms", p);
+ Setattr(cn, "copy_constructor", "1");
+
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *on = Swig_symbol_add(symname, cn);
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+
+ if (on == cn) {
+ Node *access = NewHash();
+ set_nodeType(access, "access");
+ Setattr(access, "kind", "public");
+ appendChild(n, access);
+ appendChild(n, cn);
+ Setattr(n, "has_copy_constructor", "1");
+ Setattr(n, "copy_constructor_decl", decl);
+ Setattr(n, "allocate:copy_constructor", "1");
+ Delete(access);
+ }
+ }
+ Delete(cn);
+ Delete(lastname);
+ Delete(name);
+ Delete(decl);
+ Delete(symname);
+}
+
+static void addDefaultConstructor(Node *n) {
+ Node *cn = NewHash();
+ set_nodeType(cn, "constructor");
+ Setattr(cn, "access", "public");
+ Setfile(cn, Getfile(n));
+ Setline(cn, Getline(n));
+
+ String *cname = Getattr(n, "name");
+ String *lastname = Swig_scopename_last(cname);
+ String *name = SwigType_templateprefix(lastname);
+ String *decl = NewString("f().");
+ String *oldname = Getattr(n, "sym:name");
+ String *symname = Swig_name_make(cn, cname, name, decl, oldname);
+
+ if (Strcmp(symname, "$ignore") != 0) {
+ Setattr(cn, "name", name);
+ Setattr(cn, "sym:name", symname);
+ SetFlag(cn, "feature:new");
+ Setattr(cn, "decl", decl);
+ Setattr(cn, "ismember", "1");
+ Setattr(cn, "parentNode", n);
+ Setattr(cn, "default_constructor", "1");
+
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *on = Swig_symbol_add(symname, cn);
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+
+ if (on == cn) {
+ Node *access = NewHash();
+ set_nodeType(access, "access");
+ Setattr(access, "kind", "public");
+ appendChild(n, access);
+ appendChild(n, cn);
+ Setattr(n, "has_default_constructor", "1");
+ Setattr(n, "allocate:default_constructor", "1");
+ Delete(access);
+ }
+ }
+ Delete(cn);
+ Delete(lastname);
+ Delete(name);
+ Delete(decl);
+ Delete(symname);
+}
+
+static void addDestructor(Node *n) {
+ Node *cn = NewHash();
+ set_nodeType(cn, "destructor");
+ Setattr(cn, "access", "public");
+ Setfile(cn, Getfile(n));
+ Setline(cn, Getline(n));
+
+ String *cname = Getattr(n, "name");
+ String *lastname = Swig_scopename_last(cname);
+ String *name = SwigType_templateprefix(lastname);
+ Insert(name, 0, "~");
+ String *decl = NewString("f().");
+ String *symname = Swig_name_make(cn, cname, name, decl, 0);
+ if (Strcmp(symname, "$ignore") != 0) {
+ String *possible_nonstandard_symname = NewStringf("~%s", Getattr(n, "sym:name"));
+
+ Setattr(cn, "name", name);
+ Setattr(cn, "sym:name", symname);
+ Setattr(cn, "decl", "f().");
+ Setattr(cn, "ismember", "1");
+ Setattr(cn, "parentNode", n);
+
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *nonstandard_destructor = Equal(possible_nonstandard_symname, symname) ? 0 : Swig_symbol_clookup(possible_nonstandard_symname, 0);
+ Node *on = Swig_symbol_add(symname, cn);
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+
+ if (on == cn) {
+ // SWIG accepts a non-standard named destructor in %extend that uses a typedef for the destructor name
+ // For example: typedef struct X {} XX; %extend X { ~XX() {...} }
+ // Don't add another destructor if a nonstandard one has been declared
+ if (!nonstandard_destructor) {
+ Node *access = NewHash();
+ set_nodeType(access, "access");
+ Setattr(access, "kind", "public");
+ appendChild(n, access);
+ appendChild(n, cn);
+ Setattr(n, "has_destructor", "1");
+ Setattr(n, "allocate:has_destructor", "1");
+ Delete(access);
+ }
+ }
+ Delete(possible_nonstandard_symname);
+ }
+ Delete(cn);
+ Delete(lastname);
+ Delete(name);
+ Delete(decl);
+ Delete(symname);
+}
+
+};
+
+void Swig_default_allocators(Node *n) {
+ if (!n)
+ return;
+ Allocate *a = new Allocate;
+ a->top(n);
+ delete a;
+}
diff --git a/contrib/tools/swig/Source/Modules/c.cxx b/contrib/tools/swig/Source/Modules/c.cxx
new file mode 100644
index 00000000000..58cf57ab187
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/c.cxx
@@ -0,0 +1,3122 @@
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * c.cxx
+ *
+ * C language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include <ctype.h>
+#include "swigmod.h"
+
+extern "C" {
+ extern int UseWrapperSuffix;
+}
+
+int SwigType_isbuiltin(SwigType *t) {
+ const char* builtins[] = { "void", "short", "int", "long", "char", "float", "double", "bool", 0 };
+ int i = 0;
+ char *c = Char(t);
+ if (!t)
+ return 0;
+ while (builtins[i]) {
+ if (strcmp(c, builtins[i]) == 0)
+ return 1;
+ i++;
+ }
+ return 0;
+}
+
+
+// Private helpers, could be made public and reused from other language modules in the future.
+namespace
+{
+
+enum exceptions_support {
+ exceptions_support_enabled, // Default value in C++ mode.
+ exceptions_support_disabled, // Not needed at all.
+ exceptions_support_imported // Needed, but already defined in an imported module.
+};
+
+// When using scoped_dohptr, it's very simple to accidentally pass it to a vararg function, such as Printv() or Printf(), resulting in catastrophic results
+// during run-time (crash or, worse, junk in the generated output), so make sure gcc warning about this, which is not enabled by default for some reason (see
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64867 for more information), is enabled.
+#ifdef __GNUC__
+ #pragma GCC diagnostic error "-Wconditionally-supported"
+#endif // __GNUC__
+
+// Delete a DOH object on scope exit.
+class scoped_dohptr
+{
+public:
+ scoped_dohptr() : obj_(NULL) {}
+ explicit scoped_dohptr(DOH* obj) : obj_(obj) {}
+ ~scoped_dohptr() { Delete(obj_); }
+
+ // This is an std::auto_ptr<>-like "destructive" copy ctor which allows to return objects of this type from functions.
+ scoped_dohptr(scoped_dohptr const& other) : obj_(other.release()) {}
+
+ // Same for the assignment operator.
+ scoped_dohptr& operator=(scoped_dohptr const& other) {
+ reset(other.release());
+
+ return *this;
+ }
+
+ // Assignment operator takes ownership of the pointer, just as the ctor does.
+ scoped_dohptr& operator=(DOH* obj) {
+ reset(obj);
+
+ return *this;
+ }
+
+ DOH* get() const { return obj_; }
+
+ DOH* release() const /* not really */ {
+ DOH* obj = obj_;
+ const_cast<DOH*&>(const_cast<scoped_dohptr*>(this)->obj_) = NULL;
+ return obj;
+ }
+
+ void reset(DOH* obj = NULL) {
+ if (obj != obj_) {
+ Delete(obj_);
+ obj_ = obj;
+ }
+ }
+
+ operator DOH*() const { return obj_; }
+
+protected:
+ DOH* obj_;
+};
+
+// Wrapper for a DOH object which can be owned or not.
+class maybe_owned_dohptr : public scoped_dohptr
+{
+public:
+ explicit maybe_owned_dohptr(DOH* obj = NULL) : scoped_dohptr(obj), owned_(true) {}
+
+ maybe_owned_dohptr(maybe_owned_dohptr const& other) : scoped_dohptr(other) {
+ owned_ = other.owned_;
+
+ // We can live other.owned_ unchanged, as its pointer is null now anyhow.
+ }
+
+ maybe_owned_dohptr& operator=(maybe_owned_dohptr const& other) {
+ reset(other.release());
+ owned_ = other.owned_;
+
+ return *this;
+ }
+
+ ~maybe_owned_dohptr() {
+ if (!owned_)
+ obj_ = NULL; // Prevent it from being deleted by the base class dtor.
+ }
+
+ void assign_owned(DOH* obj) {
+ reset(obj);
+ }
+
+ void assign_non_owned(DOH* obj) {
+ reset(obj);
+ owned_ = false;
+ }
+
+private:
+ bool owned_;
+};
+
+
+// Helper class setting the given pointer to the given value in its ctor and resetting it in the dtor.
+//
+// Used to non-intrusively set a pointer to some object only during this object life-time.
+template <typename T>
+class temp_ptr_setter
+{
+public:
+ // Pointer must be non-null, its current value is restored when this object is destroyed.
+ temp_ptr_setter(T* ptr, T value) : ptr_(ptr), value_orig_(*ptr) {
+ *ptr_ = value;
+ }
+
+ ~temp_ptr_setter() {
+ *ptr_ = value_orig_;
+ }
+
+private:
+ T* const ptr_;
+ T const value_orig_;
+
+ // Non copyable.
+ temp_ptr_setter(const temp_ptr_setter&);
+ temp_ptr_setter& operator=(const temp_ptr_setter&);
+};
+
+
+// Helper class to output "begin" fragment in the ctor and "end" in the dtor.
+class begin_end_output_guard
+{
+public:
+ begin_end_output_guard(File* f, const_String_or_char_ptr begin, const_String_or_char_ptr end)
+ : f_(f),
+ end_(NewString(end))
+ {
+ String* const s = NewString(begin);
+ Dump(s, f_);
+ Delete(s);
+ }
+
+ ~begin_end_output_guard()
+ {
+ Dump(end_, f_);
+ Delete(end_);
+ }
+
+private:
+ // Non copyable.
+ begin_end_output_guard(const begin_end_output_guard&);
+ begin_end_output_guard& operator=(const begin_end_output_guard&);
+
+ File* const f_;
+ String* const end_;
+};
+
+// Subclass to output extern "C" guards when compiling as C++.
+class cplusplus_output_guard : private begin_end_output_guard
+{
+public:
+ explicit cplusplus_output_guard(File* f)
+ : begin_end_output_guard(
+ f,
+ "#ifdef __cplusplus\n"
+ "extern \"C\" {\n"
+ "#endif\n\n",
+ "#ifdef __cplusplus\n"
+ "}\n"
+ "#endif\n\n"
+ )
+ {
+ }
+};
+
+// String containing one indentation level for the generated code.
+const char* const cindent = " ";
+
+// Returns the non-owned string to the name of the class or enum to use in C wrappers.
+String* get_c_proxy_name(Node* n) {
+ String *proxyname = Getattr(n, "proxyname");
+ if (!proxyname) {
+ String *symname = Getattr(n, "sym:name");
+ String *nspace = Getattr(n, "sym:nspace");
+
+ if (nspace) {
+ scoped_dohptr nspace_mangled(Swig_name_mangle_string(nspace));
+ proxyname = NewStringf("%s_%s", (DOH*)nspace_mangled, symname);
+ } else {
+ proxyname = Swig_name_type(symname);
+ }
+ Setattr(n, "proxyname", proxyname);
+
+ Delete(proxyname); // It stays alive because it's referenced by the hash.
+ }
+
+ return proxyname;
+}
+
+// Returns the first named "import" node under the given one (which must be non-NULL). May return NULL.
+Node* find_first_named_import(Node* parent) {
+ for (Node* n = firstChild(parent); n; n = nextSibling(n)) {
+ if (Cmp(nodeType(n), "import") == 0) {
+ // We've almost succeeded, but there are sometimes some weird unnamed import modules that don't really count for our purposes, so skip them.
+ if (Getattr(n, "module"))
+ return n;
+ } else if (Cmp(nodeType(n), "include") == 0) {
+ // Recurse into this node as included files may contain imports too.
+ if (Node* const import = find_first_named_import(n))
+ return import;
+ } else {
+ // We consider that import nodes can only occur in the global scope, some don't bother recursing here. If this turns out to be false, we'd just need to
+ // start doing it.
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ Information about the function return type.
+ */
+class cxx_rtype_desc
+{
+public:
+ // Default ctor creates a "void" return type.
+ cxx_rtype_desc() {}
+
+ // If this returns true, get_return_code() can't be called.
+ bool is_void() const {
+ return !type_;
+ }
+
+ // This function must be called before calling get_return_code().
+ void set_type(String* type) {
+ type_ = Copy(type);
+ }
+
+ // This function must also be called before calling get_return_code().
+ //
+ // NB: It takes ownership of the string, the intended use is to pass it NewStringf(...).
+ void set_return_value(String* new_string) {
+ value_ = new_string;
+ }
+
+ // This function applies the given typemap, which must set $result variable from $cresult containing the result of C wrapper function call.
+ //
+ // If it is not called, the trivial "$result = $cresult" typemap is used and, in fact, the extra variables are optimized away and just "return $cresult" is
+ // generated directly for brevity.
+ //
+ // If the string doesn't start with "$result = ", it is prepended to it implicitly, for convenience.
+ //
+ // NB: It takes ownership of the string, which is typically returned from Swig_typemap_lookup().
+ void apply_out_typemap(String* new_out_tm_string) {
+ out_tm_ = new_out_tm_string;
+ }
+
+ // Return the function return type: can always be called, even for void functions (for which it just returns "void").
+ String* type() const {
+ return type_ ? type_ : get_void_type();
+ }
+
+ // Return the string containing the code for returning the value, previously set by set_return_value().
+ //
+ // The returned string ends with a semicolon, i.e. is a complete statement (or possibly more than one).
+ //
+ // Asserts unless both set_type() and set_return_value() had been called.
+ scoped_dohptr get_return_code() const {
+ assert(type_);
+ assert(value_);
+
+ if (!out_tm_) {
+ // Trivial case when we return the same value, just do it.
+ //
+ // Add extra spaces after/before opening/closing braces because we keep everything on the same line in this case.
+ return scoped_dohptr(NewStringf(" return %s; ", value_.get()));
+ }
+
+ // We need to start by introducing a temporary variable for the C call result because if $cresult is used twice by the typemap, we don't want to call the
+ // function twice. Note that just "auto" is enough because C functions can't return references, but we need "auto&&" for C++ result which can be anything
+ // (defined by the user in their typemaps).
+ scoped_dohptr code(NewStringf(
+ "\n"
+ "%sauto swig_cres = %s;\n",
+ cindent, value_.get()
+ ));
+
+ // We support 2 cases: either typemap is a statement, or multiple statements, containing assignment to $result, in which case this assignment must occur at
+ // its beginning.
+ bool const has_result = strstr(Char(out_tm_), "$result = ") != NULL;
+ if (has_result) {
+ Printv(code, cindent, "auto&& ", NIL);
+ } else {
+ // Or the typemap is just an expression, which can be returned directly, without defining $result at all. Note that this is more than an optimization as
+ // it allows the generated code to work even with non-copyable classes.
+ Printv(code, cindent, "return ", NIL);
+ }
+
+ // Skip leading whitespace and chop the trailing whitespace from the typemap to keep indentation consistent.
+ const char* tm = Char(out_tm_);
+ while (isspace(*tm))
+ ++tm;
+ Append(code, tm);
+ Chop(code);
+
+ if ((Char(code))[Len(code) - 1] != ';')
+ Append(code, ";");
+
+ Replaceall(code, "$cresult", "swig_cres");
+
+ if (has_result) {
+ Printf(code, "\n%sreturn $result;\n", cindent);
+ Replaceall(code, "$result", "swig_cxxres");
+ } else {
+ Append(code, "\n");
+ }
+
+ return code;
+ }
+
+private:
+ static String* get_void_type() {
+ static String* const void_type = NewString("void");
+ return void_type;
+ }
+
+ scoped_dohptr type_;
+ scoped_dohptr value_;
+ scoped_dohptr out_tm_;
+};
+
+/*
+ Information about a function parameter.
+
+ This is similar to cxx_rtype_desc, but is used for the parameters and not the return type.
+ */
+class cxx_ptype_desc
+{
+public:
+ // Ctor initializes the object to an empty/unknown state, call set_type() later to finish initialization.
+ cxx_ptype_desc() {}
+
+ // This function must be called (with a non-null string) before calling get_param_code().
+ void set_type(String* type) { type_ = Copy(type); }
+
+ // If this one returns NULL, it means that we don't have any type information at all.
+ String* type() const { return type_; }
+
+ // This may be called before calling get_param_code() if a translation from C++ to C type is necessary. By default the parameter is passed "as is".
+ void apply_in_typemap(String* new_in_tm_string) {
+ in_tm_ = new_in_tm_string;
+ }
+
+ // Return the full expression needed to pass the given value as parameter to C wrapper function.
+ scoped_dohptr get_param_code(String* value) const {
+ assert(type_);
+
+ if (!in_tm_) {
+ return scoped_dohptr(Copy(value));
+ }
+
+ // There doesn't seem to be any simple way to use the full SWIG typemap expansion machinery here, so just do it manually.
+ scoped_dohptr code(Copy(in_tm_));
+ Replace(code, "$1", value, DOH_REPLACE_NUMBER_END);
+ return code;
+ }
+
+private:
+ scoped_dohptr type_;
+ scoped_dohptr in_tm_;
+};
+
+
+/*
+ Struct containing information needed only for generating C++ wrappers.
+*/
+struct cxx_wrappers
+{
+ // Default ctor doesn't do anything, use initialize() if C++ wrappers really need to be generated.
+ cxx_wrappers() :
+ except_check_start(NULL), except_check_end(NULL),
+ sect_cxx_h(NULL), sect_types(NULL), sect_decls(NULL), sect_impls(NULL) {
+ node_func_ = NULL;
+ rtype_desc_ = NULL;
+ ptype_desc_ = NULL;
+ }
+
+ void initialize() {
+ sect_cxx_h = NewStringEmpty();
+ sect_types = NewStringEmpty();
+ sect_decls = NewStringEmpty();
+ sect_impls = NewStringEmpty();
+
+ // Allow using SWIG directive to inject code here.
+ Swig_register_filebyname("cxxheader", sect_cxx_h);
+ Swig_register_filebyname("cxxcode", sect_impls);
+ }
+
+ // This function must be called after initialize(). The two can't be combined because we don't yet know if we're going to use exceptions or not when we
+ // initialize the object of this class in C::main(), so this one is called later from C::top().
+ void initialize_exceptions(exceptions_support support) {
+ switch (support) {
+ case exceptions_support_enabled:
+ case exceptions_support_imported:
+ except_check_start = "swig_check(";
+ except_check_end = ")";
+ break;
+
+ case exceptions_support_disabled:
+ except_check_start =
+ except_check_end = "";
+ break;
+ }
+ }
+
+ bool is_initialized() const { return sect_types != NULL; }
+
+ bool is_exception_support_enabled() const { return *except_check_start != '\0'; }
+
+
+ // All the functions below are only used when is_initialized() returns true.
+
+ // Fill the provided rtype_desc with the type information for the given function node.
+ //
+ // Returns false in case of error, i.e. if function wrapper can't be generated at all.
+ bool lookup_cxx_ret_type(cxx_rtype_desc& rtype_desc, Node* n) {
+ String* const func_type = Getattr(n, "type");
+ if (SwigType_type(func_type) == T_VOID) {
+ // Nothing to do, rtype_desc is void by default.
+ return true;
+ }
+
+ // As above, ensure our replaceSpecialVariables() is used.
+ temp_ptr_setter<cxx_rtype_desc*> set(&rtype_desc_, &rtype_desc);
+
+ bool use_cxxout = true;
+ String* type(Swig_typemap_lookup("cxxouttype", n, "", NULL));
+ if (!type) {
+ use_cxxout = false;
+ type = Swig_typemap_lookup("ctype", n, "", NULL);
+ }
+
+ if (!type) {
+ Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, Getfile(n), Getline(n),
+ "No ctype typemap defined for the return type \"%s\" of %s\n",
+ SwigType_str(func_type, NULL),
+ Getattr(n, "sym:name")
+ );
+ return false;
+ }
+
+ if (!do_resolve_type(n, func_type, type, NULL, &rtype_desc))
+ return false;
+
+ if (use_cxxout) {
+ if (String* out_tm = Swig_typemap_lookup("cxxout", n, "", NULL))
+ rtype_desc.apply_out_typemap(out_tm);
+ }
+
+ return true;
+ }
+
+ // Return the type description for the given parameter of the function.
+ bool lookup_cxx_parm_type(cxx_ptype_desc& ptype_desc, Node* n, Parm* p) {
+ // Ensure our own replaceSpecialVariables() is used for $typemap() expansion.
+ temp_ptr_setter<cxx_ptype_desc*> set(&ptype_desc_, &ptype_desc);
+
+ bool use_cxxin = true;
+ String* type = Swig_typemap_lookup("cxxintype", p, "", NULL);
+ if (!type) {
+ use_cxxin = false;
+ type = Swig_typemap_lookup("ctype", p, "", NULL);
+ }
+
+ if (!type) {
+ Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, Getfile(p), Getline(p),
+ "No ctype typemap defined for the parameter \"%s\" of %s\n",
+ Getattr(p, "name"),
+ Getattr(n, "sym:name")
+ );
+ return false;
+ }
+
+ if (!do_resolve_type(n, Getattr(p, "type"), type, &ptype_desc, NULL))
+ return false;
+
+ if (use_cxxin) {
+ if (String* in_tm = Getattr(p, "tmap:cxxin"))
+ ptype_desc.apply_in_typemap(Copy(in_tm));
+ }
+
+ return true;
+ }
+
+
+ // This function is called from C::replaceSpecialVariables() but only does something non-trivial when it's called by our own lookup_cxx_xxx_type() functions.
+ bool replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ if (!ptype_desc_ && !rtype_desc_)
+ return false;
+
+ if (Cmp(method, "ctype") != 0) {
+ Swig_warning(WARN_C_UNSUPPORTTED, input_file, line_number, "Unsupported %s typemap %s\n", method, tm);
+ return false;
+ }
+
+ if (SwigType *type = Getattr(parm, "type")) {
+ if (ptype_desc_)
+ ptype_desc_->set_type(type);
+ if (rtype_desc_)
+ rtype_desc_->set_type(type);
+
+ if (!do_resolve_type(node_func_, type, tm, ptype_desc_, rtype_desc_))
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ // Used for generating exception checks around the calls, see initialize_exceptions().
+ const char* except_check_start;
+ const char* except_check_end;
+
+
+ // The order of the members here is the same as the order in which they appear in the output file.
+
+ // This section doesn't contain anything by default but can be used by typemaps etc. It is the only section outside of the namespace in which all the other
+ // declaration live.
+ String* sect_cxx_h;
+
+ // This section contains forward declarations of the classes.
+ String* sect_types;
+
+ // Full declarations of the classes.
+ String* sect_decls;
+
+ // Implementation of the classes.
+ String* sect_impls;
+
+
+private:
+ // Replace "resolved_type" occurrences in the string with the value corresponding to the given type.
+ //
+ // Note that the node here is the function itself, but type may be either its return type or the type of one of its parameters, so it's passed as a different
+ // parameter.
+ //
+ // Also fills in the start/end wrapper parts of the provided type descriptions if they're not null, with the casts needed to translate from C type to C++ type
+ // (this is used for the parameters of C++ functions, hence the name) and from C types to C++ types (which is used for the function return values).
+ static bool do_resolve_type(Node* n, String* type, String* s, cxx_ptype_desc* ptype_desc, cxx_rtype_desc* rtype_desc) {
+ enum TypeKind
+ {
+ Type_Ptr,
+ Type_Ref,
+ Type_Obj,
+ Type_Enm,
+ Type_Max
+ } typeKind = Type_Max;
+
+ // These correspond to the typemaps for SWIGTYPE*, SWIGTYPE&, SWIGTYPE and enum SWIGTYPE, respectively, defined in c.swg.
+ static const char* typemaps[Type_Max] = {
+ "$resolved_type*",
+ "$*resolved_type*",
+ "$&resolved_type*",
+ "$resolved_type",
+ };
+
+ for (int i = 0; i < Type_Max; ++i) {
+ if (Strstr(s, typemaps[i])) {
+ typeKind = static_cast<TypeKind>(i);
+ break;
+ }
+ }
+
+ if (typeKind == Type_Max) {
+ if (Strstr(s, "resolved_type")) {
+ Swig_warning(WARN_C_UNSUPPORTTED, input_file, line_number,
+ "Unsupported typemap \"%s\" used for type \"%s\" of \"%s\"\n",
+ s, type, Getattr(n, "name")
+ );
+
+ return false;
+ }
+
+ // Nothing else needed.
+ if (rtype_desc)
+ rtype_desc->set_type(s);
+ if (ptype_desc)
+ ptype_desc->set_type(s);
+
+ return true;
+ }
+
+ // The logic here is somewhat messy because we use the same "$resolved_type*" typemap for pointers/references to both enums and classes, but we actually
+ // need to do quite different things for them. It could probably be simplified by changing the typemaps to be distinct, but this would require also updating
+ // the code for C wrappers generation in substituteResolvedTypeSpecialVariable().
+ //
+ // An even better idea might be to try to define this using cxx{in,out} typemaps for the various types and let the generic SWIG machinery do all the
+ // matching instead of doing it in the code here.
+ scoped_dohptr resolved_type(SwigType_typedef_resolve_all(type));
+ scoped_dohptr base_resolved_type(SwigType_base(resolved_type));
+
+ scoped_dohptr typestr;
+ if (SwigType_isenum(base_resolved_type)) {
+ String* enumname = NULL;
+ if (Node* const enum_node = Language::instance()->enumLookup(base_resolved_type)) {
+ // This is the name of the enum in C wrappers, it should be already set by getEnumName().
+ enumname = Getattr(enum_node, "enumname");
+
+ if (enumname) {
+ String* const enum_symname = Getattr(enum_node, "sym:name");
+
+ if (Checkattr(enum_node, "ismember", "1")) {
+ Node* const parent_class = parentNode(enum_node);
+ typestr = NewStringf("%s::%s", Getattr(parent_class, "sym:name"), enum_symname);
+ } else {
+ typestr = Copy(enum_symname);
+ }
+ }
+ }
+
+ if (!enumname) {
+ // Unknown enums are mapped to int and no casts are necessary in this case.
+ typestr = NewString("int");
+ }
+
+ if (SwigType_ispointer(type))
+ Append(typestr, " *");
+ else if (SwigType_isreference(type))
+ Append(typestr, " &");
+
+ if (enumname) {
+ switch (typeKind) {
+ case Type_Ptr:
+ if (rtype_desc) {
+ rtype_desc->apply_out_typemap(NewStringf("(%s)$cresult", typestr.get()));
+ }
+
+ if (ptype_desc) {
+ ptype_desc->apply_in_typemap(NewStringf("(%s*)$1", enumname));
+ }
+ break;
+
+ case Type_Ref:
+ if (rtype_desc) {
+ rtype_desc->apply_out_typemap(NewStringf("(%s)(*($cresult))", typestr.get()));
+ }
+
+ if (ptype_desc) {
+ ptype_desc->apply_in_typemap(NewStringf("(%s*)&($1)", enumname));
+ }
+ break;
+
+ case Type_Enm:
+ if (rtype_desc) {
+ rtype_desc->apply_out_typemap(NewStringf("(%s)$cresult", typestr.get()));
+ }
+
+ if (ptype_desc) {
+ ptype_desc->apply_in_typemap(NewStringf("(%s)$1", enumname));
+ }
+ break;
+
+ case Type_Obj:
+ case Type_Max:
+ // Unreachable, but keep here to avoid -Wswitch warnings.
+ assert(0);
+ }
+ } else {
+ // This is the only thing we need to do even when we don't have the enum name.
+ if (typeKind == Type_Ref && ptype_desc)
+ ptype_desc->apply_in_typemap(NewString("&($1)"));
+ }
+ } else {
+ String* classname;
+ if (Node* const class_node = Language::instance()->classLookup(type)) {
+ // Deal with some special cases:
+ switch (typeKind) {
+ case Type_Ptr:
+ // If this is a pointer passed by const reference, we return just the pointer directly because we don't have any pointer-valued variable to give out
+ // a reference to.
+ if (strncmp(Char(resolved_type), "r.q(const).", 11) == 0) {
+ scoped_dohptr deref_type(Copy(resolved_type));
+ Delslice(deref_type, 0, 11);
+ typestr = SwigType_str(deref_type, 0);
+ }
+ break;
+
+ case Type_Obj:
+ // Const objects are just objects for our purposes here, remove the const from them to avoid having "const const" in the output.
+ if (SwigType_isconst(resolved_type))
+ SwigType_del_qualifier(resolved_type);
+ break;
+
+ case Type_Ref:
+ case Type_Enm:
+ case Type_Max:
+ // Nothing special to do.
+ break;
+ }
+
+ if (!typestr)
+ typestr = SwigType_str(resolved_type, 0);
+
+ classname = Getattr(class_node, "sym:name");
+
+ // We don't use namespaces, but the type may contain them, so get rid of them by replacing the base type name, which is fully qualified, with just the
+ // class name, which is not.
+ scoped_dohptr basetype(SwigType_base(resolved_type));
+ scoped_dohptr basetypestr(SwigType_str(basetype, 0));
+ if (Cmp(basetypestr, classname) != 0) {
+ Replaceall(typestr, basetypestr, classname);
+ }
+ } else {
+ classname = NULL;
+ }
+
+ if (!classname) {
+ Swig_warning(WARN_C_UNSUPPORTTED, input_file, line_number,
+ "Unsupported C++ wrapper function %s type \"%s\"\n",
+ ptype_desc ? "parameter" : "return", SwigType_str(type, 0)
+ );
+ return false;
+ }
+
+ const char* const owns = GetFlag(n, "feature:new") ? "true" : "false";
+ switch (typeKind) {
+ case Type_Ptr:
+ if (ptype_desc) {
+ ptype_desc->apply_in_typemap(NewString("$1->swig_self()"));
+ }
+
+ if (rtype_desc) {
+ rtype_desc->apply_out_typemap(NewStringf(
+ "$cresult ? new %s($cresult, %s) : nullptr;",
+ classname, owns
+ ));
+ }
+ break;
+
+ case Type_Ref:
+ if (rtype_desc) {
+ // We can't return a reference, as this requires an existing object and we don't have any, so we have to return an object instead, and this object
+ // must be constructed using the special ctor not taking the pointer ownership.
+ typestr = Copy(classname);
+
+ rtype_desc->apply_out_typemap(NewStringf("%s{$cresult, false}", classname));
+ }
+
+ if (ptype_desc) {
+ ptype_desc->apply_in_typemap(NewString("$1.swig_self()"));
+ }
+ break;
+
+ case Type_Obj:
+ if (rtype_desc) {
+ // The pointer returned by C function wrapping a function returning an object should never be null unless an exception happened, so we don't test
+ // for it here, unlike in Type_Ptr case.
+ //
+ // Also, normally all returned objects should be owned by their wrappers, but there is a special case of objects not being returned by value: this
+ // seems not to make sense, but can actually happen when typemaps map references or pointers to objects, like they do for e.g. shared_ptr<>.
+ //
+ // Note that we must use the type of the function, retrieved from its node, here and not the type passed to us which is the result of typemap
+ // expansion and so may not be a reference any more.
+ rtype_desc->apply_out_typemap(NewStringf("%s{$cresult, %s}",
+ typestr.get(),
+ SwigType_isreference(Getattr(n, "type")) ? owns : "true"
+ ));
+ }
+
+ if (ptype_desc) {
+ // It doesn't seem like it can ever be useful to pass an object by value to a wrapper function and it can fail if it doesn't have a copy ctor (see
+ // code related to has_copy_ctor_ in our dtor above), so always pass it by const reference instead.
+ Append(typestr, " const&");
+
+ ptype_desc->apply_in_typemap(NewString("$1.swig_self()"));
+ }
+ break;
+
+ case Type_Enm:
+ case Type_Max:
+ // Unreachable, but keep here to avoid -Wswitch warnings.
+ assert(0);
+ }
+ }
+
+ Replaceall(s, typemaps[typeKind], typestr);
+
+ if (rtype_desc)
+ rtype_desc->set_type(s);
+ if (ptype_desc)
+ ptype_desc->set_type(s);
+
+ return true;
+ }
+
+
+ // These pointers are temporarily set to non-null value only while expanding a typemap for C++ wrappers, see replaceSpecialVariables().
+ cxx_ptype_desc* ptype_desc_;
+ cxx_rtype_desc* rtype_desc_;
+
+ // This one is set from the outside, so make it public for simplicity.
+public:
+ Node* node_func_;
+};
+
+/*
+ cxx_function_wrapper
+
+ Outputs the C++ wrapper function. It's different from the C function because it is declared inside the namespace and so doesn't need the usual prefix and may
+ also have different parameter and return types when objects and/or cxx{in,out}type typemaps are involved.
+ */
+class cxx_function_wrapper
+{
+public:
+ // Call can_wrap() to check if this wrapper can be emitted later.
+ explicit cxx_function_wrapper(cxx_wrappers& cxx_wrappers, Node* n, Parm* p) : cxx_wrappers_(cxx_wrappers) {
+ func_node = NULL;
+
+ except_check_start =
+ except_check_end = "";
+
+ if (Checkattr(n, "feature:cxxignore", "1"))
+ return;
+
+ // Usually generating wrappers for overloaded methods is fine, but sometimes their types can clash after applying typemaps and in this case we have no
+ // choice but to avoid generating them, as otherwise we'd just generate uncompilable code.
+ if (Getattr(n, "sym:overloaded")) {
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore"))
+ return;
+ }
+
+ if (!cxx_wrappers_.lookup_cxx_ret_type(rtype_desc, n))
+ return;
+
+ parms_cxx = NewStringEmpty();
+ parms_call = NewStringEmpty();
+
+ if (p) {
+ // We want to use readable parameter names in our wrappers instead of the autogenerated arg$N if possible, so do it, and do it before calling
+ // Swig_typemap_attach_parms(), as this uses the parameter names for typemap expansion.
+ for (Parm* p2 = p; p2; p2 = nextSibling(p2)) {
+ String* name = Getattr(p, "name");
+ if (!name) {
+ // Can't do anything for unnamed parameters.
+ continue;
+ }
+
+ // Static variables use fully qualified names, so we need to strip the scope from them.
+ scoped_dohptr name_ptr;
+ if (Strstr(name, "::")) {
+ name_ptr = Swig_scopename_last(name);
+ name = name_ptr.get();
+ }
+
+ Setattr(p, "lname", name);
+ }
+
+ Swig_typemap_attach_parms("cxxin", p, NULL);
+
+ for (; p; p = Getattr(p, "tmap:in:next")) {
+ if (Checkattr(p, "tmap:in:numinputs", "0"))
+ continue;
+
+ String* const name = Getattr(p, "lname");
+
+ cxx_ptype_desc ptype_desc;
+ if (!cxx_wrappers_.lookup_cxx_parm_type(ptype_desc, n, p))
+ return;
+
+ if (Len(parms_cxx))
+ Append(parms_cxx, ", ");
+ Printv(parms_cxx, ptype_desc.type(), " ", name, NIL);
+
+ if (Len(parms_call))
+ Append(parms_call, ", ");
+ Append(parms_call, ptype_desc.get_param_code(name));
+ }
+ }
+
+
+ // Avoid checking for exceptions unnecessarily. Note that this is more than an optimization: we'd get into infinite recursion if we checked for exceptions
+ // thrown by members of SWIG_CException itself if we didn't do it.
+ if (cxx_wrappers_.is_exception_support_enabled() &&
+ !Checkattr(n, "noexcept", "true") &&
+ (!Checkattr(n, "throw", "1") || Getattr(n, "throws"))) {
+ except_check_start = cxx_wrappers_.except_check_start;
+ except_check_end = cxx_wrappers_.except_check_end;
+ }
+
+ // Everything is fine, so set func_node to indicate success.
+ func_node = n;
+ }
+
+ bool can_wrap() const { return func_node != NULL; }
+
+ // Emit just the function body, including the braces around it.
+ //
+ // This helper is used both by our emit() and emit_member_function().
+ void emit_body(String* wparms) {
+ String* const wname = Getattr(func_node, "wrap:name");
+
+ Append(cxx_wrappers_.sect_impls, "{");
+
+ if (rtype_desc.is_void()) {
+ Printv(cxx_wrappers_.sect_impls,
+ " ", wname, "(", wparms, "); ",
+ NIL
+ );
+
+ if (*except_check_start != '\0') {
+ Printv(cxx_wrappers_.sect_impls,
+ except_check_start,
+ except_check_end,
+ "; ",
+ NIL
+ );
+ }
+ } else {
+ rtype_desc.set_return_value(NewStringf("%s%s(%s)%s", except_check_start, wname, wparms, except_check_end));
+ Append(cxx_wrappers_.sect_impls, rtype_desc.get_return_code());
+ }
+
+ Append(cxx_wrappers_.sect_impls, "}\n");
+ }
+
+ // Do emit the function wrapper.
+ void emit() {
+ // The wrapper function name should be sym:name, but we change it to include the namespace prefix in our own globalvariableHandler(), so now we have to undo
+ // this by using the value saved there, if available. This is definitely clumsy and it would be better to avoid it, but this would probably need to be done
+ // by separating C and C++ wrapper generation in two different passes and so would require significantly more changes than this hack.
+ String* name = Getattr(func_node, "c:globalvariableHandler:sym:name");
+ if (!name)
+ name = Getattr(func_node, "sym:name");
+
+ Printv(cxx_wrappers_.sect_impls,
+ "inline ", rtype_desc.type(), " ", name, "(", parms_cxx.get(), ") ",
+ NIL
+ );
+
+ emit_body(parms_call);
+ }
+
+
+ cxx_wrappers& cxx_wrappers_;
+ Node* func_node;
+ cxx_rtype_desc rtype_desc;
+ scoped_dohptr parms_cxx;
+ scoped_dohptr parms_call;
+ const char* except_check_start;
+ const char* except_check_end;
+
+private:
+ // Non copyable.
+ cxx_function_wrapper(const cxx_function_wrapper&);
+ cxx_function_wrapper& operator=(const cxx_function_wrapper&);
+};
+
+
+/*
+ Return true if the class, or one of its base classes, uses multiple inheritance, i.e. has more than one base class.
+
+ The output first_base parameter is optional and is filled with the first base class (if any).
+*/
+bool uses_multiple_inheritance(Node* n, scoped_dohptr* first_base_out = NULL) {
+ if (first_base_out)
+ first_base_out->reset();
+
+ List* const baselist = Getattr(n, "bases");
+ if (!baselist)
+ return false;
+
+ scoped_dohptr first_base;
+ for (Iterator i = First(baselist); i.item; i = Next(i)) {
+ if (Checkattr(i.item, "feature:ignore", "1"))
+ continue;
+
+ if (first_base)
+ return true;
+
+ if (uses_multiple_inheritance(i.item))
+ return true;
+
+ first_base = Copy(i.item);
+ }
+
+ if (first_base_out)
+ *first_base_out = first_base;
+
+ return false;
+}
+
+/*
+ cxx_class_wrapper
+
+ Outputs the declaration of the class wrapping the given one if we're generating C++ wrappers, i.e. if the provided cxx_wrappers object is initialized.
+*/
+class cxx_class_wrapper
+{
+public:
+ // If the provided cxx_wrappers object is not initialized, this class doesn't do anything.
+ //
+ // The node pointer must be valid, point to a class and remain valid for the lifetime of this object.
+ cxx_class_wrapper(cxx_wrappers& cxx_wrappers, Node* n) : cxx_wrappers_(cxx_wrappers) {
+ class_node_ = NULL;
+
+ if (!cxx_wrappers_.is_initialized())
+ return;
+
+ if (Checkattr(n, "feature:cxxignore", "1"))
+ return;
+
+ String* const classname = Getattr(n, "sym:name");
+
+ scoped_dohptr base_classes(NewStringEmpty());
+ if (uses_multiple_inheritance(n, &first_base_)) {
+ Swig_warning(WARN_C_UNSUPPORTTED, Getfile(n), Getline(n),
+ "Multiple inheritance not supported yet, skipping C++ wrapper generation for %s\n",
+ classname
+ );
+
+ // Return before initializing class_node_, so that the dtor won't output anything neither.
+ return;
+ }
+
+ if (first_base_)
+ Printv(base_classes, " : public ", Getattr(first_base_, "sym:name"), NIL);
+
+ Printv(cxx_wrappers_.sect_types,
+ "class ", classname, ";\n",
+ NIL
+ );
+
+ Printv(cxx_wrappers_.sect_decls,
+ "class ", classname, base_classes.get(), " {\n"
+ "public:",
+ NIL
+ );
+
+ // If we have any extra code, inject it. Note that we need a hack with an artificial extra node to use Swig_typemap_lookup(), as it needs a "type" attribute
+ // which the class node doesn't have.
+ scoped_dohptr dummy(NewHash());
+ Setattr(dummy, "type", Getattr(n, "name"));
+ Setfile(dummy, Getfile(n));
+ Setline(dummy, Getline(n));
+ scoped_dohptr cxxcode(Swig_typemap_lookup("cxxcode", dummy, "", NULL));
+ if (!cxxcode || *Char(cxxcode) != '\n')
+ Append(cxx_wrappers_.sect_decls, "\n");
+ if (cxxcode) {
+ Replaceall(cxxcode, "$cxxclassname", classname);
+ Replaceall(cxxcode, "$cclassptrname", get_c_class_ptr(n));
+ Append(cxx_wrappers_.sect_decls, cxxcode);
+ }
+
+ class_node_ = n;
+ dtor_wname_ = NULL;
+ has_copy_ctor_ = false;
+ }
+
+ // Get indentation used inside this class declaration.
+ const char* get_indent() const {
+ // Currently we always use a single level of indent, but this would need to change if/when nested classes are supported.
+ //
+ // As the first step, we should probably change all occurrences of "cindent" in this class itself to use get_indent() instead.
+ return cindent;
+ }
+
+ // Emit wrapper of a member function.
+ void emit_member_function(Node* n) {
+ if (!class_node_)
+ return;
+
+ // We don't need to redeclare functions inherited from the base class, as we use real inheritance.
+ if (Getattr(n, "c:inherited_from"))
+ return;
+
+ // And we even don't need to redeclare virtual functions actually overridden in the derived class, as their implementation is the same as in the base class
+ // anyhow, so don't bother generating needless extra code.
+ if (Getattr(n, "override"))
+ return;
+
+ // Also ignore friend function declarations: they appear inside the class, but we shouldn't generate any wrappers for them.
+ if (Checkattr(n, "storage", "friend"))
+ return;
+
+ // As mentioned elsewhere, we can't use Swig_storage_isstatic() here because the "storage" attribute is temporarily saved in another view when this
+ // function is being executed, so rely on another attribute to determine if it's a static function instead.
+ const bool is_member = Checkattr(n, "ismember", "1");
+ const bool is_static = is_member && Getattr(n, "cplus:staticbase");
+ const bool is_ctor = Checkattr(n, "nodeType", "constructor");
+
+ Parm* p = Getattr(n, "parms");
+ if (p && is_member && !is_ctor && !is_static) {
+ // We should have "this" as the first parameter and we need to just skip it, as we handle it specially in C++ wrappers.
+ if (Checkattr(p, "name", "self")) {
+ p = nextSibling(p);
+ } else {
+ // This is not supposed to happen, so warn if it does.
+ Swig_warning(WARN_C_UNSUPPORTTED, Getfile(n), Getline(n),
+ "Unexpected first parameter \"%s\" in %s\n",
+ Getattr(p, "name"),
+ Getattr(n, "sym:name"));
+ }
+ }
+
+ cxx_function_wrapper func_wrapper(cxx_wrappers_, n, p);
+ if (!func_wrapper.can_wrap())
+ return;
+
+ // Define aliases for the stuff actually stored in the function wrapper object.
+ cxx_rtype_desc& rtype_desc = func_wrapper.rtype_desc;
+ String* const parms_cxx = func_wrapper.parms_cxx;
+ String* const parms_call = func_wrapper.parms_call;
+
+ // For some reason overloaded functions use fully-qualified name, so we can't just use the name directly.
+ scoped_dohptr name_ptr(Swig_scopename_last(Getattr(n, "name")));
+ String* const name = name_ptr;
+ String* const wname = Getattr(n, "wrap:name");
+
+ String* const classname = Getattr(class_node_, "sym:name");
+
+ if (Checkattr(n, "kind", "variable")) {
+ if (Checkattr(n, "memberget", "1")) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, rtype_desc.type(), " ", name, "() const;\n",
+ NIL
+ );
+
+ rtype_desc.set_return_value(NewStringf("%s(swig_self())", Getattr(n, "sym:name")));
+ Printv(cxx_wrappers_.sect_impls,
+ "inline ", rtype_desc.type(), " ", classname, "::", name, "() const "
+ "{", rtype_desc.get_return_code().get(), "}\n",
+ NIL
+ );
+ } else if (Checkattr(n, "memberset", "1")) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, "void ", name, "(", parms_cxx, ");\n",
+ NIL
+ );
+
+ Printv(cxx_wrappers_.sect_impls,
+ "inline void ", classname, "::", name, "(", parms_cxx, ") "
+ "{ ", Getattr(n, "sym:name"), "(swig_self(), ", parms_call, "); }\n",
+ NIL
+ );
+ } else if (Checkattr(n, "varget", "1")) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, "static ", rtype_desc.type(), " ", name, "();\n",
+ NIL
+ );
+
+ rtype_desc.set_return_value(NewStringf("%s()", Getattr(n, "sym:name")));
+ Printv(cxx_wrappers_.sect_impls,
+ "inline ", rtype_desc.type(), " ", classname, "::", name, "() "
+ "{", rtype_desc.get_return_code().get(), "}\n",
+ NIL
+ );
+ } else if (Checkattr(n, "varset", "1")) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, "static void ", name, "(", parms_cxx, ");\n",
+ NIL
+ );
+
+ Printv(cxx_wrappers_.sect_impls,
+ "inline void ", classname, "::", name, "(", parms_cxx, ") "
+ "{ ", Getattr(n, "sym:name"), "(", parms_call, "); }\n",
+ NIL
+ );
+ } else {
+ Swig_warning(WARN_C_UNSUPPORTTED, Getfile(n), Getline(n),
+ "Not generating C++ wrappers for variable %s\n",
+ Getattr(n, "sym:name")
+ );
+ }
+ } else if (is_ctor) {
+ // Delegate to the ctor from opaque C pointer taking ownership of the object.
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, classname, "(", parms_cxx, ");\n",
+ NIL
+ );
+
+ Printv(cxx_wrappers_.sect_impls,
+ "inline ", classname, "::", classname, "(", parms_cxx, ") : ",
+ classname, "{",
+ func_wrapper.except_check_start,
+ wname, "(", parms_call, ")",
+ func_wrapper.except_check_end,
+ "} {}\n",
+ NIL
+ );
+
+ // Remember that we had a copy ctor.
+ if (Checkattr(n, "copy_constructor", "1"))
+ has_copy_ctor_ = true;
+ } else if (Checkattr(n, "nodeType", "destructor")) {
+ if (first_base_) {
+ // Delete the pointer and reset the ownership flag to ensure that the base class doesn't do it again.
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, get_virtual_prefix(n), "~", classname, "() {\n",
+ cindent, cindent, "if (swig_owns_self_) {\n",
+ cindent, cindent, cindent, wname, "(swig_self());\n",
+ cindent, cindent, cindent, "swig_owns_self_ = false;\n",
+ cindent, cindent, "}\n",
+ cindent, "}\n",
+ NIL
+ );
+ } else {
+ // Slightly simplified version for classes without base classes, as we don't need to reset swig_self_ then.
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, get_virtual_prefix(n), "~", classname, "() {\n",
+ cindent, cindent, "if (swig_owns_self_)\n",
+ cindent, cindent, cindent, wname, "(swig_self_);\n",
+ cindent, "}\n",
+ NIL
+ );
+
+ // We're also going to need this in move assignment operator.
+ dtor_wname_ = wname;
+ }
+ } else if (is_member) {
+ // Wrapper parameters list may or not include "this" pointer and may or not have other parameters, so construct it piecewise for simplicity.
+ scoped_dohptr wparms(NewStringEmpty());
+ if (!is_static)
+ Append(wparms, "swig_self()");
+ if (Len(parms_call)) {
+ if (Len(wparms))
+ Append(wparms, ", ");
+ Append(wparms, parms_call);
+ }
+
+ Printv(cxx_wrappers_.sect_decls,
+ cindent,
+ is_static ? "static " : get_virtual_prefix(n), rtype_desc.type(), " ",
+ name, "(", parms_cxx, ")",
+ get_const_suffix(n), ";\n",
+ NIL
+ );
+
+ Printv(cxx_wrappers_.sect_impls,
+ "inline ", rtype_desc.type(), " ",
+ classname, "::", name, "(", parms_cxx, ")",
+ get_const_suffix(n),
+ " ",
+ NIL
+ );
+
+ func_wrapper.emit_body(wparms);
+ } else {
+ // This is something we don't know about
+ Swig_warning(WARN_C_UNSUPPORTTED, Getfile(n), Getline(n),
+ "Not generating C++ wrappers for %s\n",
+ Getattr(n, "sym:name")
+ );
+ }
+ }
+
+ ~cxx_class_wrapper() {
+ // Don't do anything if generation of the wrapper for this class was disabled in ctor.
+ if (!class_node_)
+ return;
+
+ // This is the name used for the class pointers in C wrappers.
+ scoped_dohptr c_class_ptr = get_c_class_ptr(class_node_);
+
+ String* const classname = Getattr(class_node_, "sym:name");
+
+ // We need to generate a ctor from the C object pointer, which is required to be able to create objects of this class from pointers created by C wrappers
+ // and also by any derived classes.
+ Printv(cxx_wrappers_.sect_decls,
+ "\n",
+ cindent, "explicit ", classname, "(", c_class_ptr.get(), " swig_self, "
+ "bool swig_owns_self = true) noexcept : ",
+ NIL
+ );
+
+ if (first_base_) {
+ // In this case we delegate to the base class ctor, but need a cast because it expects a different pointer type (as these types are opaque, there is no
+ // relationship between them).
+ Printv(cxx_wrappers_.sect_decls,
+ Getattr(first_base_, "sym:name"),
+ "{(", get_c_class_ptr(first_base_).get(), ")swig_self, swig_owns_self}",
+ NIL
+ );
+ } else {
+ // Just initialize our own field.
+ Printv(cxx_wrappers_.sect_decls,
+ "swig_self_{swig_self}, swig_owns_self_{swig_owns_self}",
+ NIL
+ );
+ }
+
+ Append(cxx_wrappers_.sect_decls, " {}\n");
+
+ // If the class doesn't have a copy ctor, forbid copying it: we currently must do it even if the original class has a perfectly cromulent implicit copy ctor
+ // because we don't wrap it and copying would use the trivial ctor that would just copy the swig_self_ pointer resulting in double destruction of it later.
+ // To fix this, we would need to always provide our own C wrapper for the copy ctor, which is not something we do currently.
+ if (!has_copy_ctor_) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, classname, "(", classname, " const&) = delete;\n",
+ NIL
+ );
+ }
+
+ // We currently never wrap the assignment operator, so we have to always disable it for the same reason we disable the copy ctor above.
+ // It would definitely be nice to provide the assignment, if possible.
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, classname, "& operator=(", classname, " const&) = delete;\n",
+ NIL
+ );
+
+ // OTOH we may always provide move ctor and assignment, as we can always implement them trivially ourselves.
+ if (first_base_) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, classname, "(", classname, "&& obj) = default;\n",
+ cindent, classname, "& operator=(", classname, "&& obj) = default;\n",
+ NIL
+ );
+ } else {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, classname, "(", classname, "&& obj) noexcept : "
+ "swig_self_{obj.swig_self_}, swig_owns_self_{obj.swig_owns_self_} { "
+ "obj.swig_owns_self_ = false; "
+ "}\n",
+ cindent, classname, "& operator=(", classname, "&& obj) noexcept {\n",
+ NIL
+ );
+
+ if (dtor_wname_) {
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, cindent, "if (swig_owns_self_)\n",
+ cindent, cindent, cindent, dtor_wname_, "(swig_self_);\n",
+ NIL
+ );
+ }
+
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, cindent, "swig_self_ = obj.swig_self_;\n",
+ cindent, cindent, "swig_owns_self_ = obj.swig_owns_self_;\n",
+ cindent, cindent, "obj.swig_owns_self_ = false;\n",
+ cindent, cindent, "return *this;\n",
+ cindent, "}\n",
+ NIL
+ );
+ }
+
+ // We also need a swig_self() method for accessing the C object pointer.
+ Printv(cxx_wrappers_.sect_decls,
+ cindent, c_class_ptr.get(), " swig_self() const noexcept ",
+ NIL
+ );
+
+ if (first_base_) {
+ // If we have a base class, we reuse its existing "self" pointer.
+ Printv(cxx_wrappers_.sect_decls,
+ "{ return (", c_class_ptr.get(), ")", Getattr(first_base_, "sym:name"), "::swig_self(); }\n",
+ NIL
+ );
+ } else {
+ // We use our own pointer, which we also have to declare, together with the ownership flag.
+ //
+ // Perhaps we could avoid having a separate bool flag by reusing the low-order bit of the pointer itself as the indicator of ownership and masking it when
+ // retrieving it here in the future. If we decide to implement this optimization, the code generated here should be the only thing that would need to
+ // change.
+ Printv(cxx_wrappers_.sect_decls,
+ "{ return swig_self_; }\n",
+ cindent, c_class_ptr.get(), " swig_self_;\n",
+ cindent, "bool swig_owns_self_;\n",
+ NIL
+ );
+ }
+
+ Printv(cxx_wrappers_.sect_decls,
+ "};\n"
+ "\n",
+ NIL
+ );
+ }
+
+private:
+ // Various helpers.
+
+ // Return the string containing the pointer type used for representing the objects of the given class in the C wrappers.
+ //
+ // Returned value includes "*" at the end.
+ static scoped_dohptr get_c_class_ptr(Node* class_node) {
+ return scoped_dohptr(NewStringf("SwigObj_%s*", get_c_proxy_name(class_node)));
+ }
+
+ // Return "virtual " if this is a virtual function, empty string otherwise.
+ static const char* get_virtual_prefix(Node* n) {
+ return Checkattr(n, "storage", "virtual") ? "virtual " : "";
+ }
+
+ // Return " const" if this is a const function, empty string otherwise.
+ static const char* get_const_suffix(Node* n) {
+ String* const qualifier = Getattr(n, "qualifier");
+ return qualifier && strncmp(Char(qualifier), "q(const)", 8) == 0 ? " const" : "";
+ }
+
+
+ cxx_wrappers& cxx_wrappers_;
+
+ // The class node itself, left null only if we skip generating wrappers for it for whatever reason.
+ Node* class_node_;
+
+ // We currently don't support generating C++ wrappers for classes using multiple inheritance. This could be implemented, with some tweaks to allow
+ // initializing the other base classes after creating the most-derived object, but hasn't been done yet. Until then we store just the first base class (if
+ // any, this member can also be null).
+ scoped_dohptr first_base_;
+
+ // Name of the C function used for deleting the owned object, if any.
+ String* dtor_wname_;
+
+ // True if the class defines an explicit copy ctor.
+ bool has_copy_ctor_;
+
+
+ // Non copyable.
+ cxx_class_wrapper(const cxx_class_wrapper&);
+ cxx_class_wrapper& operator=(const cxx_class_wrapper&);
+};
+
+} // anonymous namespace
+
+class C:public Language {
+ static const char *usage;
+
+ // These files contain types used by the wrappers declarations and the declarations themselves and end up in the output header file.
+ String *sect_wrappers_types;
+ String *sect_wrappers_decl;
+
+ // This one contains wrapper functions definitions and end up in the output C++ file.
+ String *sect_wrappers;
+
+ String *empty_string;
+
+ // Namespace used for the C++ wrappers, set from -namespace command-line option if specified or from the module name otherwise.
+ String *ns_cxx;
+
+ // Prefix used for all symbols, if non-null. If ns_cxx was specified, it is a mangled version of it.
+ String *ns_prefix;
+
+ // Name of the module, used as a prefix for module-level symbols if ns_prefix is null.
+ String *module_name;
+
+ // Name of the output header, set in top().
+ String *outfile_h;
+
+ // Used only while generating wrappers for an enum and contains the prefix, ending with underscore, to use for enum elements or is empty.
+ scoped_dohptr enum_prefix_;
+
+ // Used only while generating wrappers for an enum, as we don't know if enum will have any elements or not in advance and we must not generate an empty enum,
+ // so we accumulate the full declaration here and then write it to sect_wrappers_types at once only if there are any elements.
+ String *enum_decl;
+
+ // Selects between the wrappers (public) declarations and (private) definitions.
+ enum {
+ output_wrapper_decl,
+ output_wrapper_def
+ } current_output;
+
+ // Selects between various kinds of needed support for exception-related code.
+ exceptions_support exceptions_support_;
+
+ // This object contains information necessary only for C++ wrappers generation, use its is_initialized() to check if this is being done.
+ cxx_wrappers cxx_wrappers_;
+
+ // Non-owning pointer to the current C++ class wrapper if we're currently generating one or NULL.
+ cxx_class_wrapper* cxx_class_wrapper_;
+
+ // This is parallel to enum_prefix_ but for C++ enum elements.
+ scoped_dohptr cxx_enum_prefix_;
+
+ // This is parallel to enum_decl but for C++ enum declaration.
+ String *cxx_enum_decl;
+
+ // An extra indent level needed for nested C++ enums.
+ const char* cxx_enum_indent;
+
+public:
+
+ /* -----------------------------------------------------------------------------
+ * C()
+ * ----------------------------------------------------------------------------- */
+
+ C() :
+ empty_string(NewString("")),
+ ns_cxx(NULL),
+ ns_prefix(NULL),
+ module_name(NULL),
+ outfile_h(NULL),
+ cxx_class_wrapper_(NULL)
+ {
+ UseWrapperSuffix = 1;
+ }
+
+ ~C()
+ {
+ Delete(ns_cxx);
+ Delete(ns_prefix);
+ }
+
+ // Construct the name to be used for a function with the given name in C wrappers.
+ //
+ // The returned string must be freed by caller.
+ maybe_owned_dohptr getFunctionWrapperName(Node *n, String *name) const
+ {
+ maybe_owned_dohptr wname;
+
+ // The basic idea here is that for class members we don't need to use any prefix at all, as they're already prefixed by the class name, which has the
+ // appropriate prefix, but we need to use a prefix for the other symbols.
+ //
+ // However there are a couple of special cases complicating this:
+ //
+ // - Friend functions are declared inside the class, but are not member functions, so we have to check for both the current class and "ismember" property.
+ // - Destructors and implicitly generated constructors don't have "ismember" for some reason, so we need to check for them specifically.
+ // - Variable getters and setters don't need to use the prefix as they don't clash with anything.
+ if ((getCurrentClass() &&
+ (Checkattr(n, "ismember", "1") ||
+ Checkattr(n, "nodeType", "constructor") ||
+ Checkattr(n, "nodeType", "destructor"))) ||
+- Checkattr(n, "varget", "1") || Checkattr(n, "varset", "1")) {
+ wname.assign_non_owned(name);
+ return wname;
+ }
+
+ // Use namespace as the prefix if feature:nspace is in use.
+ scoped_dohptr scopename_prefix;
+ if (GetFlag(parentNode(n), "feature:nspace")) {
+ scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
+ if (scopename_prefix) {
+ scoped_dohptr mangled_prefix(Swig_name_mangle_string(scopename_prefix));
+ scopename_prefix = mangled_prefix;
+ }
+ }
+
+ // Fall back to the module name if we don't use feature:nspace and don't have the global prefix neither.
+ //
+ // Note that we really, really need to use some prefix, as wrapper function can't have the same name as the original function being wrapped.
+ String* const prefix = scopename_prefix
+ ? scopename_prefix
+ : ns_prefix
+ ? ns_prefix
+ : module_name;
+
+ wname.assign_owned(NewStringf("%s_%s", prefix, name));
+ return wname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getClassProxyName()
+ *
+ * Test to see if a type corresponds to something wrapped with a proxy class.
+ * Return NULL if not, otherwise the proxy class name to be freed by the caller.
+ * ----------------------------------------------------------------------------- */
+
+ String *getClassProxyName(SwigType *t) {
+ Node *n = classLookup(t);
+
+ return n ? Copy(get_c_proxy_name(n)) : NULL;
+
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ *
+ * Return the name to use for the enum in the generated code.
+ * Also caches it in the node for subsequent access.
+ * Returns NULL if the node doesn't correspond to an enum.
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(Node *n) {
+ String *enumname = Getattr(n, "enumname");
+ if (!enumname) {
+ // We can't use forward-declared enums because we can't define them for C wrappers (we could forward declare them in C++ if their underlying type,
+ // available as "inherit" node attribute, is specified, but not in C), so we have no choice but to use "int" for them.
+ if (Checkattr(n, "sym:weak", "1"))
+ return NULL;
+
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ // Add in class scope when referencing enum if not a global enum
+ String *proxyname = 0;
+ if (String *name = Getattr(n, "name")) {
+ if (String *scopename_prefix = Swig_scopename_prefix(name)) {
+ proxyname = getClassProxyName(scopename_prefix);
+ Delete(scopename_prefix);
+ }
+ }
+ if (proxyname) {
+ enumname = NewStringf("%s_%s", proxyname, symname);
+ Delete(proxyname);
+ } else {
+ // global enum or enum in a namespace
+ enumname = Copy(get_c_proxy_name(n));
+ }
+ Setattr(n, "enumname", enumname);
+ Delete(enumname);
+ }
+ }
+
+ return enumname;
+ }
+
+
+ /* -----------------------------------------------------------------------------
+ * substituteResolvedTypeSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteResolvedTypeSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
+ scoped_dohptr btype(SwigType_base(classnametype));
+ if (SwigType_isenum(btype)) {
+ Node* const enum_node = enumLookup(btype);
+ String* const enumname = enum_node ? getEnumName(enum_node) : NULL;
+
+ // We use the enum name in the wrapper declaration if it's available, as this makes it more type safe, but we always use just int for the function
+ // definition because we don't have the enum declaration in scope there. This obviously only actually works if the actual enum underlying type is int (or
+ // smaller).
+ maybe_owned_dohptr c_enumname;
+ if (current_output == output_wrapper_decl && enumname) {
+ // We need to add "enum" iff this is not already a typedef for the enum.
+ if (Checkattr(enum_node, "allows_typedef", "1"))
+ c_enumname.assign_non_owned(enumname);
+ else
+ c_enumname.assign_owned(NewStringf("enum %s", enumname));
+ } else {
+ c_enumname.assign_owned(NewString("int"));
+ }
+
+ Replaceall(tm, classnamespecialvariable, c_enumname);
+ } else {
+ if (!CPlusPlus) {
+ // Just use the original C type when not using C++, we know that this type can be used in the wrappers.
+ Clear(tm);
+ String* const s = SwigType_str(classnametype, 0);
+ Append(tm, s);
+ Delete(s);
+ return;
+ }
+
+ String* typestr = NIL;
+ if (current_output == output_wrapper_def || Cmp(btype, "SwigObj") == 0) {
+ // Special case, just leave it unchanged.
+ typestr = NewString("SwigObj");
+ } else {
+ typestr = getClassProxyName(btype);
+ if (!typestr) {
+ if (SwigType_isbuiltin(btype)) {
+ // This should work just as well in C without any changes.
+ typestr = SwigType_str(classnametype, 0);
+ } else {
+ // Swig doesn't know anything about this type, use descriptor for it.
+ typestr = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+
+ // And make sure it is declared before it is used.
+ Printf(sect_wrappers_types, "typedef struct %s %s;\n\n", typestr, typestr);
+ }
+ }
+ }
+
+ Replaceall(tm, classnamespecialvariable, typestr);
+ Delete(typestr);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteResolvedType()
+ *
+ * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
+ * that SWIG knows about. Also substitutes enums with enum name.
+ * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
+ * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
+ * Inputs:
+ * pt - parameter type
+ * tm - typemap contents that might contain the special variable to be replaced
+ * Outputs:
+ * tm - typemap contents complete with the special variable substitution
+ * ----------------------------------------------------------------------------- */
+
+ void substituteResolvedType(SwigType *pt, String *tm) {
+ SwigType *type = SwigType_typedef_resolve_all(pt);
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$resolved_type")) {
+ SwigType *classnametype = Copy(strippedtype);
+ substituteResolvedTypeSpecialVariable(classnametype, tm, "$resolved_type");
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*resolved_type")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ if (Len(classnametype) > 0) {
+ substituteResolvedTypeSpecialVariable(classnametype, tm, "$*resolved_type");
+ }
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&resolved_type")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ substituteResolvedTypeSpecialVariable(classnametype, tm, "$&resolved_type");
+ Delete(classnametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+ }
+
+ /*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *
+ * Override the base class method to ensure that $resolved_type is expanded correctly inside $typemap().
+ *--------------------------------------------------------------------*/
+
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ // This function is called by Swig_typemap_lookup(), which may be called when generating C or C++ wrappers, so delegate to the latter one if necessary.
+ if (cxx_wrappers_.is_initialized() && cxx_wrappers_.replaceSpecialVariables(method, tm, parm))
+ return;
+
+ SwigType *type = Getattr(parm, "type");
+ substituteResolvedType(type, tm);
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ bool except_flag = CPlusPlus;
+ bool use_cxx_wrappers = CPlusPlus;
+
+ // look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ } else if (strcmp(argv[i], "-namespace") == 0) {
+ if (argv[i + 1]) {
+ ns_cxx = NewString(argv[i + 1]);
+ ns_prefix = Swig_name_mangle_string(ns_cxx);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-nocxx") == 0) {
+ use_cxx_wrappers = false;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noexcept") == 0) {
+ except_flag = false;
+ Swig_mark_arg(i);
+ }
+ }
+ }
+
+ // add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGC 1", 0);
+ if (except_flag)
+ Preprocessor_define("SWIG_C_EXCEPT 1", 0);
+ if (CPlusPlus)
+ Preprocessor_define("SWIG_CPPMODE 1", 0);
+ if (use_cxx_wrappers)
+ Preprocessor_define("SWIG_CXX_WRAPPERS 1", 0);
+
+ SWIG_library_directory("c");
+
+ SWIG_config_file("c.swg");
+
+ String* const ns_prefix_ = ns_prefix ? NewStringf("%s_", ns_prefix) : NewString("");
+
+ // The default naming convention is to use new_Foo(), copy_Foo() and delete_Foo() for the default/copy ctor and dtor of the class Foo, but we prefer to
+ // start all Foo methods with the same prefix, so change this. Notice that new/delete are chosen to ensure that we avoid conflicts with the existing class
+ // methods, more natural create/destroy, for example, could result in errors if the class already had a method with the same name, but this is impossible
+ // for the chosen names as they're keywords in C++ ("copy" is still a problem but we'll just have to live with it).
+ Swig_name_register("construct", NewStringf("%s%%n%%c_new", ns_prefix_));
+ Swig_name_register("copy", NewStringf("%s%%n%%c_copy", ns_prefix_));
+ Swig_name_register("destroy", NewStringf("%s%%n%%c_delete", ns_prefix_));
+
+ // These ones are only needed when using a global prefix, as otherwise the defaults are fine.
+ if (ns_prefix) {
+ Swig_name_register("member", NewStringf("%s%%n%%c_%%m", ns_prefix_));
+ Swig_name_register("type", NewStringf("%s%%c", ns_prefix_));
+ }
+
+ Delete(ns_prefix_);
+
+ exceptions_support_ = except_flag ? exceptions_support_enabled : exceptions_support_disabled;
+
+ if (use_cxx_wrappers)
+ cxx_wrappers_.initialize();
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ module_name = Getattr(n, "name");
+ String *outfile = Getattr(n, "outfile");
+
+ // initialize I/O
+ const scoped_dohptr f_wrappers_cxx(NewFile(outfile, "w", SWIG_output_files()));
+ if (!f_wrappers_cxx) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ Swig_banner(f_wrappers_cxx);
+
+ Swig_obligatory_macros(f_wrappers_cxx, "C");
+
+ // Open the file where all wrapper declarations will be written to in the end.
+ outfile_h = Getattr(n, "outfile_h");
+ const scoped_dohptr f_wrappers_h(NewFile(outfile_h, "w", SWIG_output_files()));
+ if (!f_wrappers_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+
+ Swig_banner(f_wrappers_h);
+
+ // Associate file with the SWIG sections with the same name, so that e.g. "%header" contents end up in sect_header etc.
+ const scoped_dohptr sect_begin(NewStringEmpty());
+ const scoped_dohptr sect_header(NewStringEmpty());
+ const scoped_dohptr sect_runtime(NewStringEmpty());
+ const scoped_dohptr sect_init(NewStringEmpty());
+
+ // This one is used outside of this function, so it's a member variable rather than a local one.
+ sect_wrappers = NewStringEmpty();
+
+ Swig_register_filebyname("begin", sect_begin);
+ Swig_register_filebyname("header", sect_header);
+ Swig_register_filebyname("wrapper", sect_wrappers);
+ Swig_register_filebyname("runtime", sect_runtime);
+ Swig_register_filebyname("init", sect_init);
+
+ // This one is C-specific and goes directly to the output header file.
+ Swig_register_filebyname("cheader", f_wrappers_h);
+
+ // Deal with exceptions support.
+ if (exceptions_support_ == exceptions_support_enabled) {
+ // Redefine SWIG_CException_Raise() to have a unique prefix in the shared library built from SWIG-generated sources to allow using more than one extension
+ // in the same process without conflicts. This has to be done in this hackish way because we really need to change the name of the function itself, not
+ // its wrapper (which is not even generated).
+ Printv(sect_runtime,
+ "#define SWIG_CException_Raise ", (ns_prefix ? ns_prefix : module_name), "_SWIG_CException_Raise\n",
+ NIL
+ );
+
+ // We need to check if we have any %imported modules, as they would already define the exception support code and we want to have exactly one copy of it
+ // in the generated shared library, so check for "import" nodes.
+ if (find_first_named_import(n)) {
+ // We import another module, which will have already defined SWIG_CException, so set the flag indicating that we shouldn't do it again in this one and
+ // define the symbol to skip compiling its implementation.
+ Printv(sect_runtime, "#define SWIG_CException_DEFINED 1\n", NIL);
+
+ // Also set a flag telling classDeclaration() to skip creating SWIG_CException wrappers.
+ exceptions_support_ = exceptions_support_imported;
+ }
+ }
+
+ if (cxx_wrappers_.is_initialized())
+ cxx_wrappers_.initialize_exceptions(exceptions_support_);
+
+ {
+ String* const include_guard_name = NewStringf("SWIG_%s_WRAP_H_", module_name);
+ String* const include_guard_begin = NewStringf(
+ "#ifndef %s\n"
+ "#define %s\n\n",
+ include_guard_name,
+ include_guard_name
+ );
+ String* const include_guard_end = NewStringf(
+ "\n"
+ "#endif /* %s */\n",
+ include_guard_name
+ );
+
+ begin_end_output_guard
+ include_guard_wrappers_h(f_wrappers_h, include_guard_begin, include_guard_end);
+
+ // All the struct types used by the functions go to f_wrappers_types so that they're certain to be defined before they're used by any functions. All the
+ // functions declarations go directly to f_wrappers_decl we write both of them to f_wrappers_h at the end.
+ sect_wrappers_types = NewString("");
+ sect_wrappers_decl = NewString("");
+
+ {
+ cplusplus_output_guard
+ cplusplus_guard_wrappers(sect_wrappers),
+ cplusplus_guard_wrappers_h(sect_wrappers_decl);
+
+ // emit code for children
+ Language::top(n);
+ } // close extern "C" guards
+
+ Dump(sect_wrappers_types, f_wrappers_h);
+ Delete(sect_wrappers_types);
+
+ Dump(sect_wrappers_decl, f_wrappers_h);
+ Delete(sect_wrappers_decl);
+
+ if (cxx_wrappers_.is_initialized()) {
+ if (!ns_cxx) {
+ // We need some namespace for the C++ wrappers as otherwise their names could conflict with the C functions, so use the module name if nothing was
+ // explicitly specified.
+ ns_cxx = Copy(module_name);
+ }
+
+ Printv(f_wrappers_h, "#ifdef __cplusplus\n\n", NIL);
+ Dump(cxx_wrappers_.sect_cxx_h, f_wrappers_h);
+
+ // Generate possibly nested namespace declarations, as unfortunately we can't rely on C++17 nested namespace definitions being always available.
+ scoped_dohptr cxx_ns_end(NewStringEmpty());
+ for (const char* c = Char(ns_cxx);;) {
+ const char* const next = strstr(c, "::");
+
+ maybe_owned_dohptr ns_component;
+ if (next) {
+ ns_component.assign_owned(NewStringWithSize(c, next - c));
+ } else {
+ ns_component.assign_non_owned((DOH*)c);
+ }
+
+ Printf(f_wrappers_h, "namespace %s {\n", ns_component.get());
+ Printf(cxx_ns_end, "}\n");
+
+ if (!next)
+ break;
+
+ c = next + 2;
+ }
+
+ Printv(f_wrappers_h, "\n", NIL);
+ Dump(cxx_wrappers_.sect_types, f_wrappers_h);
+
+ Printv(f_wrappers_h, "\n", NIL);
+ Dump(cxx_wrappers_.sect_decls, f_wrappers_h);
+
+ Printv(f_wrappers_h, "\n", NIL);
+ Dump(cxx_wrappers_.sect_impls, f_wrappers_h);
+
+ Printv(f_wrappers_h, "\n", cxx_ns_end.get(), "\n#endif /* __cplusplus */\n", NIL);
+ }
+ } // close wrapper header guard
+
+ // write all to the file
+ Dump(sect_begin, f_wrappers_cxx);
+ Dump(sect_runtime, f_wrappers_cxx);
+ Dump(sect_header, f_wrappers_cxx);
+ Dump(sect_wrappers, f_wrappers_cxx);
+ Dump(sect_init, f_wrappers_cxx);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ // When we import another module, we need access to its declarations in our header, so we must include the header generated for that module. Unfortunately
+ // there doesn't seem to be any good way to get the name of that header, so we try to guess it from the header name of this module. This is obviously not
+ // completely reliable, but works reasonably well in practice and it's not clear what else could we do, short of requiring some C-specific %import attribute
+ // specifying the name of the header explicitly.
+
+ // We can only do something if we have a module name.
+ if (String* const imported_module_name = Getattr(n, "module")) {
+ // Start with our header name.
+ scoped_dohptr header_name(Copy(outfile_h));
+
+ // Strip the output directory from the file name, as it should be common to all generated headers.
+ Replace(header_name, SWIG_output_directory(), "", DOH_REPLACE_FIRST);
+
+ // And replace our module name with the name of the one being imported.
+ Replace(header_name, module_name, imported_module_name, DOH_REPLACE_FIRST);
+
+ // Finally inject inclusion of this header.
+ Printv(Swig_filebyname("cheader"), "#include \"", header_name.get(), "\"\n", NIL);
+ }
+
+ return Language::importDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------------------ */
+
+ virtual int globalvariableHandler(Node *n) {
+ // Don't export static globals, they won't be accessible when using a shared library, for example.
+ if (Checkattr(n, "storage", "static"))
+ return SWIG_NOWRAP;
+
+ // We can't export variables defined inside namespaces to C directly, whatever their type, and we can only export them under their original name, so we
+ // can't do it when using a global namespace prefix neither.
+ if (!ns_prefix && !scoped_dohptr(Swig_scopename_prefix(Getattr(n, "name")))) {
+ // If we can export the variable directly, do it, this will be more convenient to use from C code than accessor functions.
+ if (String* const var_decl = make_c_var_decl(n)) {
+ Printv(sect_wrappers_decl, "SWIGIMPORT ", var_decl, ";\n\n", NIL);
+ Delete(var_decl);
+ return SWIG_OK;
+ }
+ }
+
+ // We have to prepend the global prefix to the names of the accessors for this variable, if we use one.
+ //
+ // Note that we can't just register the name format using the prefix for "get" and "set", as we do it for "member", and using it for both would result in
+ // the prefix being used twice for the member variables getters and setters, so we have to work around it here instead.
+ if (ns_prefix && !getCurrentClass()) {
+ Swig_require("c:globalvariableHandler", n, "*sym:name", NIL);
+ Setattr(n, "sym:name", NewStringf("%s_%s", ns_prefix, Getattr(n, "sym:name")));
+ }
+
+ // Otherwise, e.g. if it's of a C++-only type, or a reference, generate accessor functions for it.
+ int const rc = Language::globalvariableHandler(n);
+
+ if (Getattr(n, "view"))
+ Swig_restore(n);
+
+ return rc;
+ }
+
+ /* ----------------------------------------------------------------------
+ * prepend_feature()
+ * ---------------------------------------------------------------------- */
+
+ String* prepend_feature(Node *n) {
+ String *prepend_str = Getattr(n, "feature:prepend");
+ if (prepend_str) {
+ char *t = Char(prepend_str);
+ if (*t == '{') {
+ Delitem(prepend_str, 0);
+ Delitem(prepend_str, DOH_END);
+ }
+ }
+ return (prepend_str ? prepend_str : empty_string);
+ }
+
+ /* ----------------------------------------------------------------------
+ * append_feature()
+ * ---------------------------------------------------------------------- */
+
+ String* append_feature(Node *n) {
+ String *append_str = Getattr(n, "feature:append");
+ if (append_str) {
+ char *t = Char(append_str);
+ if (*t == '{') {
+ Delitem(append_str, 0);
+ Delitem(append_str, DOH_END);
+ }
+ }
+ return (append_str ? append_str : empty_string);
+ }
+
+ /* ----------------------------------------------------------------------
+ * get_mangled_type()
+ * ---------------------------------------------------------------------- */
+
+ String *get_mangled_type(SwigType *type_arg) {
+ String *result = NewString("");
+ SwigType *type = 0;
+ SwigType *tdtype = SwigType_typedef_resolve_all(type_arg);
+ if (tdtype)
+ type = tdtype;
+ else
+ type = Copy(type_arg);
+
+ // special cases for ptr to function as an argument
+ if (SwigType_ismemberpointer(type)) {
+ SwigType_del_memberpointer(type);
+ SwigType_add_pointer(type);
+ }
+ if (SwigType_ispointer(type)) {
+ SwigType_del_pointer(type);
+ if (SwigType_isfunction(type)) {
+ Printf(result, "f");
+ Delete(type);
+ return result;
+ }
+ Delete(type);
+ type = Copy(type_arg);
+ }
+
+ SwigType *prefix = SwigType_prefix(type);
+ if (Len(prefix)) {
+ Replaceall(prefix, ".", "");
+ Replaceall(prefix, "const", "c");
+ Replaceall(prefix, "volatile", "v");
+ Replaceall(prefix, "a(", "a");
+ Replaceall(prefix, "m(", "m");
+ Replaceall(prefix, "q(", "");
+ Replaceall(prefix, ")", "");
+ Replaceall(prefix, " ", "");
+ Printf(result, "%s", prefix);
+ }
+
+ type = SwigType_base(type);
+ if (SwigType_isbuiltin(type)) {
+ Printf(result, "%c", *Char(SwigType_base(type)));
+ } else if (SwigType_isenum(type)) {
+ String* enumname = Swig_scopename_last(type);
+ const char* s = Char(enumname);
+ static const int len_enum_prefix = strlen("enum ");
+ if (strncmp(s, "enum ", len_enum_prefix) == 0)
+ s += len_enum_prefix;
+ Printf(result, "e%s", s);
+ } else {
+ // Use Swig_name_mangle_type() here and not Swig_name_mangle_string() to get slightly simpler mangled name for templates (notably avoiding "_Sp_" and
+ // "_SP_" fragments for the parentheses used by SWIG internally around template parameters).
+ Printf(result, "%s", Char(Swig_name_mangle_type(SwigType_base(type))));
+ }
+
+ Delete(prefix);
+ Delete(type);
+
+ return result;
+ }
+
+ void functionWrapperCSpecific(Node *n)
+ {
+ // this is C function, we don't apply typemaps to it
+ String *name = Getattr(n, "sym:name");
+ maybe_owned_dohptr wname = getFunctionWrapperName(n, name);
+ SwigType *type = Getattr(n, "type");
+ SwigType *return_type = NULL;
+ String *arg_names = NULL;
+ ParmList *parms = Getattr(n, "parms");
+ Parm *p;
+ String *proto = NewString("");
+ int gencomma = 0;
+ bool is_void_return = (SwigType_type(type) == T_VOID);
+
+ // create new function wrapper object
+ Wrapper *wrapper = NewWrapper();
+
+ // create new wrapper name
+ Setattr(n, "wrap:name", wname); //Necessary to set this attribute? Apparently, it's never read!
+
+ // create function call
+ arg_names = Swig_cfunction_call(empty_string, parms);
+ if (arg_names) {
+ Delitem(arg_names, 0);
+ Delitem(arg_names, DOH_END);
+ }
+ return_type = SwigType_str(type, 0);
+
+ // emit wrapper prototype and code
+ for (p = parms, gencomma = 0; p; p = nextSibling(p)) {
+ Printv(proto, gencomma ? ", " : "", SwigType_str(Getattr(p, "type"), 0), " ", Getattr(p, "lname"), NIL);
+ gencomma = 1;
+ }
+ Printv(wrapper->def, return_type, " ", wname.get(), "(", proto, ") {\n", NIL);
+
+ if (!is_void_return) {
+ Printv(wrapper->code, return_type, " result;\n", NIL);
+ }
+
+ // attach 'check' typemaps
+ Swig_typemap_attach_parms("check", parms, wrapper);
+
+ // insert constraint checking
+ for (p = parms; p; ) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Replaceall(tm, "$name", name);
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Append(wrapper->code, prepend_feature(n));
+ if (!is_void_return) {
+ Printf(wrapper->code, "result = ");
+ }
+ Printv(wrapper->code, Getattr(n, "name"), "(", arg_names, ");\n", NIL);
+ Append(wrapper->code, append_feature(n));
+ if (!is_void_return)
+ Printf(wrapper->code, "return result;\n");
+ Printf(wrapper->code, "}");
+
+ Wrapper_print(wrapper, sect_wrappers);
+
+ emit_wrapper_func_decl(n, wname);
+
+ // cleanup
+ Delete(proto);
+ Delete(arg_names);
+ Delete(return_type);
+ DelWrapper(wrapper);
+ }
+
+ void functionWrapperAppendOverloaded(String *name, Parm* first_param)
+ {
+ String *over_suffix = NewString("");
+ Parm *p;
+ String *mangled;
+
+ for (p = first_param; p; p = nextSibling(p)) {
+ mangled = get_mangled_type(Getattr(p, "type"));
+ Printv(over_suffix, "_", mangled, NIL);
+ }
+ Append(name, over_suffix);
+ Delete(over_suffix);
+ }
+
+ scoped_dohptr get_wrapper_func_return_type(Node *n)
+ {
+ SwigType *type = Getattr(n, "type");
+ String *return_type;
+
+ if ((return_type = Swig_typemap_lookup("ctype", n, "", 0))) {
+ substituteResolvedType(type, return_type);
+ } else {
+ Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(type, 0));
+ return_type = NewString("");
+ }
+
+ Replaceall(return_type, "::", "_");
+
+ return scoped_dohptr(return_type);
+ }
+
+ /* ----------------------------------------------------------------------
+ * get_wrapper_func_proto()
+ *
+ * Return the function signature, i.e. the comma-separated list of argument types and names surrounded by parentheses.
+ * If a non-null wrapper is specified, it is used to emit typemap-defined code in it and it also determines whether we're generating the prototype for the
+ * declarations or the definitions, which changes the type used for the C++ objects.
+ * ---------------------------------------------------------------------- */
+ scoped_dohptr get_wrapper_func_proto(Node *n, Wrapper* wrapper = NULL)
+ {
+ ParmList *parms = Getattr(n, "parms");
+
+ Parm *p;
+ String *proto = NewString("(");
+ int gencomma = 0;
+
+ // attach the standard typemaps
+ if (wrapper) {
+ emit_attach_parmmaps(parms, wrapper);
+ } else {
+ // We can't call emit_attach_parmmaps() without a wrapper, it would just crash.
+ // Attach "in" manually, we need it for tmap:in:numinputs below.
+ Swig_typemap_attach_parms("in", parms, 0);
+ }
+ Setattr(n, "wrap:parms", parms); //never read again?!
+
+ // attach 'ctype' typemaps
+ Swig_typemap_attach_parms("ctype", parms, 0);
+
+
+ // prepare function definition
+ for (p = parms, gencomma = 0; p; ) {
+ String *tm;
+ SwigType *type = NULL;
+
+ while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ if (!p) break;
+
+ type = Getattr(p, "type");
+ if (SwigType_type(type) == T_VOID) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ if (SwigType_type(type) == T_VARARGS) {
+ Swig_error(Getfile(n), Getline(n), "Vararg function %s not supported.\n", Getattr(n, "name"));
+ return scoped_dohptr(NULL);
+ }
+
+ String *lname = Getattr(p, "lname");
+ String *c_parm_type = 0;
+ String *arg_name = NewString("");
+
+ Printf(arg_name, "c%s", lname);
+
+ if ((tm = Getattr(p, "tmap:ctype"))) { // set the appropriate type for parameter
+ c_parm_type = Copy(tm);
+ substituteResolvedType(type, c_parm_type);
+
+ // We prefer to keep typedefs in the wrapper functions signatures as it makes them more readable, but we can't do it for nested typedefs as
+ // they're not valid in C, so resolve them in this case.
+ if (strstr(Char(c_parm_type), "::")) {
+ SwigType* const tdtype = SwigType_typedef_resolve_all(c_parm_type);
+ Delete(c_parm_type);
+ c_parm_type = tdtype;
+ }
+
+ // template handling
+ Replaceall(c_parm_type, "$tt", SwigType_lstr(type, 0));
+ } else {
+ Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(type, 0));
+ }
+
+ Printv(proto, gencomma ? ", " : "", c_parm_type, " ", arg_name, NIL);
+ gencomma = 1;
+
+ // apply typemaps for input parameter
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", arg_name);
+ if (wrapper) {
+ Setattr(p, "emit:input", arg_name);
+ Printf(wrapper->code, "%s\n", tm);
+ }
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
+ p = nextSibling(p);
+ }
+
+ Delete(arg_name);
+ Delete(c_parm_type);
+ }
+
+ Printv(proto, ")", NIL);
+ return scoped_dohptr(proto);
+ }
+
+ /* ----------------------------------------------------------------------
+ * emit_wrapper_func_decl()
+ *
+ * Declares the wrapper function, using the C types used for it, in the header.
+ * The node here is a function declaration.
+ * ---------------------------------------------------------------------- */
+ void emit_wrapper_func_decl(Node *n, String *wname)
+ {
+ current_output = output_wrapper_decl;
+
+ // add function declaration to the proxy header file
+ Printv(sect_wrappers_decl, "SWIGIMPORT ", get_wrapper_func_return_type(n).get(), " ", wname, get_wrapper_func_proto(n).get(), ";\n\n", NIL);
+ }
+
+
+ void functionWrapperCPPSpecific(Node *n)
+ {
+ ParmList *parms = Getattr(n, "parms");
+ String *name = Copy(Getattr(n, "sym:name"));
+
+ // mangle name if function is overloaded
+ if (Getattr(n, "sym:overloaded")) {
+ if (!Getattr(n, "copy_constructor")) {
+ Parm* first_param = (Parm*)parms;
+ if (first_param) {
+ // Skip the first "this" parameter of the wrapped methods, it doesn't participate in overload resolution and would just result in extra long
+ // and ugly names.
+ //
+ // We need to avoid dropping the first argument of static methods which don't have "this" pointer, in spite of being members (and we have to
+ // use "cplus:staticbase" for this instead of just using Swig_storage_isstatic() because "storage" is reset in staticmemberfunctionHandler()
+ // and so is not available here.
+ //
+ // Of course, the constructors don't have the extra first parameter neither.
+ if (!Checkattr(n, "nodeType", "constructor") &&
+ Checkattr(n, "ismember", "1") &&
+ !Getattr(n, "cplus:staticbase")) {
+ first_param = nextSibling(first_param);
+
+ // A special case of overloading on const/non-const "this" pointer only, we still need to distinguish between those.
+ if (SwigType_isconst(Getattr(n, "decl"))) {
+ const char * const nonconst = Char(Getattr(n, "decl")) + 9 /* strlen("q(const).") */;
+ for (Node* nover = Getattr(n, "sym:overloaded"); nover; nover = Getattr(nover, "sym:nextSibling")) {
+ if (nover == n)
+ continue;
+
+ if (Cmp(Getattr(nover, "decl"), nonconst) == 0) {
+ // We have an overload differing by const only, disambiguate.
+ Append(name, "_const");
+ break;
+ }
+ }
+ }
+ }
+
+ functionWrapperAppendOverloaded(name, first_param);
+ }
+ }
+ }
+
+ // make sure lnames are set
+ Parm *p;
+ int index = 1;
+ String *lname = 0;
+
+ for (p = (Parm*)parms, index = 1; p; (p = nextSibling(p)), index++) {
+ if(!(lname = Getattr(p, "lname"))) {
+ lname = NewStringf("arg%d", index);
+ Setattr(p, "lname", lname);
+ }
+ }
+
+ // C++ function wrapper
+ current_output = output_wrapper_def;
+
+ SwigType *type = Getattr(n, "type");
+ scoped_dohptr return_type = get_wrapper_func_return_type(n);
+ maybe_owned_dohptr wname = getFunctionWrapperName(n, name);
+ bool is_void_return = (SwigType_type(type) == T_VOID);
+ // create new function wrapper object
+ Wrapper *wrapper = NewWrapper();
+
+ // create new wrapper name
+ Setattr(n, "wrap:name", wname);
+
+ // add variable for holding result of original function 'cppresult'
+ if (!is_void_return) {
+ SwigType *value_type = cplus_value_type(type);
+ SwigType* cppresult_type = value_type ? value_type : type;
+ SwigType* ltype = SwigType_ltype(cppresult_type);
+ Wrapper_add_local(wrapper, "cppresult", SwigType_str(ltype, "cppresult"));
+ Delete(ltype);
+ Delete(value_type);
+ }
+
+ // create wrapper function prototype
+ Printv(wrapper->def, "SWIGEXPORTC ", return_type.get(), " ", wname.get(), NIL);
+
+ Printv(wrapper->def, get_wrapper_func_proto(n, wrapper).get(), NIL);
+ Printv(wrapper->def, " {", NIL);
+
+ // emit variables for holding parameters
+ emit_parameter_variables(parms, wrapper);
+
+ // emit variable for holding function return value
+ emit_return_variable(n, return_type, wrapper);
+
+ // insert constraint checking
+ for (p = parms; p; ) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Replaceall(tm, "$name", name);
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // create action code
+ String *action = Getattr(n, "wrap:action");
+ if (!action)
+ action = NewString("");
+
+ String *cbase_name = Getattr(n, "c:base_name");
+ if (cbase_name) {
+ Replaceall(action, "arg1)->", NewStringf("(%s*)arg1)->", Getattr(n, "c:inherited_from")));
+ Replaceall(action, Getattr(n, "name"), cbase_name);
+ }
+
+ Replaceall(action, "result =", "cppresult =");
+
+ // prepare action code to use, e.g. insert try-catch blocks
+ action = emit_action(n);
+
+ // emit output typemap if needed
+ if (!is_void_return) {
+ String *tm;
+ if ((tm = Swig_typemap_lookup_out("out", n, "cppresult", wrapper, action))) {
+ // This is ugly, but the type of our result variable is not always the same as the actual return type currently because
+ // get_wrapper_func_return_type() applies ctype typemap to it. These types are more or less compatible though, so we should be able to cast
+ // between them explicitly.
+ const char* start = Char(tm);
+ const char* p = strstr(start, "$result = ");
+ if (p == start || (p && p[-1] == ' ')) {
+ p += strlen("$result = ");
+ scoped_dohptr result_cast(NewStringf("(%s)", return_type.get()));
+
+ // However don't add a cast which is already there.
+ if (strncmp(p, Char(result_cast), strlen(Char(result_cast))) != 0)
+ Insert(tm, p - start, result_cast);
+ }
+ Replaceall(tm, "$result", "result");
+ Replaceall(tm, "$owner", GetFlag(n, "feature:new") ? "1" : "0");
+ Printf(wrapper->code, "%s", tm);
+ if (Len(tm))
+ Printf(wrapper->code, "\n");
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), Getattr(n, "name"));
+ }
+ } else {
+ Append(wrapper->code, action);
+ }
+
+ // insert cleanup code
+ for (p = parms; p; ) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ if (tm && (Len(tm) != 0)) {
+ String *input = NewStringf("c%s", Getattr(p, "lname"));
+ Replaceall(tm, "$source", Getattr(p, "lname"));
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Printv(wrapper->code, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (is_void_return) {
+ Replaceall(wrapper->code, "$null", "");
+ Replaceall(wrapper->code, "$isvoid", "1");
+ } else {
+ Replaceall(wrapper->code, "$null", "0");
+ Replaceall(wrapper->code, "$isvoid", "0");
+
+ Append(wrapper->code, "return result;\n");
+ }
+
+ Append(wrapper->code, "}\n");
+
+ Wrapper_print(wrapper, sect_wrappers);
+
+ // cleanup
+ DelWrapper(wrapper);
+
+ emit_wrapper_func_decl(n, wname);
+
+ if (cxx_wrappers_.is_initialized()) {
+ temp_ptr_setter<Node*> set(&cxx_wrappers_.node_func_, n);
+
+ if (cxx_class_wrapper_) {
+ cxx_class_wrapper_->emit_member_function(n);
+ } else {
+ cxx_function_wrapper w(cxx_wrappers_, n, Getattr(n, "parms"));
+ if (w.can_wrap())
+ w.emit();
+ }
+ }
+
+ Delete(name);
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(Getattr(n, "sym:name"), n))
+ return SWIG_ERROR;
+ }
+
+ if (CPlusPlus) {
+ functionWrapperCPPSpecific(n);
+ } else {
+ functionWrapperCSpecific(n);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * copy_node()
+ *
+ * This is not a general-purpose node copying function, but just a helper of classHandler().
+ * --------------------------------------------------------------------- */
+
+ Node *copy_node(Node *node) {
+ Node *new_node = NewHash();
+ Setattr(new_node, "name", Copy(Getattr(node, "name")));
+ Setattr(new_node, "ismember", Copy(Getattr(node, "ismember")));
+ Setattr(new_node, "view", Copy(Getattr(node, "view")));
+ Setattr(new_node, "kind", Copy(Getattr(node, "kind")));
+ Setattr(new_node, "access", Copy(Getattr(node, "access")));
+ Setattr(new_node, "parms", Copy(Getattr(node, "parms")));
+ Setattr(new_node, "type", Copy(Getattr(node, "type")));
+ Setattr(new_node, "decl", Copy(Getattr(node, "decl")));
+
+ Node* const parent = parentNode(node);
+ Setattr(new_node, "c:inherited_from", Getattr(parent, "name"));
+ Setattr(new_node, "sym:name", Getattr(node, "sym:name"));
+ Setattr(new_node, "sym:symtab", Getattr(parent, "symtab"));
+ set_nodeType(new_node, "cdecl");
+
+ return new_node;
+ }
+
+ /* ---------------------------------------------------------------------
+ * is_in()
+ *
+ * tests if given name already exists in one of child nodes of n
+ * --------------------------------------------------------------------- */
+
+ Hash *is_in(String *name, Node *n) {
+ Hash *h;
+ for (h = firstChild(n); h; h = nextSibling(h)) {
+ if (Cmp(name, Getattr(h, "name")) == 0)
+ return h;
+ }
+ return 0;
+ }
+
+ /* ---------------------------------------------------------------------
+ * make_c_var_decl()
+ *
+ * Return the C declaration for the given node of "variable" kind.
+ *
+ * If the variable has a type not representable in C, returns NULL, the caller must check for this!
+ *
+ * This function accounts for two special cases:
+ * 1. If the type is an anonymous enum, "int" is used instead.
+ * 2. If the type is an array, its bounds are stripped.
+ * --------------------------------------------------------------------- */
+ String *make_c_var_decl(Node *n) {
+ String *name = Getattr(n, "name");
+ SwigType *type = Getattr(n, "type");
+ String *type_str = SwigType_str(type, 0);
+
+ if (Getattr(n, "unnamedinstance")) {
+ // If this is an anonymous enum, we can declare the variable as int even though we can't reference this type.
+ if (Strncmp(type_str, "enum $", 6) != 0) {
+ // Otherwise we're out of luck, with the current approach of exposing the variables directly we simply can't do it, we would need to use accessor
+ // functions instead to support this.
+ Swig_error(Getfile(n), Getline(n), "Variables of anonymous non-enum types are not supported.\n");
+ return SWIG_ERROR;
+ }
+
+ const char * const unnamed_end = strchr(Char(type_str) + 6, '$');
+ if (!unnamed_end) {
+ Swig_error(Getfile(n), Getline(n), "Unsupported anonymous enum type \"%s\".\n", type_str);
+ return SWIG_ERROR;
+ }
+
+ String* const int_type_str = NewStringf("int%s", unnamed_end + 1);
+ Delete(type_str);
+ type_str = int_type_str;
+ } else {
+ scoped_dohptr btype(SwigType_base(type));
+ if (SwigType_isenum(btype)) {
+ // Enums are special as they can be unknown, i.e. not wrapped by SWIG. In this case we just use int instead.
+ if (!enumLookup(btype)) {
+ Replaceall(type_str, btype, "int");
+ }
+ } else {
+ // Don't bother with checking if type is representable in C if we're wrapping C and not C++ anyhow: of course it is.
+ if (CPlusPlus) {
+ if (SwigType_isreference(type))
+ return NIL;
+
+ if (!SwigType_isbuiltin(btype))
+ return NIL;
+
+ // Final complication: define bool if it is used here.
+ if (Cmp(btype, "bool") == 0) {
+ Printv(sect_wrappers_types, "#include <stdbool.h>\n\n", NIL);
+ }
+ }
+ }
+ }
+
+ String* const var_decl = NewStringEmpty();
+ if (SwigType_isarray(type)) {
+ String *dims = Strchr(type_str, '[');
+ char *c = Char(type_str);
+ c[Len(type_str) - Len(dims) - 1] = '\0';
+ Printv(var_decl, c, " ", name, "[]", NIL);
+ } else {
+ Printv(var_decl, type_str, " ", name, NIL);
+ }
+
+ Delete(type_str);
+
+ return var_decl;
+ }
+
+ /* ---------------------------------------------------------------------
+ * emit_c_struct_def()
+ *
+ * Append the declarations of C struct members to the given string.
+ * Notice that this function has a side effect of outputting all enum declarations inside the struct into sect_wrappers_types directly.
+ * This is done to avoid gcc warnings "declaration does not declare anything" given for the anonymous enums inside the structs.
+ * --------------------------------------------------------------------- */
+
+ void emit_c_struct_def(String* out, Node *n) {
+ for ( Node* node = firstChild(n); node; node = nextSibling(node)) {
+ String* const ntype = nodeType(node);
+ if (Cmp(ntype, "cdecl") == 0) {
+ SwigType* t = NewString(Getattr(node, "type"));
+ SwigType_push(t, Getattr(node, "decl"));
+ t = SwigType_typedef_resolve_all(t);
+ if (SwigType_isfunction(t)) {
+ Swig_warning(WARN_C_UNSUPPORTTED, input_file, line_number, "Extending C struct with %s is not currently supported, ignored.\n", SwigType_str(t, 0));
+ } else {
+ String* const var_decl = make_c_var_decl(node);
+ Printv(out, cindent, var_decl, ";\n", NIL);
+ Delete(var_decl);
+ }
+ } else if (Cmp(ntype, "enum") == 0) {
+ // This goes directly into sect_wrappers_types, before this struct declaration.
+ emit_one(node);
+ } else {
+ // WARNING: proxy declaration can be different than original code
+ if (Cmp(nodeType(node), "extend") == 0)
+ emit_c_struct_def(out, node);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * classDeclaration()
+ * --------------------------------------------------------------------- */
+
+ virtual int classDeclaration(Node *n) {
+ if (Cmp(Getattr(n, "name"), "SWIG_CException") == 0) {
+ // Ignore this class only if it was already wrapped in another module, imported from this one (if exceptions are disabled, we shouldn't be even parsing
+ // SWIG_CException in the first place and if they're enabled, we handle it normally).
+ if (exceptions_support_ == exceptions_support_imported)
+ return SWIG_NOWRAP;
+ }
+
+ return Language::classDeclaration(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * classHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ String* const name = get_c_proxy_name(n);
+
+ if (CPlusPlus) {
+ cxx_class_wrapper cxx_class_wrapper_obj(cxx_wrappers_, n);
+ temp_ptr_setter<cxx_class_wrapper*> set_cxx_class_wrapper(&cxx_class_wrapper_, &cxx_class_wrapper_obj);
+
+ // inheritance support: attach all members from base classes to this class
+ if (List *baselist = Getattr(n, "bases")) {
+ Iterator i;
+ for (i = First(baselist); i.item; i = Next(i)) {
+ // look for member variables and functions
+ Node *node;
+ for (node = firstChild(i.item); node; node = nextSibling(node)) {
+ if ((Cmp(Getattr(node, "kind"), "variable") == 0)
+ || (Cmp(Getattr(node, "kind"), "function") == 0)) {
+ if ((Cmp(Getattr(node, "access"), "public") == 0)
+ && (Cmp(Getattr(node, "storage"), "static") != 0)) {
+ // Assignment operators are not inherited in C++ and symbols without sym:name should be ignored, not copied into the derived class.
+ if (Getattr(node, "sym:name") && Cmp(Getattr(node, "name"), "operator =") != 0) {
+ String *parent_name = Getattr(parentNode(node), "name");
+ Hash *dupl_name_node = is_in(Getattr(node, "name"), n);
+ // if there's a duplicate inherited name, due to the C++ multiple
+ // inheritance, change both names to avoid ambiguity
+ if (dupl_name_node) {
+ String *cif = Getattr(dupl_name_node, "c:inherited_from");
+ String *old_name = Getattr(dupl_name_node, "sym:name");
+ if (cif && parent_name && (Cmp(cif, parent_name) != 0)) {
+ Setattr(dupl_name_node, "sym:name", NewStringf("%s%s", cif ? cif : "", old_name));
+ Setattr(dupl_name_node, "c:base_name", old_name);
+ Node *new_node = copy_node(node);
+ Setattr(new_node, "name", NewStringf("%s%s", parent_name, old_name));
+ Setattr(new_node, "c:base_name", old_name);
+ appendChild(n, new_node);
+ }
+ } else {
+ appendChild(n, copy_node(node));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // declare type for specific class in the proxy header
+ Printv(sect_wrappers_types, "typedef struct SwigObj_", name, " ", name, ";\n\n", NIL);
+
+ return Language::classHandler(n);
+ } else {
+ // this is C struct, just declare it in the proxy
+ String* struct_def = NewStringEmpty();
+ String* const tdname = Getattr(n, "tdname");
+ if (tdname)
+ Append(struct_def, "typedef struct {\n");
+ else
+ Printv(struct_def, "struct ", name, " {\n", NIL);
+ emit_c_struct_def(struct_def, n);
+ if (tdname)
+ Printv(struct_def, "} ", tdname, ";\n\n", NIL);
+ else
+ Append(struct_def, "};\n\n");
+
+ Printv(sect_wrappers_types, struct_def, NIL);
+ Delete(struct_def);
+ }
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ SwigType *type = Getattr(n, "type");
+ SwigType *tdtype = SwigType_typedef_resolve_all(type);
+ if (tdtype) {
+ type = tdtype;
+ Setattr(n, "type", type);
+ }
+ SwigType *btype = SwigType_base(type);
+ if (SwigType_isarray(type) && !SwigType_isbuiltin(btype)) {
+ // this hack applies to member objects array (not ptrs.)
+ SwigType_add_pointer(btype);
+ SwigType_add_array(btype, NewStringf("%s", SwigType_array_getdim(type, 0)));
+ Setattr(n, "type", btype);
+ }
+ Delete(type);
+ Delete(btype);
+ return Language::staticmembervariableHandler(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * membervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+ SwigType *type = Getattr(n, "type");
+ SwigType *tdtype = SwigType_typedef_resolve_all(type);
+ if (tdtype) {
+ type = tdtype;
+ Setattr(n, "type", type);
+ }
+ SwigType *btype = SwigType_base(type);
+ if (SwigType_isarray(type) && !SwigType_isbuiltin(btype)) {
+ // this hack applies to member objects array (not ptrs.)
+ SwigType_add_pointer(btype);
+ SwigType_add_array(btype, NewStringf("%s", SwigType_array_getdim(type, 0)));
+ Setattr(n, "type", btype);
+ }
+ Delete(type);
+ Delete(btype);
+ return Language::membervariableHandler(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * constructorHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int constructorHandler(Node *n) {
+ // For some reason, the base class implementation of constructorDeclaration() only takes care of the copy ctor automatically for the languages not
+ // supporting overloading (i.e. not calling allow_overloading(), as we do). So duplicate the relevant part of its code here,
+ if (!Abstract && Getattr(n, "copy_constructor")) {
+ return Language::copyconstructorHandler(n);
+ }
+
+ if (GetFlag(n, "feature:extend")) {
+ // Pretend that all ctors added via %extend are overloaded to avoid clash between the functions created for them and the actual exported function, that
+ // could have the same "Foo_new" name otherwise.
+ SetFlag(n, "sym:overloaded");
+ }
+
+ return Language::constructorHandler(n);
+ }
+
+ /* ----------------------------------------------------------------------
+ * Language::enumforwardDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumforwardDeclaration(Node *n) {
+ // Base implementation of this function calls enumDeclaration() for "missing" enums, i.e. those without any definition at all. This results in invalid (at
+ // least in C++) enum declarations in the output, so simply don't do this here.
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * enumDeclaration()
+ * --------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+ if (ImportMode)
+ return SWIG_OK;
+
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ // We don't know here if we're going to have any non-ignored enum elements, so generate enum declaration in a temporary string.
+ enum_decl = NewStringEmpty();
+
+ // Another string for C++ enum declaration, which differs from the C one because it never uses the prefix, as C++ enums are declared in the correct scope.
+ cxx_enum_decl = cxx_wrappers_.is_initialized() ? NewStringEmpty() : NULL;
+
+ // If we're currently generating a wrapper class, we need an extra level of indent.
+ if (cxx_enum_decl) {
+ if (cxx_class_wrapper_) {
+ cxx_enum_indent = cxx_class_wrapper_->get_indent();
+ Append(cxx_enum_decl, cxx_enum_indent);
+ } else {
+ cxx_enum_indent = "";
+ }
+ }
+
+ String* const symname = Getattr(n, "sym:name");
+
+ // Preserve the typedef if we have it in the input.
+ bool const is_typedef = Checkattr(n, "allows_typedef", "1");
+ if (is_typedef) {
+ Printv(enum_decl, "typedef ", NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, "typedef ", NIL);
+ }
+ Printv(enum_decl, "enum", NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, "enum", NIL);
+
+ String* enum_prefix;
+ if (Node* const klass = getCurrentClass()) {
+ enum_prefix = get_c_proxy_name(klass);
+ } else {
+ enum_prefix = ns_prefix; // Possibly NULL, but that's fine.
+ }
+
+ // C++ enum names don't use the prefix, as they're defined in namespace or class scope.
+ String* cxx_enum_prefix = NULL;
+
+ scoped_dohptr enumname;
+ scoped_dohptr cxx_enumname;
+
+ // Unnamed enums may just have no name at all or have a synthesized invalid name of the form "$unnamedN$ which is indicated by "unnamed" attribute.
+ if (String* const name = Getattr(n, "unnamed") ? NULL : symname) {
+ // If it's a typedef, its sym:name is the typedef name, but we don't want to use it here (we already use it for the typedef we generate), so use the
+ // actual C++ name instead.
+ if (is_typedef) {
+ // But the name may include the containing class, so get rid of it.
+ enumname = Swig_scopename_last(Getattr(n, "name"));
+ } else {
+ enumname = Copy(name);
+ }
+
+ const bool scoped_enum = Checkattr(n, "scopedenum", "1");
+
+ if (cxx_enum_decl) {
+ // In C++ we can use actual scoped enums instead of emulating them with element prefixes.
+ if (scoped_enum)
+ Printv(cxx_enum_decl, " class", NIL);
+
+ // And enum name itself shouldn't include the prefix neither, as this enum is either inside a namespace or inside a class, so use enumname before it
+ // gets updated below.
+ Printv(cxx_enum_decl, " ", enumname.get(), NIL);
+ }
+
+ if (enum_prefix) {
+ enumname = NewStringf("%s_%s", enum_prefix, enumname.get());
+ }
+
+ Printv(enum_decl, " ", enumname.get(), NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, " ", cxx_enumname.get(), NIL);
+
+ // For scoped enums, their name should be prefixed to their elements in addition to any other prefix we use.
+ if (scoped_enum) {
+ enum_prefix = enumname.get();
+ cxx_enum_prefix = cxx_enumname.get();
+ }
+ }
+
+ enum_prefix_ = enum_prefix ? NewStringf("%s_", enum_prefix) : NewStringEmpty();
+ cxx_enum_prefix_ = cxx_enum_prefix ? NewStringf("%s_", cxx_enum_prefix) : NewStringEmpty();
+
+ Printv(enum_decl, " {\n", NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, " {\n", NIL);
+
+ int const len_orig = Len(enum_decl);
+
+ // Emit each enum item.
+ Language::enumDeclaration(n);
+
+ // Only emit the enum declaration if there were actually any items.
+ if (Len(enum_decl) > len_orig) {
+ Printv(enum_decl, "\n}", NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, "\n", cxx_enum_indent, "}", NIL);
+
+ if (is_typedef) {
+ Printv(enum_decl, " ", enum_prefix_.get(), symname, NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, " ", symname, NIL);
+ }
+ Printv(enum_decl, ";\n\n", NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, ";\n\n", NIL);
+
+ Append(sect_wrappers_types, enum_decl);
+ if (cxx_enum_decl) {
+ // Enums declared in global scopes can be just defined before everything else, but nested enums have to be defined inside the declaration of the class,
+ // which we must be in process of creating, so output them in the appropriate section.
+ Append(cxx_class_wrapper_ ? cxx_wrappers_.sect_decls : cxx_wrappers_.sect_types, cxx_enum_decl);
+ }
+ }
+
+ Delete(enum_decl);
+ if (cxx_enum_decl)
+ Delete(cxx_enum_decl);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * --------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (Cmp(Getattr(n, "ismember"), "1") == 0 && Cmp(Getattr(n, "access"), "public") != 0)
+ return SWIG_NOWRAP;
+ Swig_require("enumvalueDeclaration", n, "?enumvalueex", "?enumvalue", NIL);
+
+ if (!GetFlag(n, "firstenumitem")) {
+ Printv(enum_decl, ",\n", NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, ",\n", NIL);
+ }
+
+ String* const symname = Getattr(n, "sym:name");
+ Printv(enum_decl, cindent, enum_prefix_.get(), symname, NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, cxx_enum_indent, cindent, cxx_enum_prefix_.get(), symname, NIL);
+
+ // We only use "enumvalue", which comes from the input, and not "enumvalueex" synthesized by SWIG itself because C should use the correct value for the enum
+ // items without an explicit one anyhow (and "enumvalueex" can't be always used as is in C code for enum elements inside a class or even a namespace).
+ String *value = Getattr(n, "enumvalue");
+ if (value) {
+ // We can't always use the raw value, check its type to see if we need to transform it.
+ maybe_owned_dohptr cvalue;
+ switch (SwigType_type(Getattr(n, "type"))) {
+ case T_BOOL:
+ // Boolean constants can't appear in C code, so replace them with their values in the simplest possible case. This is not exhaustive, of course,
+ // but better than nothing and doing the right thing is not simple at all as we'd need to really parse the expression, just textual substitution wouldn't
+ // be enough (consider e.g. an enum element called "very_true" and another one using it as its value).
+ if (Cmp(value, "true") == 0) {
+ cvalue.assign_owned(NewString("1"));
+ } else if (Cmp(value, "false") == 0) {
+ cvalue.assign_owned(NewString("0"));
+ } else {
+ Swig_error(Getfile(n), Getline(n), "Unsupported boolean enum value \"%s\".\n", value);
+ }
+ break;
+ default:
+ cvalue.assign_non_owned(value);
+ }
+
+ Printv(enum_decl, " = ", cvalue.get(), NIL);
+ if (cxx_enum_decl)
+ Printv(cxx_enum_decl, " = ", cvalue.get(), NIL);
+ }
+
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * constantWrapper()
+ * --------------------------------------------------------------------- */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ // We use the "value" and hope that it will work in C as well as in C++.
+ String *value = Getattr(n, "value");
+ Printv(sect_wrappers_decl, "#define ", name, " ", value, "\n", NIL);
+ return SWIG_OK;
+ }
+}; /* class C */
+
+/* -----------------------------------------------------------------------------
+ * swig_c() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_c() {
+ return new C();
+}
+
+extern "C" Language *swig_c(void) {
+ return new_swig_c();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+const char *C::usage = (char *) "\
+C Options (available with -c)\n\
+ -namespace ns - use prefix based on the provided namespace\n\
+ -nocxx - do not generate C++ wrappers\n\
+ -noexcept - do not generate exception handling code\n\
+\n";
+
diff --git a/contrib/tools/swig/Source/Modules/contract.cxx b/contrib/tools/swig/Source/Modules/contract.cxx
new file mode 100644
index 00000000000..5091bebdef0
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/contract.cxx
@@ -0,0 +1,358 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * contract.cxx
+ *
+ * Support for Wrap by Contract in SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+/* Contract structure. This holds rules about the different kinds of contract sections
+ and their combination rules */
+
+struct contract {
+ const char *section;
+ const char *combiner;
+};
+/* Contract rules. This table defines what contract sections are recognized as well as
+ how contracts are to combined via inheritance */
+
+static contract Rules[] = {
+ {"require:", "&&"},
+ {"ensure:", "||"},
+ {NULL, NULL}
+};
+
+/* ----------------------------------------------------------------------------
+ * class Contracts:
+ *
+ * This class defines the functions that need to be used in
+ * "wrap by contract" module.
+ * ------------------------------------------------------------------------- */
+
+class Contracts:public Dispatcher {
+ String *make_expression(String *s, Node *n);
+ void substitute_parms(String *s, ParmList *p, int method);
+public:
+ Hash *ContractSplit(Node *n);
+ int emit_contract(Node *n, int method);
+ int cDeclaration(Node *n);
+ int constructorDeclaration(Node *n);
+ int externDeclaration(Node *n);
+ int extendDirective(Node *n);
+ int importDirective(Node *n);
+ int includeDirective(Node *n);
+ int namespaceDeclaration(Node *n);
+ int classDeclaration(Node *n);
+ virtual int top(Node *n);
+};
+
+static int Contract_Mode = 0; /* contract option */
+static int InClass = 0; /* Parsing C++ or not */
+static int InConstructor = 0;
+static Node *CurrentClass = 0;
+
+/* Set the contract mode, default is 0 (not open) */
+/* Normally set in main.cxx, when get the "-contracts" option */
+void Swig_contract_mode_set(int flag) {
+ Contract_Mode = flag;
+}
+
+/* Get the contract mode */
+int Swig_contract_mode_get() {
+ return Contract_Mode;
+}
+
+/* Apply contracts */
+void Swig_contracts(Node *n) {
+
+ Contracts *a = new Contracts;
+ a->top(n);
+ delete a;
+}
+
+/* Split the whole contract into preassertion, postassertion and others */
+Hash *Contracts::ContractSplit(Node *n) {
+
+ String *contract = Getattr(n, "feature:contract");
+ Hash *result;
+ if (!contract)
+ return NULL;
+
+ result = NewHash();
+ String *current_section = NewString("");
+ const char *current_section_name = Rules[0].section;
+ List *l = SplitLines(contract);
+
+ Iterator i;
+ for (i = First(l); i.item; i = Next(i)) {
+ int found = 0;
+ if (Strchr(i.item, '{'))
+ continue;
+ if (Strchr(i.item, '}'))
+ continue;
+ for (int j = 0; Rules[j].section; j++) {
+ if (Strstr(i.item, Rules[j].section)) {
+ if (Len(current_section)) {
+ Setattr(result, current_section_name, current_section);
+ current_section = Getattr(result, Rules[j].section);
+ if (!current_section)
+ current_section = NewString("");
+ }
+ current_section_name = Rules[j].section;
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ Append(current_section, i.item);
+ }
+ if (Len(current_section))
+ Setattr(result, current_section_name, current_section);
+ return result;
+}
+
+/* This function looks in base classes and collects contracts found */
+static void inherit_contracts(Node *c, Node *n, Hash *contracts, Hash *messages) {
+
+ Node *b, *temp;
+ String *name, *type, *local_decl, *base_decl;
+ List *bases;
+ int found = 0;
+
+ bases = Getattr(c, "bases");
+ if (!bases)
+ return;
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+ local_decl = Getattr(n, "decl");
+ if (local_decl) {
+ local_decl = SwigType_typedef_resolve_all(local_decl);
+ } else {
+ return;
+ }
+ /* Width first search */
+ for (int i = 0; i < Len(bases); i++) {
+ b = Getitem(bases, i);
+ temp = firstChild(b);
+ while (temp) {
+ base_decl = Getattr(temp, "decl");
+ if (base_decl) {
+ base_decl = SwigType_typedef_resolve_all(base_decl);
+ if ((checkAttribute(temp, "storage", "virtual")) &&
+ (checkAttribute(temp, "name", name)) && (checkAttribute(temp, "type", type)) && (!Strcmp(local_decl, base_decl))) {
+ /* Yes, match found. */
+ Hash *icontracts = Getattr(temp, "contract:rules");
+ Hash *imessages = Getattr(temp, "contract:messages");
+ found = 1;
+ if (icontracts && imessages) {
+ /* Add inherited contracts and messages to the contract rules above */
+ int j = 0;
+ for (j = 0; Rules[j].section; j++) {
+ String *t = Getattr(contracts, Rules[j].section);
+ String *s = Getattr(icontracts, Rules[j].section);
+ if (s) {
+ if (t) {
+ Insert(t, 0, "(");
+ Printf(t, ") %s (%s)", Rules[j].combiner, s);
+ String *m = Getattr(messages, Rules[j].section);
+ Printf(m, " %s [%s from %s]", Rules[j].combiner, Getattr(imessages, Rules[j].section), Getattr(b, "name"));
+ } else {
+ Setattr(contracts, Rules[j].section, NewString(s));
+ Setattr(messages, Rules[j].section, NewStringf("[%s from %s]", Getattr(imessages, Rules[j].section), Getattr(b, "name")));
+ }
+ }
+ }
+ }
+ }
+ Delete(base_decl);
+ }
+ temp = nextSibling(temp);
+ }
+ }
+ Delete(local_decl);
+ if (!found) {
+ for (int j = 0; j < Len(bases); j++) {
+ b = Getitem(bases, j);
+ inherit_contracts(b, n, contracts, messages);
+ }
+ }
+}
+
+/* This function cleans up the assertion string by removing some extraneous characters.
+ Splitting the assertion into pieces */
+
+String *Contracts::make_expression(String *s, Node *n) {
+ String *str_assert, *expr = 0;
+ List *list_assert;
+
+ str_assert = NewString(s);
+ /* Omit all useless characters and split by ; */
+ Replaceall(str_assert, "\n", "");
+ Replaceall(str_assert, "{", "");
+ Replaceall(str_assert, "}", "");
+ Replace(str_assert, " ", "", DOH_REPLACE_ANY | DOH_REPLACE_NOQUOTE);
+ Replace(str_assert, "\t", "", DOH_REPLACE_ANY | DOH_REPLACE_NOQUOTE);
+
+ list_assert = Split(str_assert, ';', -1);
+ Delete(str_assert);
+
+ /* build up new assertion */
+ str_assert = NewString("");
+ Iterator ei;
+
+ for (ei = First(list_assert); ei.item; ei = Next(ei)) {
+ expr = ei.item;
+ if (Len(expr)) {
+ Replaceid(expr, Getattr(n, "name"), Swig_cresult_name());
+ if (Len(str_assert))
+ Append(str_assert, "&&");
+ Printf(str_assert, "(%s)", expr);
+ }
+ }
+ Delete(list_assert);
+ return str_assert;
+}
+
+/* This function substitutes parameter names for argument names in the
+ contract specification. Note: it is assumed that the wrapper code
+ uses arg1 for self and arg2..argn for arguments. */
+
+void Contracts::substitute_parms(String *s, ParmList *p, int method) {
+ int argnum = 1;
+ char argname[32];
+
+ if (method) {
+ Replaceid(s, "$self", "arg1");
+ argnum++;
+ }
+ while (p) {
+ sprintf(argname, "arg%d", argnum);
+ String *name = Getattr(p, "name");
+ if (name) {
+ Replaceid(s, name, argname);
+ }
+ argnum++;
+ p = nextSibling(p);
+ }
+}
+
+int Contracts::emit_contract(Node *n, int method) {
+ Hash *contracts;
+ Hash *messages;
+ String *c;
+
+ ParmList *cparms;
+
+ if (!Getattr(n, "feature:contract"))
+ return SWIG_ERROR;
+
+ /* Get contract parameters */
+ cparms = Getmeta(Getattr(n, "feature:contract"), "parms");
+
+ /* Split contract into preassert & postassert */
+ contracts = ContractSplit(n);
+ if (!contracts)
+ return SWIG_ERROR;
+
+ /* This messages hash is used to hold the error messages that will be displayed on
+ failed contract. */
+
+ messages = NewHash();
+
+ /* Take the different contract expressions and clean them up a bit */
+ Iterator i;
+ for (i = First(contracts); i.item; i = Next(i)) {
+ String *e = make_expression(i.item, n);
+ substitute_parms(e, cparms, method);
+ Setattr(contracts, i.key, e);
+
+ /* Make a string containing error messages */
+ Setattr(messages, i.key, NewString(e));
+ }
+
+ /* If we're in a class. We need to inherit other assertions. */
+ if (InClass) {
+ inherit_contracts(CurrentClass, n, contracts, messages);
+ }
+
+ /* Save information */
+ Setattr(n, "contract:rules", contracts);
+ Setattr(n, "contract:messages", messages);
+
+ /* Okay. Generate the contract runtime code. */
+
+ if ((c = Getattr(contracts, "require:"))) {
+ Setattr(n, "contract:preassert", NewStringf("SWIG_contract_assert(%s, \"Contract violation: require: %s\");\n", c, Getattr(messages, "require:")));
+ }
+ if ((c = Getattr(contracts, "ensure:"))) {
+ Setattr(n, "contract:postassert", NewStringf("SWIG_contract_assert(%s, \"Contract violation: ensure: %s\");\n", c, Getattr(messages, "ensure:")));
+ }
+ return SWIG_OK;
+}
+
+int Contracts::cDeclaration(Node *n) {
+ int ret = SWIG_OK;
+ String *decl = Getattr(n, "decl");
+
+ /* Not a function. Don't even bother with it (for now) */
+ if (!SwigType_isfunction(decl))
+ return SWIG_OK;
+
+ if (Getattr(n, "feature:contract"))
+ ret = emit_contract(n, InClass && !Swig_storage_isstatic(n));
+ return ret;
+}
+
+int Contracts::constructorDeclaration(Node *n) {
+ int ret = SWIG_OK;
+ InConstructor = 1;
+ if (Getattr(n, "feature:contract"))
+ ret = emit_contract(n, 0);
+ InConstructor = 0;
+ return ret;
+}
+
+int Contracts::externDeclaration(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::extendDirective(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::importDirective(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::includeDirective(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::namespaceDeclaration(Node *n) {
+ return emit_children(n);
+}
+
+int Contracts::classDeclaration(Node *n) {
+ int ret = SWIG_OK;
+ int oldInClass = InClass;
+ Node *oldClass = CurrentClass;
+ InClass = 1;
+ CurrentClass = n;
+ emit_children(n);
+ InClass = oldInClass;
+ CurrentClass = oldClass;
+ return ret;
+}
+
+int Contracts::top(Node *n) {
+ emit_children(n);
+ return SWIG_OK;
+}
diff --git a/contrib/tools/swig/Source/Modules/csharp.cxx b/contrib/tools/swig/Source/Modules/csharp.cxx
new file mode 100644
index 00000000000..09031b321d5
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/csharp.cxx
@@ -0,0 +1,4912 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * csharp.cxx
+ *
+ * C# language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <limits.h> // for INT_MAX
+#include <ctype.h>
+#include <csharpdoc.h>
+
+/* Hash type used for upcalls from C/C++ */
+typedef DOH UpcallData;
+
+class CSHARP:public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *protected_string;
+
+ Hash *swig_types_hash;
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ File *f_single_out;
+ List *filenames_list;
+
+ bool proxy_flag; // Flag for generating proxy classes
+ bool native_function_flag; // Flag for when wrapping a native function
+ bool enum_constant_flag; // Flag for when wrapping an enum or constant
+ bool static_flag; // Flag for when wrapping a static functions or member variables
+ bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
+ bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
+ bool global_variable_flag; // Flag for when wrapping a global variable
+ bool old_variable_names; // Flag for old style variable names in the intermediary class
+ bool generate_property_declaration_flag; // Flag for generating properties
+ bool doxygen; // Flag for Doxygen generation
+
+ String *imclass_name; // intermediary class name
+ String *module_class_name; // module class name
+ String *imclass_class_code; // intermediary class code
+ String *proxy_class_def;
+ String *proxy_class_code;
+ String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
+ String *module_class_code;
+ String *proxy_class_name; // 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;
+ String *module_class_constants_code;
+ String *common_begin_code;
+ String *enum_code;
+ String *dllimport; // DllImport attribute name
+ String *namespce; // Optional namespace name
+ String *imclass_imports; //intermediary class imports from %pragma
+ String *module_imports; //module imports from %pragma
+ String *imclass_baseclass; //inheritance for intermediary class class from %pragma
+ String *module_baseclass; //inheritance for module class from %pragma
+ String *imclass_interfaces; //interfaces for intermediary class class from %pragma
+ String *module_interfaces; //interfaces for module class from %pragma
+ String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
+ String *module_class_modifiers; //class modifiers for module class overridden by %pragma
+ String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
+ String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
+ String *director_callback_typedefs; // Director function pointer typedefs for callbacks
+ String *director_callbacks; // Director callback function pointer member variables
+ String *director_delegate_callback; // Director callback method that delegates are set to call
+ String *director_delegate_definitions; // Director delegates definitions in proxy class
+ String *director_delegate_instances; // Director delegates member variables in proxy class
+ String *director_method_types; // Director method types
+ String *director_connect_parms; // Director delegates parameter list for director connect call
+ String *destructor_call; //C++ destructor call if any
+ String *output_file; // File name for single file mode. If set all generated code will be written to this file
+
+ // Director method stuff:
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int n_directors;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+ int nesting_depth;
+
+ enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
+
+public:
+
+ /* -----------------------------------------------------------------------------
+ * CSHARP()
+ * ----------------------------------------------------------------------------- */
+
+ CSHARP():empty_string(NewString("")),
+ public_string(NewString("public")),
+ protected_string(NewString("protected")),
+ swig_types_hash(NULL),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ f_single_out(NULL),
+ filenames_list(NULL),
+ proxy_flag(true),
+ native_function_flag(false),
+ enum_constant_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ old_variable_names(false),
+ generate_property_declaration_flag(false),
+ doxygen(false),
+ imclass_name(NULL),
+ module_class_name(NULL),
+ imclass_class_code(NULL),
+ proxy_class_def(NULL),
+ proxy_class_code(NULL),
+ interface_class_code(NULL),
+ module_class_code(NULL),
+ proxy_class_name(NULL),
+ full_imclass_name(NULL),
+ variable_name(NULL),
+ proxy_class_constants_code(NULL),
+ module_class_constants_code(NULL),
+ common_begin_code(NULL),
+ enum_code(NULL),
+ dllimport(NULL),
+ namespce(NULL),
+ imclass_imports(NULL),
+ module_imports(NULL),
+ imclass_baseclass(NULL),
+ module_baseclass(NULL),
+ imclass_interfaces(NULL),
+ module_interfaces(NULL),
+ imclass_class_modifiers(NULL),
+ module_class_modifiers(NULL),
+ upcasts_code(NULL),
+ imclass_cppcasts_code(NULL),
+ director_callback_typedefs(NULL),
+ director_callbacks(NULL),
+ director_delegate_callback(NULL),
+ director_delegate_definitions(NULL),
+ director_delegate_instances(NULL),
+ director_method_types(NULL),
+ director_connect_parms(NULL),
+ destructor_call(NULL),
+ output_file(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ n_directors(0),
+ first_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;
+ directorLanguage();
+ }
+
+ /* -----------------------------------------------------------------------------
+ * ~CSHARP()
+ * ----------------------------------------------------------------------------- */
+
+ ~CSHARP() {
+ delete doxygenTranslator;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getProxyName()
+ *
+ * Test to see if a type corresponds to something wrapped with a proxy class.
+ * Return NULL if not otherwise the proxy class name, fully qualified with
+ * a namespace if the nspace feature is used.
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t) {
+ String *proxyname = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ proxyname = Getattr(n, "proxyname");
+ if (!proxyname) {
+ String *nspace = Getattr(n, "sym:nspace");
+ 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")) {
+ if (String* name = Getattr(outer_class, "sym:name")) {
+ Push(symname, ".");
+ Push(symname, name);
+ }
+ else
+ return NULL;
+ }
+ }
+ if (nspace) {
+ if (namespce)
+ proxyname = NewStringf("%s.%s.%s", namespce, nspace, symname);
+ else
+ proxyname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ proxyname = Copy(symname);
+ }
+ Setattr(n, "proxyname", proxyname);
+ Delete(proxyname);
+ Delete(symname);
+ }
+ }
+ }
+ return proxyname;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("csharp");
+
+ int doxygen_translator_flags = 0;
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-dllimport") == 0) {
+ if (argv[i + 1]) {
+ dllimport = NewString("");
+ Printf(dllimport, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-namespace") == 0) {
+ if (argv[i + 1]) {
+ namespce = NewString("");
+ Printf(namespce, argv[i + 1]);
+ if (Len(namespce) == 0) {
+ Delete(namespce);
+ namespce = 0;
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ Swig_mark_arg(i);
+ proxy_flag = false;
+ } else if (strcmp(argv[i], "-oldvarnames") == 0) {
+ Swig_mark_arg(i);
+ old_variable_names = true;
+ } else if (strcmp(argv[i], "-outfile") == 0) {
+ if (argv[i + 1]) {
+ output_file = NewString("");
+ Printf(output_file, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-doxygen") == 0) {
+ doxygen = true;
+ scan_doxygen_comments = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-doxygen-translator") == 0) {
+ doxygen_translator_flags |= DoxygenTranslator::debug_translator;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-doxygen-parser") == 0) {
+ doxygen_translator_flags |= DoxygenTranslator::debug_parser;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ if (doxygen)
+ doxygenTranslator = new CSharpDocConverter(doxygen_translator_flags);
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGCSHARP 1", 0);
+
+ SWIG_config_file("csharp.swg");
+
+ allow_overloading();
+ Swig_interface_feature_enable();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+
+ // Get any options set in the module directive
+ Node *module = Getattr(n, "module");
+ Node *optionsnode = Getattr(module, "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "imclassname"))
+ imclass_name = Copy(Getattr(optionsnode, "imclassname"));
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ common_begin_code = Getattr(optionsnode, "csbegin");
+ if (common_begin_code)
+ Printf(common_begin_code, "\n");
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (Swig_directors_enabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ swig_types_hash = NewHash();
+ filenames_list = NewList();
+
+ // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
+ if (!imclass_name) {
+ imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
+ module_class_name = Copy(Getattr(n, "name"));
+ } else {
+ // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
+ if (Cmp(imclass_name, Getattr(n, "name")) == 0)
+ module_class_name = NewStringf("%sModule", Getattr(n, "name"));
+ else
+ module_class_name = Copy(Getattr(n, "name"));
+ }
+
+ // module class and intermediary classes are always created
+ if (!addSymbol(imclass_name, module))
+ return SWIG_ERROR;
+ if (!addSymbol(module_class_name, module))
+ return SWIG_ERROR;
+
+ imclass_class_code = NewString("");
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ module_class_constants_code = NewString("");
+ imclass_baseclass = NewString("");
+ imclass_interfaces = NewString("");
+ imclass_class_modifiers = NewString("");
+ module_class_code = NewString("");
+ module_baseclass = NewString("");
+ module_interfaces = NewString("");
+ module_imports = NewString("");
+ module_class_modifiers = NewString("");
+ imclass_imports = NewString("");
+ imclass_cppcasts_code = NewString("");
+ director_connect_parms = NewString("");
+ upcasts_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+ n_directors = 0;
+ if (!dllimport)
+ dllimport = Copy(module_class_name);
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "CSHARP");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ Printf(f_runtime, "\n");
+ if (namespce) {
+ String *wrapper_name = NewStringf("");
+ Printf(wrapper_name, "CSharp_%s_%%f", namespce);
+ Swig_name_register("wrapper", wrapper_name);
+ Delete(wrapper_name);
+ }
+ else {
+ Swig_name_register("wrapper", "CSharp_%f");
+ }
+
+ if (old_variable_names) {
+ Swig_name_register("set", "set_%n%v");
+ Swig_name_register("get", "get_%n%v");
+ }
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ /* Emit code */
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+ // Generate the intermediary class
+ {
+ File *f_im = getOutputFile(SWIG_output_directory(), imclass_name);
+
+ addOpenNamespace(0, f_im);
+
+ if (imclass_imports)
+ Printf(f_im, "%s\n", imclass_imports);
+
+ if (Len(imclass_class_modifiers) > 0)
+ Printf(f_im, "%s ", imclass_class_modifiers);
+ Printf(f_im, "%s ", imclass_name);
+
+ if (imclass_baseclass && *Char(imclass_baseclass))
+ Printf(f_im, ": %s ", imclass_baseclass);
+ if (Len(imclass_interfaces) > 0)
+ Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
+ Printf(f_im, "{\n");
+
+ // Add the intermediary class methods
+ Replaceall(imclass_class_code, "$module", module_class_name);
+ Replaceall(imclass_class_code, "$imclassname", imclass_name);
+ Replaceall(imclass_class_code, "$dllimport", dllimport);
+ Printv(f_im, imclass_class_code, NIL);
+ Printv(f_im, imclass_cppcasts_code, NIL);
+
+ // Finish off the class
+ Printf(f_im, "}\n");
+ addCloseNamespace(0, f_im);
+
+ if (f_im != f_single_out)
+ Delete(f_im);
+ f_im = NULL;
+ }
+
+ // Generate the C# module class
+ {
+ File *f_module = getOutputFile(SWIG_output_directory(), module_class_name);
+
+ addOpenNamespace(0, f_module);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ if (Len(module_class_modifiers) > 0)
+ Printf(f_module, "%s ", module_class_modifiers);
+ Printf(f_module, "%s ", module_class_name);
+
+ if (module_baseclass && *Char(module_baseclass))
+ Printf(f_module, ": %s ", module_baseclass);
+ if (Len(module_interfaces) > 0)
+ Printv(f_module, "implements ", module_interfaces, " ", NIL);
+ Printf(f_module, "{\n");
+
+ Replaceall(module_class_code, "$module", module_class_name);
+ Replaceall(module_class_constants_code, "$module", module_class_name);
+
+ Replaceall(module_class_code, "$imclassname", imclass_name);
+ Replaceall(module_class_constants_code, "$imclassname", imclass_name);
+
+ Replaceall(module_class_code, "$dllimport", dllimport);
+ Replaceall(module_class_constants_code, "$dllimport", dllimport);
+
+ // Add the wrapper methods
+ Printv(f_module, module_class_code, NIL);
+
+ // Write out all the global constants
+ Printv(f_module, module_class_constants_code, NIL);
+
+ // Finish off the class
+ Printf(f_module, "}\n");
+ addCloseNamespace(0, f_module);
+
+ if (f_module != f_single_out)
+ Delete(f_module);
+ f_module = NULL;
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Output a C# type wrapper class for each SWIG type
+ for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
+ emitTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(swig_types_hash);
+ swig_types_hash = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(imclass_name);
+ imclass_name = NULL;
+ Delete(imclass_class_code);
+ imclass_class_code = NULL;
+ Delete(proxy_class_def);
+ proxy_class_def = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(module_class_constants_code);
+ module_class_constants_code = NULL;
+ Delete(imclass_baseclass);
+ imclass_baseclass = NULL;
+ Delete(imclass_interfaces);
+ imclass_interfaces = NULL;
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = NULL;
+ Delete(module_class_name);
+ module_class_name = NULL;
+ Delete(module_class_code);
+ module_class_code = NULL;
+ Delete(module_baseclass);
+ module_baseclass = NULL;
+ Delete(module_interfaces);
+ module_interfaces = NULL;
+ Delete(module_imports);
+ module_imports = NULL;
+ Delete(module_class_modifiers);
+ module_class_modifiers = NULL;
+ Delete(imclass_imports);
+ imclass_imports = NULL;
+ Delete(imclass_cppcasts_code);
+ imclass_cppcasts_code = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ Delete(namespce);
+ namespce = NULL;
+ n_dmethods = 0;
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ if (f_single_out) {
+ Dump(f_single_out, f_begin);
+ Delete(f_single_out);
+ f_single_out = NULL;
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitBanner()
+ * ----------------------------------------------------------------------------- */
+
+ void emitBanner(File *f) {
+ Printf(f, "//------------------------------------------------------------------------------\n");
+ Printf(f, "// <auto-generated />\n");
+ Printf(f, "//\n");
+ Swig_banner_target_lang(f, "//");
+ Printf(f, "//------------------------------------------------------------------------------\n\n");
+ Printv(f, common_begin_code, NIL);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getOutputFile()
+ *
+ * Prepares a File object by creating the file in the file system and
+ * writing the banner for auto-generated files to it (emitBanner).
+ * If '-outfile' is provided (single file mode) the supplied parameters will
+ * be ignored and the returned file will always be:
+ * <outdir>/<outfile>
+ * Otherwise the file will be:
+ * <dir>/<name>.cs
+ * ----------------------------------------------------------------------------- */
+
+ File *getOutputFile(const String *dir, const String *name) {
+ if (output_file) {
+ if (!f_single_out) {
+ String *filen = NewStringf("%s%s", SWIG_output_directory(), output_file);
+ f_single_out = NewFile(filen, "w", SWIG_output_files());
+ if (!f_single_out) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(f_single_out);
+ }
+ return f_single_out;
+ } else {
+ String *filen = NewStringf("%s%s.cs", dir, name);
+ File *f = NewFile(filen, "w", SWIG_output_files());
+ if (!f) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(f);
+ return f;
+ }
+ }
+
+ /*-----------------------------------------------------------------------
+ * Add new director upcall signature
+ *----------------------------------------------------------------------*/
+
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ Hash *new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+ Setattr(new_udata, "overname", Copy(overloaded_name));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Get director upcall signature
+ *----------------------------------------------------------------------*/
+
+ /*
+ UpcallData * getUpcallMethodData(String *director_class, String *decl) {
+ String *key = NewStringf("%s|%s", director_class, decl);
+ UpcallData *udata = Getattr(dmethods_table, key);
+
+ Delete(key);
+ return udata;
+ }
+ */
+
+ /* ----------------------------------------------------------------------
+ * nativeWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n, imclass_name))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ String *im_outattributes = 0;
+ int num_arguments = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(symname, n, imclass_name))
+ return SWIG_ERROR;
+ }
+
+ /*
+ The rest of this function deals with generating the intermediary class wrapper function (that wraps
+ a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
+ matching PInvoke c function call.
+ */
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *wname = Swig_name_wrapper(overloaded_name);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("ctype", l, f);
+ Swig_typemap_attach_parms("imtype", l, f);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
+ String *ctypeout = Getattr(n, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
+ if (ctypeout)
+ tm = ctypeout;
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ Printf(im_return_type, "%s", tm);
+ im_outattributes = Getattr(n, "tmap:imtype:outattributes");
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ is_void_return = Cmp(c_return_type, "void") == 0;
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
+
+ Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore")) {
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+
+ Printv(imclass_class_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
+
+ if (im_outattributes)
+ Printf(imclass_class_code, " %s\n", im_outattributes);
+
+ Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
+
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ int gencomma = 0;
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the ctype types of the parameter */
+ if ((tm = Getattr(p, "tmap:ctype"))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = Getattr(p, "tmap:imtype"))) {
+ const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
+ Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(imclass_class_code, ", ");
+ Printf(imclass_class_code, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
+
+ gencomma = 1;
+
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ canThrow(n, "in", p);
+ Replaceall(tm, "$arg", arg); /* deprecated? */
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->code, "%s\n", tm);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ }
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ canThrow(n, "check", p);
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ canThrow(n, "freearg", p);
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ canThrow(n, "argout", p);
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Look for usage of throws typemap and the canthrow flag
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ canThrow(n, "throws", p);
+ }
+ }
+ }
+
+ String *null_attribute = 0;
+ // Now write code to make the function call
+ if (!native_function_flag) {
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ canThrow(n, "out", n);
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ null_attribute = Getattr(n, "tmap:out:null");
+ if (Len(tm))
+ Printf(f->code, "\n");
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, returntype, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "newfree", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "ret", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* Finish C function and intermediary class function definitions */
+ Printf(imclass_class_code, ")");
+ Printf(imclass_class_code, ";\n");
+
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ Replaceall(f->code, "$isvoid", is_void_return ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
+ Setattr(n, "csharp:canthrow", "1");
+ }
+
+ if (!null_attribute)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", null_attribute);
+
+ /* Dump the function out */
+ if (!native_function_flag) {
+ Wrapper_print(f, f_wrappers);
+
+ // Handle %csexception which sets the canthrow attribute
+ if (Getattr(n, "feature:except:canthrow"))
+ Setattr(n, "csharp:canthrow", "1");
+
+ // A very simple check (it is not foolproof) to help typemap/feature writers for
+ // throwing C# exceptions from unmanaged code. It checks for the common methods which
+ // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
+ // so that code which checks for pending exceptions is added in the C# proxy method.
+ if (!Getattr(n, "csharp:canthrow")) {
+ if (Strstr(f->code, "SWIG_exception")) {
+ Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
+ "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
+ } else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
+ Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
+ "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
+ }
+ }
+ }
+
+ if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
+ moduleClassFunctionHandler(n);
+ }
+
+ /*
+ * Generate the proxy class properties for public member variables.
+ * Not for enums and constants.
+ */
+ 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, getClassPrefix(), variable_name))) != 0;
+
+ String *getter_setter_name = NewString("");
+ if (!getter_flag)
+ Printf(getter_setter_name, "set");
+ else
+ Printf(getter_setter_name, "get");
+ Putc(toupper((int) *Char(variable_name)), getter_setter_name);
+ Printf(getter_setter_name, "%s", Char(variable_name) + 1);
+
+ Setattr(n, "proxyfuncname", getter_setter_name);
+ Setattr(n, "imfuncname", symname);
+
+ proxyClassFunctionHandler(n);
+ Delete(getter_setter_name);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ Language::variableWrapper(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------------------ */
+
+ virtual int globalvariableHandler(Node *n) {
+
+ generate_property_declaration_flag = true;
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+ generate_property_declaration_flag = false;
+
+ if (proxy_flag) {
+ Printf(module_class_code, "\n }\n\n");
+ }
+
+ return ret;
+ }
+
+ String *getCurrentScopeName(String *nspace) {
+ String *scope = 0;
+ if (nspace || getCurrentClass()) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s", nspace);
+ if (Node *cls = getCurrentClass()) {
+ if (Node *outer = Getattr(cls, "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"));
+ }
+ Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
+ Delete(outerClassesPrefix);
+ } else
+ Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
+ }
+ }
+ return scope;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumDeclaration()
+ *
+ * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
+ * 1) Simple enums - simple constant within the proxy class or module class
+ * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
+ * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
+ * 4) Proper enums - proper C# enum
+ * Anonymous enums always default to 1)
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+ enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
+ EnumFeature enum_feature = decodeEnumFeature(n);
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab0);
+ Printv(enum_code, ds, NIL);
+ Delete(ds);
+ }
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
+
+ String *scope = getCurrentScopeName(nspace);
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ // Enum base (underlying enum type)
+ Node *attributes = NewHash();
+ const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
+ Delete(attributes);
+
+ String *baseclass = NULL;
+ if (!purebase_replace) {
+ String *underlying_enum_type = Getattr(n, "enumbase");
+ if (underlying_enum_type) {
+ const String *typemap_baseclass = typemapLookup(n, "cstype", underlying_enum_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF);
+ baseclass = Copy(typemap_baseclass);
+ substituteClassname(underlying_enum_type, baseclass);
+ }
+ }
+
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, enum base %s ignored. Multiple enum bases is not supported in C# enums. "
+ "Perhaps you need the 'replace' attribute in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Class attributes
+ const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
+ if (csattributes && *Char(csattributes))
+ Printf(enum_code, "%s\n", csattributes);
+
+ // Emit the enum
+ Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
+ " ", symname, *Char(wanted_base) ? " : " : "", wanted_base, " {\n", NIL);
+ Delete(scope);
+ } else {
+ // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
+ if (symname && !Getattr(n, "unnamedinstance"))
+ Printf(constants_code, " // %s \n", symname);
+ }
+
+ if (proxy_flag && !is_wrapping_class()) {
+ // Global enums / enums in a namespace
+ assert(!full_imclass_name);
+
+ if (!nspace) {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ } else {
+ if (namespce) {
+ full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
+ } else {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ }
+ }
+ }
+
+ // Emit each enum item
+ Language::enumDeclaration(n);
+
+ if (proxy_flag && !is_wrapping_class()) {
+ Delete(full_imclass_name);
+ full_imclass_name = 0;
+ }
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
+ // Finish the enum declaration
+ // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
+ Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
+ typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
+ "}", NIL);
+
+ Replaceall(enum_code, "$csclassname", symname);
+
+ // Substitute $enumvalues - intended usage is for typesafe enums
+ if (Getattr(n, "enumvalues"))
+ Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
+ else
+ Replaceall(enum_code, "$enumvalues", "");
+
+ if (proxy_flag && is_wrapping_class()) {
+ // Enums defined within the C++ class are defined within the proxy class
+
+ // Add extra indentation
+ Replaceall(enum_code, "\n", "\n ");
+ Replaceall(enum_code, " \n", "\n");
+
+ Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
+ } else {
+ // Global enums are defined in their own file
+ String *output_directory = outputDirectory(nspace);
+ File *f_enum = getOutputFile(output_directory, symname);
+
+ addOpenNamespace(nspace, f_enum);
+
+ Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", enum_code, "\n", NIL);
+
+ addCloseNamespace(nspace, f_enum);
+ if (f_enum != f_single_out)
+ Delete(f_enum);
+ f_enum = NULL;
+ Delete(output_directory);
+ }
+ } else {
+ // Wrap C++ enum with simple constant
+ Printf(enum_code, "\n");
+ if (proxy_flag && is_wrapping_class())
+ Printv(proxy_class_constants_code, enum_code, NIL);
+ else
+ Printv(module_class_constants_code, enum_code, NIL);
+ }
+
+ Delete(enum_code);
+ enum_code = NULL;
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ int unnamedinstance = GetFlag(parent, "unnamedinstance");
+ String *parent_name = Getattr(parent, "name");
+ String *nspace = getNSpace();
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_CHAR) {
+ String *enumstringval = Getattr(n, "enumstringval");
+ if (enumstringval) {
+ // Escape character literal for C#.
+ String *val = NewStringf("'%(csharpescape)s'", enumstringval);
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+ } else {
+ String *numval = Getattr(n, "enumnumval");
+ if (numval) Setattr(n, "enumvalue", numval);
+ }
+
+ {
+ EnumFeature enum_feature = decodeEnumFeature(parent);
+
+ if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
+
+ // Add to language symbol table
+ String *scope = 0;
+ if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", enumClassPrefix);
+ } else {
+ scope = Copy(module_class_name);
+ }
+ } else {
+ scope = getCurrentScopeName(nspace);
+ if (!scope)
+ scope = Copy(Getattr(parent, "sym:name"));
+ else
+ Printf(scope, ".%s", Getattr(parent, "sym:name"));
+ }
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+
+ if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) C/C++ enum with a proper C# enum
+ // Emit the enum item.
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(enum_code, ",\n");
+
+ if (csattributes)
+ Printf(enum_code, " %s\n", csattributes);
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab2);
+ Printv(enum_code, ds, NIL);
+ Delete(ds);
+ }
+ Printf(enum_code, " %s", symname);
+
+ // Check for the %csconstvalue feature
+ String *value = Getattr(n, "feature:cs:constvalue");
+
+ // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
+ value = value ? value : Getattr(n, "enumvalue");
+ if (value) {
+ Printf(enum_code, " = %s", value);
+ }
+ } else {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ Setattr(n, "type", typemap_lookup_type);
+ const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF);
+
+ String *return_type = Copy(tm);
+ substituteClassname(typemap_lookup_type, return_type);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ if (csattributes)
+ Printf(enum_code, " %s\n", csattributes);
+
+ if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) enum using the typesafe enum pattern
+ if (Getattr(n, "enumvalue")) {
+ String *value = enumValue(n);
+ Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
+ Delete(value);
+ } else {
+ Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
+ }
+ } else {
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
+
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ const char *const_readonly = const_feature_flag ? "const" : "static readonly";
+ String *value = enumValue(n);
+ Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
+ Delete(value);
+ }
+ Delete(return_type);
+ }
+
+ // Add the enum value to the comma separated list being constructed in the enum declaration.
+ String *enumvalues = Getattr(parent, "enumvalues");
+ if (!enumvalues)
+ Setattr(parent, "enumvalues", Copy(symname));
+ else
+ Printv(enumvalues, ", ", symname, NIL);
+ Delete(scope);
+ }
+
+ Delete(newsymname);
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ * Used for wrapping constants - #define or %constant.
+ * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
+ * C# static const variables are generated for these.
+ * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
+ * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
+ * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
+ * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *return_type = NewString("");
+ String *constants_code = NewString("");
+ // The value as C# code.
+ String *csvalue = Copy(Getattr(n, "value"));
+ Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:cstype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:cstype:outattributes", NIL);
+
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+
+ const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
+ if (!is_enum_item) {
+ String *scope = 0;
+ if (proxy_class_name) {
+ String *nspace = getNSpace();
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", proxy_class_name);
+ } else {
+ scope = Copy(module_class_name);
+ }
+ if (!addSymbol(itemname, n, scope))
+ return SWIG_ERROR;
+ Delete(scope);
+ }
+
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ /* Adjust the enum type for the Swig_typemap_lookup.
+ * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
+ if (is_enum_item) {
+ t = Getattr(parentNode(n), "enumtype");
+ Setattr(n, "type", t);
+ }
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("cstype", l, NULL);
+
+ /* Get C# return types */
+ bool classname_substituted_flag = false;
+
+ if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
+ String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ classname_substituted_flag = substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (Getattr(n, "stringval")) {
+ char quote = 0;
+ switch (SwigType_type(t)) {
+ case T_STRING:
+ case T_WSTRING:
+ quote = '\"';
+ break;
+ case T_CHAR:
+ case T_WCHAR:
+ quote = '\'';
+ break;
+ }
+ if (quote) {
+ // Escape character literal for C#.
+ Delete(csvalue);
+ csvalue = NewStringf("%c%(csharpescape)s%c", quote, Getattr(n, "stringval"), quote);
+ }
+ }
+
+ const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(constants_code, " %s\n", outattributes);
+
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab2);
+ Printv(constants_code, ds, NIL);
+ Delete(ds);
+ }
+
+ Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
+
+ // Check for the %csconstvalue feature
+ String *value = Getattr(n, "feature:cs:constvalue");
+
+ if (value) {
+ Printf(constants_code, "%s;\n", value);
+ } else if (!const_feature_flag) {
+ // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
+
+ if (classname_substituted_flag) {
+ if (SwigType_isenum(t)) {
+ // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
+ Printf(constants_code, "(%s)%s.%s();\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ // This handles function pointers using the %constant directive
+ Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+ } else {
+ Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+
+ // Each constant and enum value is wrapped with a separate PInvoke function call
+ SetFlag(n, "feature:immutable");
+ enum_constant_flag = true;
+ variableWrapper(n);
+ enum_constant_flag = false;
+ } else {
+ // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
+ if (Getattr(n, "wrappedasconstant")) {
+ if (SwigType_type(t) == T_CHAR) {
+ String *stringval = Getattr(n, "stringval");
+ if (stringval)
+ Printf(constants_code, "'%(csharpescape)s';\n", stringval);
+ else
+ Printf(constants_code, "(char)%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ } else {
+ Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ }
+ } else {
+ Printf(constants_code, "%s;\n", csvalue);
+ }
+ }
+
+ // Emit the generated code to appropriate place
+ // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
+ if (!is_enum_item) {
+ if (proxy_flag && wrapping_member_flag)
+ Printv(proxy_class_constants_code, constants_code, NIL);
+ else
+ Printv(module_class_constants_code, constants_code, NIL);
+ }
+ // Cleanup
+ Swig_restore(n);
+ Delete(return_type);
+ Delete(constants_code);
+ Delete(csvalue);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * insertDirective()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int insertDirective(Node *n) {
+ int ret = SWIG_OK;
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ Replaceall(code, "$module", module_class_name);
+ Replaceall(code, "$imclassname", imclass_name);
+ Replaceall(code, "$dllimport", dllimport);
+
+ if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
+ if (proxy_class_code) {
+ Swig_typemap_replace_embedded_typemap(code, n);
+ int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
+ Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
+ }
+ } else {
+ ret = Language::insertDirective(n);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * pragmaDirective()
+ *
+ * Valid Pragmas:
+ * imclassbase - base (extends) for the intermediary class
+ * imclassclassmodifiers - class modifiers for the intermediary class
+ * imclasscode - text (C# code) is copied verbatim to the intermediary class
+ * imclassimports - import statements for the intermediary class
+ * imclassinterfaces - interface (implements) for the intermediary class
+ *
+ * modulebase - base (extends) for the module class
+ * moduleclassmodifiers - class modifiers for the module class
+ * modulecode - text (C# code) is copied verbatim to the module class
+ * moduleimports - import statements for the module class
+ * moduleinterfaces - interface (implements) for the module class
+ *
+ * ----------------------------------------------------------------------------- */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "csharp") == 0) {
+
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "imclassbase") == 0) {
+ Delete(imclass_baseclass);
+ imclass_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "imclasscode") == 0) {
+ Printf(imclass_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "imclassimports") == 0) {
+ Delete(imclass_imports);
+ imclass_imports = Copy(strvalue);
+ } else if (Strcmp(code, "imclassinterfaces") == 0) {
+ Delete(imclass_interfaces);
+ imclass_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "modulebase") == 0) {
+ Delete(module_baseclass);
+ module_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
+ Delete(module_class_modifiers);
+ module_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "modulecode") == 0) {
+ Printf(module_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "moduleimports") == 0) {
+ Delete(module_imports);
+ module_imports = Copy(strvalue);
+ } else if (Strcmp(code, "moduleinterfaces") == 0) {
+ Delete(module_interfaces);
+ module_interfaces = Copy(strvalue);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getQualifiedInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getQualifiedInterfaceName(Node *n) {
+ String *ret = Getattr(n, "interface:qname");
+ if (!ret) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *interface_name = Getattr(n, "interface:name");
+ if (nspace) {
+ if (namespce)
+ ret = NewStringf("%s.%s.%s", namespce, nspace, interface_name);
+ else
+ ret = NewStringf("%s.%s", nspace, interface_name);
+ } else {
+ ret = Copy(interface_name);
+ }
+ Setattr(n, "interface:qname", ret);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getInterfaceName(SwigType *t, bool qualified) {
+ String *interface_name = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n && Getattr(n, "interface:name"))
+ interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
+ }
+ return interface_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addInterfaceNameAndUpcasts()
+ * ----------------------------------------------------------------------------- */
+
+ void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, List *base_list, SwigType *c_classname) {
+ for (Iterator it = First(base_list); it.item; it = Next(it)) {
+ Node *base = it.item;
+ SwigType *c_baseclassname = Getattr(base, "name");
+ String *interface_name = Getattr(base, "interface:name");
+ SwigType *bsmart = Getattr(base, "smart");
+ if (Len(interface_list))
+ Append(interface_list, ", ");
+ Append(interface_list, interface_name);
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(base, "csinterfacecode", Getattr(base, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ String *cptr_method_name = 0;
+ if (interface_code) {
+ Replaceall(interface_code, "$interfacename", interface_name);
+ Printv(interface_upcasts, interface_code, NIL);
+ cptr_method_name = Copy(Getattr(attributes, "tmap:csinterfacecode:cptrmethod"));
+ }
+ if (!cptr_method_name)
+ cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
+ Replaceall(cptr_method_name, ".", "_");
+ Replaceall(cptr_method_name, "$interfacename", interface_name);
+
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
+ upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname);
+
+ Delete(upcast_method_name);
+ Delete(cptr_method_name);
+ Delete(interface_code);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * upcastsCode()
+ *
+ * Add code for C++ casting to base class
+ * ----------------------------------------------------------------------------- */
+
+ void upcastsCode(SwigType *smart, SwigType *bsmart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
+ String *wname = Swig_name_wrapper(upcast_method_name);
+
+ Printv(imclass_cppcasts_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
+ Printf(imclass_cppcasts_code, " public static extern global::System.IntPtr %s(global::System.IntPtr jarg1);\n", upcast_method_name);
+
+ Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
+
+ if (smart) {
+ if (bsmart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(bsmart);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n",
+ " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n"
+ "}\n", "\n", NIL);
+
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ }
+ } else {
+ String *classname = SwigType_namestr(c_classname);
+ String *baseclassname = SwigType_namestr(c_baseclassname);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT ", baseclassname, " * SWIGSTDCALL ", wname, "(", classname, " *jarg1) {\n",
+ " return (", baseclassname, " *)jarg1;\n"
+ "}\n", "\n", NIL);
+
+ Delete(baseclassname);
+ Delete(classname);
+ }
+
+ Delete(wname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ SwigType *c_classname = Getattr(n, "name");
+ SwigType *c_baseclassname = NULL;
+ String *baseclass = NULL;
+ String *interface_list = NewStringEmpty();
+ String *interface_upcasts = NewStringEmpty();
+ 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");
+ SwigType *smart = Getattr(n, "smart");
+ SwigType *bsmart = 0;
+
+ // Inheritance from pure C# classes
+ Node *attributes = NewHash();
+ const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!(GetFlag(base.item, "feature:ignore") || GetFlag(base.item, "feature:interface"))) {
+ SwigType *baseclassname = Getattr(base.item, "name");
+ if (!c_baseclassname) {
+ String *name = getProxyName(baseclassname);
+ if (name) {
+ c_baseclassname = baseclassname;
+ baseclass = name;
+ bsmart = Getattr(base.item, "smart");
+ }
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+ List *interface_bases = Getattr(n, "interface:bases");
+ if (interface_bases)
+ addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
+
+ bool derived = baseclass != 0;
+ if (derived && purebase_notderived)
+ pure_baseclass = empty_string;
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ baseclass = NULL;
+ if (purebase_notderived)
+ Swig_error(Getfile(n), Getline(n), "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
+ } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in C#. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Pure C# interfaces
+ const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
+ if (*Char(interface_list) && *Char(pure_interfaces))
+ Append(interface_list, ", ");
+ Append(interface_list, pure_interfaces);
+ // Start writing the proxy class
+ if (!has_outerclass)
+ Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", NIL);
+
+ // Class attributes
+ const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
+ if (csattributes && *Char(csattributes))
+ Printf(proxy_class_def, "%s\n", csattributes);
+
+ Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $csclassname", // Class name and base class
+ (*Char(wanted_base) || *Char(interface_list)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(interface_list)) ? // Interfaces
+ ", " : "", interface_list, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
+ typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
+ NIL);
+
+ // C++ destructor is wrapped by the Finalize and Dispose methods
+
+ const char *tmap_method = derived ? "csdestruct_derived" : "csdestruct";
+ const String *tm = typemapExists(n, tmap_method, typemap_lookup_type);
+ if (tm) {
+ Swig_error(Getfile(tm), Getline(tm),
+ "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
+ tmap_method, proxy_class_name);
+ }
+ tmap_method = "csfinalize";
+ tm = typemapExists(n, tmap_method, typemap_lookup_type);
+ if (tm) {
+ Swig_error(Getfile(tm), Getline(tm),
+ "A deprecated %s typemap was found for %s, please remove it and replace all csdestruct, csdestruct_derived and csfinalize typemaps by the csdispose, csdispose_derived, csdisposing and csdisposing_derived typemaps.\n",
+ tmap_method, proxy_class_name);
+ }
+
+ tmap_method = derived ? "csdisposing_derived" : "csdisposing";
+ String *destruct = NewString("");
+ attributes = NewHash();
+ const String *destruct_methodname = NULL;
+ const String *destruct_methodmodifiers = NULL;
+ const String *destruct_parameters = NULL;
+ if (derived) {
+ tm = typemapLookup(n, "csdisposing_derived", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:csdisposing_derived:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing_derived:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:csdisposing_derived:parameters");
+ } else {
+ tm = typemapLookup(n, "csdisposing", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:csdisposing:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:csdisposing:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:csdisposing:parameters");
+ }
+ if (tm && *Char(tm)) {
+ if (!destruct_methodname) {
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in %s typemap for %s\n", tmap_method, proxy_class_name);
+ }
+ if (!destruct_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodmodifiers attribute defined in %s typemap for %s.\n", tmap_method, proxy_class_name);
+ }
+ if (!destruct_parameters)
+ destruct_parameters = empty_string;
+ }
+ // Emit the Finalize and Dispose methods
+ if (tm) {
+ // Finalize and Dispose methods
+ Printv(proxy_class_def, typemapLookup(n, derived ? "csdispose_derived" : "csdispose", typemap_lookup_type, WARN_NONE), NIL);
+ // Dispose(bool disposing) method
+ Printv(destruct, tm, NIL);
+ if (*Char(destructor_call))
+ Replaceall(destruct, "$imcall", destructor_call);
+ else
+ Replaceall(destruct, "$imcall", "throw new global::System.MethodAccessException(\"C++ destructor does not have public access\")");
+ if (*Char(destruct)) {
+ Printv(proxy_class_def, "\n ", NIL);
+ const String *methodmods = Getattr(n, "destructmethodmodifiers");
+ if (methodmods)
+ Printv(proxy_class_def, methodmods, NIL);
+ else
+ Printv(proxy_class_def, destruct_methodmodifiers, " ", derived ? "override" : "virtual", NIL);
+ Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ") ", destruct, "\n", NIL);
+ }
+ }
+ if (*Char(interface_upcasts))
+ Printv(proxy_class_def, interface_upcasts, NIL);
+
+ if (feature_director) {
+ // Generate director connect method
+ // put this in classDirectorEnd ???
+ Printf(proxy_class_code, " private void SwigDirectorConnect() {\n");
+
+ int i;
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *method = Getattr(udata, "method");
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+ Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
+ Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirectorMethod%s);\n", methid, proxy_class_name, methid, overname);
+ }
+ 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);
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_code, ", swigDelegate%s", methid);
+ }
+ Printf(proxy_class_code, ");\n");
+ Printf(proxy_class_code, " }\n");
+
+ if (first_class_dmethod < curr_class_dmethod) {
+ // Only emit if there is at least one director method
+ Printf(proxy_class_code, "\n");
+ Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, global::System.Type[] methodTypes) {\n");
+ Printf(proxy_class_code, " global::System.Reflection.MethodInfo[] methodInfos = this.GetType().GetMethods(\n");
+ Printf(proxy_class_code, " global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance);\n");
+ Printf(proxy_class_code, " foreach (global::System.Reflection.MethodInfo methodInfo in methodInfos) {\n");
+ Printf(proxy_class_code, " if (methodInfo.DeclaringType == null)\n");
+ Printf(proxy_class_code, " continue;\n\n");
+ Printf(proxy_class_code, " if (methodInfo.Name != methodName)\n");
+ Printf(proxy_class_code, " continue;\n\n");
+ Printf(proxy_class_code, " var parameters = methodInfo.GetParameters();\n");
+ Printf(proxy_class_code, " if (parameters.Length != methodTypes.Length)\n");
+ Printf(proxy_class_code, " continue;\n\n");
+ Printf(proxy_class_code, " bool parametersMatch = true;\n");
+ Printf(proxy_class_code, " for (var i = 0; i < parameters.Length; i++) {\n");
+ Printf(proxy_class_code, " if (parameters[i].ParameterType != methodTypes[i]) {\n");
+ Printf(proxy_class_code, " parametersMatch = false;\n");
+ Printf(proxy_class_code, " break;\n");
+ Printf(proxy_class_code, " }\n");
+ Printf(proxy_class_code, " }\n\n");
+ Printf(proxy_class_code, " if (!parametersMatch)\n");
+ Printf(proxy_class_code, " continue;\n\n");
+ Printf(proxy_class_code, " if (methodInfo.IsVirtual && (methodInfo.DeclaringType.IsSubclassOf(typeof(%s))) &&\n", proxy_class_name);
+ Printf(proxy_class_code, " methodInfo.DeclaringType != methodInfo.GetBaseDefinition().DeclaringType) {\n");
+ Printf(proxy_class_code, " return true;\n");
+ Printf(proxy_class_code, " }\n");
+ Printf(proxy_class_code, " }\n\n");
+ Printf(proxy_class_code, " return false;\n");
+
+ /* Could add this code to cover corner case where the GetMethod() returns a method which allows type
+ * promotion, eg it will return foo(double), if looking for foo(int).
+ if (hasDerivedMethod) {
+ hasDerivedMethod = false;
+ if (methodInfo != null)
+ {
+ hasDerivedMethod = true;
+ ParameterInfo[] parameterArray1 = methodInfo.GetParameters();
+ for (int i=0; i<methodTypes.Length; i++)
+ {
+ if (parameterArray1[0].ParameterType != methodTypes[0])
+ {
+ hasDerivedMethod = false;
+ break;
+ }
+ }
+ }
+ }
+ */
+ //Printf(proxy_class_code, " return hasDerivedMethod;\n");
+ Printf(proxy_class_code, " }\n");
+ }
+
+ if (Len(director_delegate_callback) > 0)
+ Printv(proxy_class_code, director_delegate_callback, NIL);
+ if (Len(director_delegate_definitions) > 0)
+ Printv(proxy_class_code, "\n", director_delegate_definitions, NIL);
+ if (Len(director_delegate_instances) > 0)
+ Printv(proxy_class_code, "\n", director_delegate_instances, NIL);
+ if (Len(director_method_types) > 0)
+ Printv(proxy_class_code, "\n", director_method_types, NIL);
+
+ Delete(director_callback_typedefs);
+ director_callback_typedefs = NULL;
+ Delete(director_callbacks);
+ director_callbacks = NULL;
+ Delete(director_delegate_callback);
+ director_delegate_callback = NULL;
+ Delete(director_delegate_definitions);
+ director_delegate_definitions = NULL;
+ Delete(director_delegate_instances);
+ director_delegate_instances = NULL;
+ Delete(director_method_types);
+ director_method_types = NULL;
+ Delete(director_connect_parms);
+ director_connect_parms = NULL;
+ Delete(director_connect_method_name);
+ }
+
+ Delete(interface_upcasts);
+ Delete(interface_list);
+ Delete(attributes);
+ Delete(destruct);
+
+ // Emit extra user code
+ Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
+ "\n", NIL);
+
+ if (derived) {
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
+ upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname);
+ Delete(upcast_method_name);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * emitInterfaceDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface) {
+ Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
+ Printv(f_interface, typemapLookup(n, "csinterfacemodifiers", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL);
+ Printf(f_interface, " %s", interface_name);
+
+ String *additional = Getattr(n, "feature:interface:additional");
+ String *bases = additional ? NewStringf(" : %s", additional) : 0;
+ if (List *baselist = Getattr(n, "bases")) {
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (GetFlag(base.item, "feature:ignore") || !GetFlag(base.item, "feature:interface"))
+ continue; // TODO: warn about skipped non-interface bases
+ String *base_iname = Getattr(base.item, "interface:name");
+ if (!bases)
+ bases = NewStringf(" : %s", base_iname);
+ else {
+ Append(bases, ", ");
+ Append(bases, base_iname);
+ }
+ }
+ }
+ if (bases) {
+ Printv(f_interface, bases, NIL);
+ Delete(bases);
+ }
+ Printf(f_interface, " {\n");
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(n, "csinterfacecode", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ if (interface_code) {
+ String *interface_declaration = Copy(Getattr(attributes, "tmap:csinterfacecode:declaration"));
+ if (interface_declaration) {
+ Replaceall(interface_declaration, "$interfacename", interface_name);
+ Printv(f_interface, interface_declaration, NIL);
+ Delete(interface_declaration);
+ }
+ Delete(interface_code);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ String *nspace = getNSpace();
+ File *f_proxy = NULL;
+ File *f_interface = 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;
+ bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
+ String *old_interface_class_code = interface_class_code;
+ interface_class_code = 0;
+
+ if (proxy_flag) {
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+ String *interface_name = GetFlag(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
+ 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 (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
+ return SWIG_ERROR;
+ if (nspace)
+ Delete(fnspace);
+ Delete(outerClassesPrefix);
+ } else {
+ if (!addSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
+ return SWIG_ERROR;
+ }
+
+ if (!nspace) {
+ 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);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (Cmp(proxy_class_name, module_class_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
+ Exit(EXIT_FAILURE);
+ }
+ } else {
+ if (namespce) {
+ full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
+ } else {
+ full_imclass_name = NewStringf("%s", imclass_name);
+ }
+ }
+
+ if (!has_outerclass) {
+ String *output_directory = outputDirectory(nspace);
+ f_proxy = getOutputFile(output_directory, proxy_class_name);
+
+ addOpenNamespace(nspace, f_proxy);
+ Delete(output_directory);
+ }
+ else
+ ++nesting_depth;
+
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ destructor_call = NewString("");
+ proxy_class_constants_code = NewString("");
+
+ if (GetFlag(n, "feature:interface")) {
+ interface_class_code = NewString("");
+ String *output_directory = outputDirectory(nspace);
+ f_interface = getOutputFile(output_directory, interface_name);
+ addOpenNamespace(nspace, f_interface);
+ emitInterfaceDeclaration(n, interface_name, interface_class_code);
+ Delete(output_directory);
+ }
+ }
+
+ Language::classHandler(n);
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab0);
+ Printv(proxy_class_def, ds, NIL);
+ Delete(ds);
+ }
+
+ if (proxy_flag) {
+
+ emitProxyClassDefAndCPPCasts(n);
+
+ 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);
+ Replaceall(proxy_class_constants_code, "$csclassname", proxy_class_name);
+ Replaceall(interface_class_code, "$csclassname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$csclazzname", csclazzname);
+ Replaceall(proxy_class_code, "$csclazzname", csclazzname);
+ Replaceall(proxy_class_constants_code, "$csclazzname", csclazzname);
+ Replaceall(interface_class_code, "$csclazzname", csclazzname);
+
+ Replaceall(proxy_class_def, "$module", module_class_name);
+ Replaceall(proxy_class_code, "$module", module_class_name);
+ Replaceall(proxy_class_constants_code, "$module", module_class_name);
+ Replaceall(interface_class_code, "$module", module_class_name);
+
+ Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
+ Replaceall(interface_class_code, "$imclassname", full_imclass_name);
+
+ Replaceall(proxy_class_def, "$dllimport", dllimport);
+ Replaceall(proxy_class_code, "$dllimport", dllimport);
+ Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
+ Replaceall(interface_class_code, "$dllimport", dllimport);
+
+ 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) {
+ 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);
+ if (f_proxy != f_single_out)
+ 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;
+ }
+
+ if (f_interface) {
+ Printv(f_interface, interface_class_code, "}\n", NIL);
+ addCloseNamespace(nspace, f_interface);
+ if (f_interface != f_single_out)
+ Delete(f_interface);
+ f_interface = 0;
+ }
+
+ emitDirectorExtraMethods(n);
+
+ Delete(interface_class_code);
+ interface_class_code = old_interface_class_code;
+ Delete(csclazzname);
+ Delete(proxy_class_name);
+ proxy_class_name = old_proxy_class_name;
+ Delete(full_imclass_name);
+ full_imclass_name = old_full_imclass_name;
+ Delete(destructor_call);
+ destructor_call = old_destructor_call;
+ Delete(proxy_class_constants_code);
+ 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;
+ }
+
+ void printArgumentDeclaration(Node *n, Parm *p, String *param_type, String *arg, String *code)
+ {
+ String *specifiedoverridekey = NewString("feature:cs:defaultargs:");
+ Append(specifiedoverridekey, arg);
+ String *specifiedoverridevalue = Getattr(n, specifiedoverridekey);
+ if (specifiedoverridevalue) {
+ Printf(code, "%s %s=%s", param_type, arg, specifiedoverridevalue);
+ } else {
+ String *cppvalue = NULL;
+ //if they've not specified defaultargs, then fall back to
+ //the normal default handling of specifying one overload per possible
+ //set of arguments. If they have, then use the default argument from
+ //c++ as a literal csharp expression.
+ if (Getattr(n, "feature:cs:defaultargs"))
+ cppvalue = Getattr(p, "value");
+ if (cppvalue)
+ Printf(code, "%s %s=%s", param_type, arg, cppvalue);
+ else
+ Printf(code, "%s %s", param_type, arg);
+ }
+ Delete(specifiedoverridekey);
+ }
+
+
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ 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);
+ Delete(overloaded_name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+
+ static_flag = true;
+ Language::staticmemberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ 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);
+ Delete(overloaded_name);
+ }
+ static_flag = false;
+
+ return SWIG_OK;
+ }
+
+
+ /* -----------------------------------------------------------------------------
+ * proxyClassFunctionHandler()
+ *
+ * Function called for creating a C# wrapper function around a c++ function in the
+ * proxy class. Used for both static and non-static C++ class functions.
+ * C++ class static functions map to C# static functions.
+ * Two extra attributes in the Node must be available. These are "proxyfuncname" -
+ * the name of the C# class proxy function, which in turn will call "imfuncname" -
+ * the intermediary (PInvoke) function name in the intermediary class.
+ * ----------------------------------------------------------------------------- */
+
+ void proxyClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ Parm *last_parm = 0;
+ int i;
+ String *comment_code = NewString("");
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ bool is_interface = GetFlag(parentNode(n), "feature:interface") && !checkAttribute(n, "kind", "variable")
+ && !static_flag && Getattr(n, "interface:owner") == 0;
+
+ if (!proxy_flag)
+ return;
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ if (Getattr(n, "feature:cs:defaultargs") && Getattr(n, "defaultargs"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in directors
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("cstype", l, NULL);
+ Swig_typemap_attach_parms("csin", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
+ // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
+ SwigType *covariant = Getattr(n, "covariant");
+ String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ substituteClassname(covariant ? covariant : t, tm);
+ Printf(return_type, "%s", tm);
+ if (covariant)
+ Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number,
+ "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(covariant, 0));
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag && !enum_constant_flag) {
+ // Properties
+ 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);
+ }
+
+ /* Start generating the proxy function */
+ const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(function_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (methodmods) {
+ if (is_smart_pointer()) {
+ // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
+ String *mmods = Copy(methodmods);
+ Replaceall(mmods, "override", "");
+ Replaceall(mmods, "virtual", "");
+ Replaceall(mmods, "new", "");
+ Chop(mmods); // remove trailing whitespace
+ Printf(function_code, " %s ", mmods);
+ Delete(mmods);
+ } else {
+ Printf(function_code, " %s ", methodmods);
+ }
+ } else {
+ methodmods = (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s ", methodmods);
+ if (!is_smart_pointer()) {
+ // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
+ if (Getattr(n, "override"))
+ Printf(function_code, "override ");
+ else if (checkAttribute(n, "storage", "virtual"))
+ Printf(function_code, "virtual ");
+ if (Getattr(n, "hides"))
+ Printf(function_code, "new ");
+ }
+ }
+ if (static_flag)
+ Printf(function_code, "static ");
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+ if (is_interface)
+ Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
+
+ Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
+ if (!static_flag)
+ Printf(imcall, "swigCPtr");
+
+ emit_mark_varargs(l);
+ int gencomma = !static_flag;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ /* Ignore the 'this' argument for variable wrappers */
+ if (!(variable_wrapper_flag && i == 0)) {
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+ if (setter_flag)
+ last_parm = p;
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, setter_flag);
+
+ // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:csin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", arg);
+ String *pre = Getattr(p, "tmap:csin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$csinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$csinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$csinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma >= 2) {
+ Printf(function_code, ", ");
+ if (is_interface)
+ Printf(interface_class_code, ", ");
+ }
+ gencomma = 2;
+ printArgumentDeclaration(n, p, param_type, arg, function_code);
+ if (is_interface)
+ printArgumentDeclaration(n, p, param_type, arg, interface_class_code);
+
+ Delete(arg);
+ Delete(param_type);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+ if (is_interface)
+ Printf(interface_class_code, ");\n");
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab2);
+ Printv(comment_code, ds, NIL);
+ Delete(ds);
+ }
+
+ // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
+ if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
+ excodeSubstitute(n, tm, "csout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+
+ // For director methods: generate code to selectively make a normal polymorphic call or
+ // an explicit method call - needed to prevent infinite recursion calls in director methods.
+ 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(), getClassPrefix(), ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ String *excode = NewString("");
+ Node *directorNode = Getattr(n, "directorNode");
+ UpcallData *udata = directorNode ? Getattr(directorNode, "upcalldata") : 0;
+ if (udata) {
+ String *methid = Getattr(udata, "class_methodidx");
+
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s)) %s; else %s", proxy_function_name, methid, ex_imcall, imcall);
+ else
+ Printf(excode, "(SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s) ? %s : %s)", proxy_function_name, methid, ex_imcall, imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ } else {
+ // probably an ignored method or nodirector
+ }
+ Delete(excode);
+ Delete(ex_overloaded_name);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+ Replaceall(tm, "$imfuncname", intermediary_function_name);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag && !enum_constant_flag) {
+ // Properties
+ if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
+ // Get the C# variable type - obtained differently depending on whether a setter is required.
+ String *variable_type = return_type;
+ if (setter_flag) {
+ assert(last_parm); // (last parameter is the only parameter for properties)
+ /* Get variable type - ensure the variable name is fully resolved during typemap lookup via the symbol table set in NewParmNode */
+ SwigType *cvariable_type = Getattr(last_parm, "type");
+ Parm *variable_parm = NewParmNode(cvariable_type, n);
+ if ((tm = Swig_typemap_lookup("cstype", variable_parm, "", 0))) {
+ String *cstypeout = Getattr(variable_parm, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ substituteClassname(cvariable_type, tm);
+ variable_type = tm;
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(cvariable_type, 0));
+ }
+ }
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(proxy_class_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (!methodmods)
+ methodmods = (is_public(n) ? public_string : protected_string);
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab2);
+ Printv(proxy_class_code, ds, NIL);
+ Delete(ds);
+ }
+
+ // Start property declaration
+ Printf(proxy_class_code, " %s %s%s %s {", methodmods, static_flag ? "static " : "", variable_type, variable_name);
+ }
+ generate_property_declaration_flag = false;
+
+ if (setter_flag) {
+ // Setter method
+ assert(last_parm); // (last parameter is the only parameter for properties)
+ SwigType *cvariable_type = Getattr(last_parm, "type");
+ Parm *variable_parm = NewParmNode(cvariable_type, n);
+ if ((tm = Swig_typemap_lookup("csvarin", variable_parm, "", 0))) {
+ substituteClassname(cvariable_type, tm);
+ Replaceall(tm, "$csinput", "value");
+ Replaceall(tm, "$imfuncname", intermediary_function_name);
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarin", variable_parm);
+ Printf(proxy_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(cvariable_type, 0));
+ }
+ } else {
+ // Getter method
+ if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imfuncname", intermediary_function_name);
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarout", n);
+ Printf(proxy_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+ } else {
+ // Normal function call
+ Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
+ Printv(proxy_class_code, comment_code, NIL);
+ Printv(proxy_class_code, function_code, NIL);
+ }
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ----------------------------------------------------------------------
+ * constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int constructorHandler(Node *n) {
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *function_code = NewString("");
+ String *comment_code = NewString("");
+ String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the csin typemap has code in the pre or post attributes
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ String *im_return_type = NewString("");
+ bool feature_director = (parentNode(n) && Swig_directorclass(n));
+
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
+ if (Getattr(n, "overload:ignore"))
+ return SWIG_OK;
+
+ if (Getattr(n, "feature:cs:defaultargs") && Getattr(n, "defaultargs"))
+ return SWIG_OK;
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
+ String *imcall = NewString("");
+
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes) {
+ Printf(function_code, " %s\n", csattributes);
+ Printf(helper_code, " %s\n", csattributes);
+ }
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ tm = Getattr(n, "tmap:imtype"); // typemaps were attached earlier to the node
+ String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ Printf(im_return_type, "%s", tm);
+
+ Printf(function_code, " %s %s(", methodmods, proxy_class_name);
+ Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
+
+ Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("cstype", l, NULL);
+ Swig_typemap_attach_parms("csin", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+ String *cshin = 0;
+
+ // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:csin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", arg);
+ String *pre = Getattr(p, "tmap:csin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$csinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$csinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$csinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ cshin = Getattr(p, "tmap:csin:cshin");
+ if (cshin)
+ Replaceall(cshin, "$csinput", arg);
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(function_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ printArgumentDeclaration(n, p, param_type, arg, function_code);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", cshin ? cshin : arg);
+ ++gencomma;
+
+ Delete(cshin);
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(function_code, ")");
+ Printf(helper_code, ")");
+
+ /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */
+ Hash *attributes = NewHash();
+ String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
+ String *construct_tm = Copy(typemapLookup(n, "csconstruct", typemap_lookup_type,
+ WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes));
+ if (construct_tm) {
+ if (!feature_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:csconstruct:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_CSHARP_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"csconstruct\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(function_code, " ", construct_tm, NIL);
+ }
+
+ excodeSubstitute(n, function_code, "csconstruct", attributes);
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ if (is_terminator_code) {
+ Printv(helper_code, "\n", terminator_code, NIL);
+ }
+ Printf(helper_code, "\n }\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
+ String *im_outattributes = Getattr(n, "tmap:imtype:outattributes");
+ if (im_outattributes)
+ Printf(proxy_class_code, " %s\n", im_outattributes);
+ Printv(proxy_class_code, helper_code, "\n", NIL);
+ Replaceall(function_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(function_code, "$imcall", imcall);
+ }
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab2);
+ Printv(comment_code, ds, NIL);
+ Delete(ds);
+ }
+
+ Printv(proxy_class_code, comment_code, NIL);
+ Printv(proxy_class_code, function_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(im_return_type);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ if (proxy_flag) {
+ Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (methodmods)
+ Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+
+ generate_property_declaration_flag = true;
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+ generate_property_declaration_flag = false;
+
+ // End property declaration
+ Printf(proxy_class_code, "\n }\n\n");
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+
+ generate_property_declaration_flag = true;
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+ generate_property_declaration_flag = false;
+
+ if (!GetFlag(n, "wrappedasconstant")) {
+ // End property declaration
+ Printf(proxy_class_code, "\n }\n\n");
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberconstantHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getOverloadedName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getOverloadedName(Node *n) {
+
+ /* A C# HandleRef is used for all classes in the SWIG intermediary class.
+ * The intermediary class methods are thus mangled when overloaded to give
+ * a unique name. */
+ String *overloaded_name = Copy(Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
+ }
+
+ return overloaded_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * moduleClassFunctionHandler()
+ * ----------------------------------------------------------------------------- */
+
+ void moduleClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ Parm *last_parm = 0;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ if (Getattr(n, "feature:cs:defaultargs") && Getattr(n, "defaultargs"))
+ return;
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("cstype", l, NULL);
+ Swig_typemap_attach_parms("csin", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
+ String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ if (cstypeout)
+ tm = cstypeout;
+ substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ /* Change function name for global variables */
+ if (proxy_flag && global_variable_flag) {
+ // Capitalize the first letter in the variable to create the getter/setter function name
+ func_name = NewString("");
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
+ if (setter_flag)
+ Printf(func_name, "set");
+ else
+ Printf(func_name, "get");
+ Putc(toupper((int) *Char(variable_name)), func_name);
+ Printf(func_name, "%s", Char(variable_name) + 1);
+ if (setter_flag)
+ Swig_typemap_attach_parms("csvarin", l, NULL);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(function_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ // Translate documentation comments
+ if (have_docstring(n)) {
+ String *ds = docstring(n, tab2);
+ Printv(function_code, ds, NIL);
+ Delete(ds);
+ }
+
+ Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
+ Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+
+ bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+ last_parm = p;
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, global_or_member_variable);
+
+ // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:csin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", arg);
+ String *pre = Getattr(p, "tmap:csin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$csinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$csinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$csinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ printArgumentDeclaration(n, p, param_type, arg, function_code);
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class)
+ if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
+ excodeSubstitute(n, tm, "csout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imfuncname", overloaded_name);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (proxy_flag && global_variable_flag) {
+ // Properties
+ if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
+ // Get the C# variable type - obtained differently depending on whether a setter is required.
+ String *variable_type = return_type;
+ if (setter_flag) {
+ p = last_parm; // (last parameter is the only parameter for properties)
+ SwigType *pt = Getattr(p, "type");
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ String *cstypeout = Getattr(p, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
+ variable_type = cstypeout ? cstypeout : tm;
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ }
+ const String *csattributes = Getattr(n, "feature:cs:attributes");
+ if (csattributes)
+ Printf(module_class_code, " %s\n", csattributes);
+ const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
+ if (!methodmods)
+ methodmods = (is_public(n) ? public_string : protected_string);
+ Printf(module_class_code, " %s static %s %s {", methodmods, variable_type, variable_name);
+ }
+ generate_property_declaration_flag = false;
+
+ if (setter_flag) {
+ // Setter method
+ p = last_parm; // (last parameter is the only parameter for properties)
+ SwigType *pt = Getattr(p, "type");
+ if ((tm = Getattr(p, "tmap:csvarin"))) {
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", "value");
+ Replaceall(tm, "$imfuncname", overloaded_name);
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarin", p);
+ Printf(module_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ // Getter method
+ if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imfuncname", overloaded_name);
+ Replaceall(tm, "$imcall", imcall);
+ excodeSubstitute(n, tm, "csvarout", n);
+ Printf(module_class_code, "%s", tm);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+ } else {
+ // Normal function call
+ Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
+ Printv(module_class_code, function_code, NIL);
+ }
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *--------------------------------------------------------------------*/
+
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+ substituteClassname(type, tm);
+ }
+
+ /*----------------------------------------------------------------------
+ * decodeEnumFeature()
+ * Decode the possible enum features, which are one of:
+ * %csenum(simple)
+ * %csenum(typeunsafe) - default
+ * %csenum(typesafe)
+ * %csenum(proper)
+ *--------------------------------------------------------------------*/
+
+ EnumFeature decodeEnumFeature(Node *n) {
+ EnumFeature enum_feature = TypeunsafeEnum;
+ String *feature = Getattr(n, "feature:cs:enum");
+ if (feature) {
+ if (Cmp(feature, "simple") == 0)
+ enum_feature = SimpleEnum;
+ else if (Cmp(feature, "typesafe") == 0)
+ enum_feature = TypesafeEnum;
+ else if (Cmp(feature, "proper") == 0)
+ enum_feature = ProperEnum;
+ }
+ return enum_feature;
+ }
+
+ /* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in C# generated
+ * code. If the %csconst feature is not used, the string will contain the intermediary
+ * class call to obtain the enum value. The intermediary class and PINVOKE methods to obtain
+ * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
+ * is one and hopefully it will compile as C# code - e.g. 20 as in: enum E{e=20};
+ * The %csconstvalue feature overrides all other ways to generate the constant value.
+ * The caller must delete memory allocated for the returned string.
+ * ------------------------------------------------------------------------ */
+
+ String *enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ // Check for the %csconstvalue feature
+ String *value = Getattr(n, "feature:cs:constvalue");
+
+ if (!value) {
+ // The %csconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:cs:const");
+
+ if (const_feature_flag) {
+ // Use the C syntax to make a true C# constant and hope that it compiles as C# code
+ value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
+ } else {
+ String *newsymname = 0;
+ if (!getCurrentClass() || !proxy_flag) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ // A global scoped enum
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ symname = newsymname;
+ }
+ }
+
+ // Get the enumvalue from a PINVOKE call
+ if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
+ constantWrapper(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ memberconstantHandler(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
+ }
+ }
+ }
+ return value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(SwigType *t) {
+ Node *enumname = NULL;
+ Node *n = enumLookup(t);
+ if (n) {
+ enumname = Getattr(n, "enumname");
+ if (!enumname) {
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ // Add in class scope when referencing enum if not a global enum
+ String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
+ String *proxyname = 0;
+ if (scopename_prefix) {
+ proxyname = getProxyName(scopename_prefix);
+ }
+ if (proxyname) {
+ enumname = NewStringf("%s.%s", proxyname, symname);
+ } else {
+ // global enum or enum in a namespace
+ String *nspace = Getattr(n, "sym:nspace");
+ if (nspace) {
+ if (namespce)
+ enumname = NewStringf("%s.%s.%s", namespce, nspace, symname);
+ else
+ enumname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ enumname = Copy(symname);
+ }
+ }
+ Setattr(n, "enumname", enumname);
+ Delete(enumname);
+ Delete(scopename_prefix);
+ }
+ }
+ }
+
+ return enumname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassname()
+ *
+ * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
+ * that SWIG knows about. Also substitutes enums with enum name.
+ * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
+ * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
+ * Inputs:
+ * pt - parameter type
+ * tm - typemap contents that might contain the special variable to be replaced
+ * Outputs:
+ * tm - typemap contents complete with the special variable substitution
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * ----------------------------------------------------------------------------- */
+
+ bool substituteClassname(SwigType *pt, String *tm) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$csclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$csclassname");
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*csclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ if (Len(classnametype) > 0) {
+ substituteClassnameSpecialVariable(classnametype, tm, "$*csclassname");
+ substitution_performed = true;
+ }
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&csclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$&csclassname");
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$csinterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$csinterfacename", true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*csinterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*csinterfacename", true);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&csinterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&csinterfacename", true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", false);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassnameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
+ String *replacementname;
+ if (SwigType_isenum(classnametype)) {
+ String *enumname = getEnumName(classnametype);
+ if (enumname) {
+ replacementname = Copy(enumname);
+ } else {
+ bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
+ if (anonymous_enum) {
+ replacementname = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+ Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ } else {
+ String *classname = getProxyName(classnametype); // getProxyName() works for pointers to classes too
+ if (classname) {
+ replacementname = Copy(classname);
+ } else {
+ // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ Replaceall(tm, classnamespecialvariable, replacementname);
+
+ Delete(replacementname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteInterfacenameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool qualified) {
+
+ String *interfacename = getInterfaceName(interfacenametype, qualified);
+ if (interfacename) {
+ String *replacementname = Copy(interfacename);
+ Replaceall(tm, interfacenamespecialvariable, replacementname);
+ Delete(replacementname);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitTypeWrapperClass()
+ * ----------------------------------------------------------------------------- */
+
+ void emitTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ String *swigtype = NewString("");
+ File *f_swigtype = getOutputFile(SWIG_output_directory(), classname);
+
+ addOpenNamespace(0, f_swigtype);
+
+ // Pure C# baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "csbase", type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "csinterfaces", type, WARN_NONE);
+
+ // Emit the class
+ Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE), // Import statements
+ "\n", NIL);
+
+ // Class attributes
+ const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE);
+ if (csattributes && *Char(csattributes))
+ Printf(swigtype, "%s\n", csattributes);
+
+ Printv(swigtype, typemapLookup(n, "csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $csclassname", // Class name and base class
+ (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
+ ", " : "", pure_interfaces, " {", typemapLookup(n, "csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
+ typemapLookup(n, "cscode", type, WARN_NONE), // extra C# code
+ "}\n", NIL);
+
+ Replaceall(swigtype, "$csclassname", classname);
+ Replaceall(swigtype, "$module", module_class_name);
+ Replaceall(swigtype, "$imclassname", imclass_name);
+ Replaceall(swigtype, "$dllimport", dllimport);
+
+ // For unknown enums
+ Replaceall(swigtype, "$enumvalues", "");
+
+ Printv(f_swigtype, swigtype, NIL);
+
+ addCloseNamespace(0, f_swigtype);
+ if (f_swigtype != f_single_out)
+ Delete(f_swigtype);
+ f_swigtype = NULL;
+ Delete(swigtype);
+ Delete(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * typemapLookup()
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * ----------------------------------------------------------------------------- */
+
+ const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE)
+ Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ if (!typemap_attributes)
+ Delete(node);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * typemapExists()
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * returns found typemap or NULL if not found
+ * ----------------------------------------------------------------------------- */
+
+ const String *typemapExists(Node *n, const_String_or_char_ptr tmap_method, SwigType *type) {
+ Node *node = NewHash();
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ Delete(node);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * canThrow()
+ * Determine whether the code in the typemap can throw a C# exception.
+ * If so, note it for later when excodeSubstitute() is called.
+ * ----------------------------------------------------------------------------- */
+
+ void canThrow(Node *n, const String *typemap, Node *parameter) {
+ String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
+ String *canthrow = Getattr(parameter, canthrow_attribute);
+ if (canthrow)
+ Setattr(n, "csharp:canthrow", "1");
+ Delete(canthrow_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * excodeSubstitute()
+ * If a method can throw a C# exception, additional exception code is added to
+ * check for the pending exception so that it can then throw the exception. The
+ * $excode special variable is replaced by the exception code in the excode
+ * typemap attribute.
+ * ----------------------------------------------------------------------------- */
+
+ void excodeSubstitute(Node *n, String *code, const String *typemap, Node *parameter) {
+ String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
+ String *excode = Getattr(parameter, excode_attribute);
+ if (Getattr(n, "csharp:canthrow")) {
+ int count = Replaceall(code, "$excode", excode);
+ if (count < 1 || !excode) {
+ Swig_warning(WARN_CSHARP_EXCODE, input_file, line_number,
+ "C# exception may not be thrown - no $excode or excode attribute in '%s' typemap.\n", typemap);
+ }
+ } else {
+ Replaceall(code, "$excode", empty_string);
+ }
+ Delete(excode_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addOpenNamespace()
+ * ----------------------------------------------------------------------------- */
+
+ void addOpenNamespace(const String *nspace, File *file) {
+ if (namespce || nspace) {
+ Printf(file, "namespace ");
+ if (namespce)
+ Printv(file, namespce, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(file, nspace, NIL);
+ Printf(file, " {\n");
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addCloseNamespace()
+ * ----------------------------------------------------------------------------- */
+
+ void addCloseNamespace(const String *nspace, File *file) {
+ if (namespce || nspace)
+ Printf(file, "\n}\n");
+ }
+
+ /* -----------------------------------------------------------------------------
+ * outputDirectory()
+ *
+ * Return the directory to use for generating C# classes/enums and create the
+ * subdirectory (does not create if language specific outdir does not exist).
+ * ----------------------------------------------------------------------------- */
+
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(SWIG_output_directory());
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ Exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /*----------------------------------------------------------------------
+ * Start of director methods
+ *--------------------------------------------------------------------*/
+
+#if 0
+ /*----------------------------------------------------------------------
+ * emitDirectorUpcalls()
+ *--------------------------------------------------------------------*/
+
+ void emitDirectorUpcalls() {
+ if (n_dmethods) {
+ Wrapper *w = NewWrapper();
+ String *dmethod_data = NewString("");
+ int n_methods = 0;
+ Iterator udata_iter;
+
+ udata_iter = First(dmethods_seq);
+ while (udata_iter.item) {
+ UpcallData *udata = udata_iter.item;
+ Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
+ ++n_methods;
+
+ udata_iter = Next(udata_iter);
+
+ if (udata_iter.item)
+ Putc(',', dmethod_data);
+ Putc('\n', dmethod_data);
+ }
+
+
+ Wrapper_print(w, f_wrappers);
+ Delete(dmethod_data);
+ Delete(swig_module_init);
+ DelWrapper(w);
+ }
+ }
+#endif
+
+ /*----------------------------------------------------------------------
+ * emitDirectorExtraMethods()
+ *
+ * This is where the director connect method is generated.
+ *--------------------------------------------------------------------*/
+ void emitDirectorExtraMethods(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // Output the director connect method:
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+ 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);
+ SwigType *smart = Getattr(n, "smart");
+ String *smartptr = smart ? SwigType_namestr(smart) : 0;
+ 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));
+
+ Printv(imclass_class_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
+ Printf(imclass_class_code, " public static extern void %s(global::System.Runtime.InteropServices.HandleRef jarg1", swig_director_connect);
+
+ Wrapper *code_wrap = NewWrapper();
+ Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL %s(void *objarg", wname);
+
+ if (smartptr) {
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", smartptr, smartptr);
+ Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
+ Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
+ } else {
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
+ }
+
+ Printf(code_wrap->code, " director->swig_connect_director(");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+
+ 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->code, "callback%s", methid);
+ Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", qualified_classname, sym_name, methid, methid);
+ }
+
+ Printf(code_wrap->def, ") {\n");
+ Printf(code_wrap->code, ");\n");
+ Printf(imclass_class_code, ");\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(wname);
+ Delete(swig_director_connect);
+ Delete(qualified_classname);
+ Delete(dirclassname);
+ }
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying C# object.
+ *
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *overloaded_name = 0;
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = 0;
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = directorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ SwigType *c_ret_type = NULL;
+ String *jupcall_args = NewString("");
+ String *callback_typedef_parms = NewString("");
+ String *delegate_parms = NewString("");
+ String *proxy_method_types = NewString("");
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ if (!ignored_method)
+ overloaded_name = getOverloadedName(n);
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a C# exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ SwigType *noref_type = SwigType_del_reference(Copy(returntype));
+ String *noref_ltype = SwigType_lstr(noref_type, 0);
+ String *return_ltype = SwigType_lstr(returntype, 0);
+
+ Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
+ Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
+ Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
+ Printf(w->code, "c_result = &result_default;\n");
+ Delete(return_ltype);
+ Delete(noref_ltype);
+ Delete(noref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ if (!ignored_method) {
+ /* Create the intermediate class wrapper */
+ tm = Swig_typemap_lookup("imtype", n, "", 0);
+ if (tm) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ const String *im_directoroutattributes = Getattr(n, "tmap:imtype:directoroutattributes");
+ if (im_directoroutattributes) {
+ Printf(callback_def, " %s\n", im_directoroutattributes);
+ if (!ignored_method)
+ Printf(director_delegate_definitions, " %s\n", im_directoroutattributes);
+ }
+
+ Printf(callback_def, " private %s SwigDirectorMethod%s(", tm, overloaded_name);
+ const String *csdirectordelegatemodifiers = Getattr(n, "feature:csdirectordelegatemodifiers");
+ String *modifiers = (csdirectordelegatemodifiers ? NewStringf("%s%s", csdirectordelegatemodifiers, Len(csdirectordelegatemodifiers) > 0 ? " " : "") : NewStringf("public "));
+ Printf(director_delegate_definitions, " %sdelegate %s", modifiers, tm);
+ Delete(modifiers);
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+ }
+
+ if ((c_ret_type = Swig_typemap_lookup("ctype", n, "", 0))) {
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Swig_director_parms_fixup(l);
+
+ /* Attach the standard typemaps */
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("ctype", l, 0);
+ Swig_typemap_attach_parms("imtype", l, 0);
+ Swig_typemap_attach_parms("cstype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("csdirectorin", l, 0);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ /* Preamble code */
+ if (!ignored_method)
+ Printf(w->code, "if (!swig_callback%s) {\n", overloaded_name);
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ else if (!ignored_method)
+ Printf(w->code, "return;\n");
+ }
+
+ if (!ignored_method)
+ Printf(w->code, "} else {\n");
+
+ /* Go through argument list, convert from native to C# */
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* And add to the upcall args */
+ if (i > 0)
+ Printf(jupcall_args, ", ");
+ Printf(jupcall_args, "%s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = Getattr(p, "tmap:ctype"))) {
+ String *ctypeout = Getattr(p, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
+ if (ctypeout)
+ c_param_type = ctypeout;
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
+
+ /* Add input marshalling code */
+ if ((tm = Getattr(p, "tmap:directorin"))) {
+
+ Setattr(p, "emit:directorinput", arg);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ /* Add C type to callback typedef */
+ if (i > 0)
+ Printf(callback_typedef_parms, ", ");
+ Printf(callback_typedef_parms, "%s", c_param_type);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = Getattr(p, "tmap:imtype"))) {
+
+ String *imtypeout = Getattr(p, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
+ if (imtypeout)
+ tm = imtypeout;
+ const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
+
+ String *din = Copy(Getattr(p, "tmap:csdirectorin"));
+
+ if (din) {
+ Replaceall(din, "$module", module_class_name);
+ Replaceall(din, "$imclassname", imclass_name);
+ substituteClassname(pt, din);
+ Replaceall(din, "$iminput", ln);
+
+ // pre and post attribute support
+ String *pre = Getattr(p, "tmap:csdirectorin:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$iminput", ln);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:csdirectorin:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$iminput", ln);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:csdirectorin:terminator");
+ if (terminator) {
+ substituteClassname(pt, terminator);
+ Replaceall(terminator, "$iminput", ln);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+
+ if (i > 0) {
+ Printf(delegate_parms, ", ");
+ Printf(proxy_method_types, ", ");
+ Printf(imcall_args, ", ");
+ }
+ Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else
+ Printv(imcall_args, ln, NIL);
+
+ /* Get the C# parameter type */
+ if ((tm = Getattr(p, "tmap:cstype"))) {
+ substituteClassname(pt, tm);
+ int flags = DOH_REPLACE_FIRST | DOH_REPLACE_ID_BEGIN | DOH_REPLACE_NOCOMMENT;
+ if (Replace(tm, "ref ", "", flags) || Replace(tm, "ref\t", "", flags)) {
+ Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm);
+ } else if (Replace(tm, "out ", "", flags) || Replace(tm, "out\t", "", flags)) {
+ Printf(proxy_method_types, "typeof(%s).MakeByRefType()", tm);
+ } else {
+ Printf(proxy_method_types, "typeof(%s)", tm);
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(ln);
+ Delete(arg);
+ Delete(c_decl);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* Finish off the inherited upcall's definition */
+
+ Printf(callback_def, "%s)", delegate_parms);
+ Printf(callback_def, " {\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("%s(%s)", symname, imcall_args);
+
+ if ((tm = Swig_typemap_lookup("csdirectorout", n, "", 0))) {
+ substituteClassname(returntype, tm);
+ Replaceall(tm, "$cscall", upcall);
+ if (!is_void)
+ Insert(tm, 0, "return ");
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+
+ // pre and post attribute support
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code && is_post_code)
+ Printf(callback_code, "%s\n try {\n %s;\n } finally {\n%s\n }\n", pre_code, tm, post_code);
+ else if (is_pre_code)
+ Printf(callback_code, "%s\n %s;\n", pre_code, tm);
+ else if (is_post_code)
+ Printf(callback_code, " try {\n %s;\n } finally {\n%s\n }\n", tm, post_code);
+ else
+ Printf(callback_code, " %s;\n", tm);
+ if (is_terminator_code)
+ Printv(callback_code, "\n", terminator_code, NIL);
+ }
+
+ Printf(callback_code, " }\n");
+ Delete(upcall);
+
+ if (!ignored_method) {
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "swig_callback%s(%s);\n", overloaded_name, jupcall_args);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ canThrow(n, "directorargout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Terminate wrapper code */
+ Printf(w->code, "}\n");
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!ignored_method)
+ Printv(director_delegate_callback, "\n", callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ if (!ignored_method) {
+ /* Emit the actual upcall through */
+ String *member_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
+ String *imclass_dmethod = NewStringf("SwigDirector_%s", member_name);
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name);
+ String *methid = Getattr(udata, "class_methodidx");
+ Setattr(n, "upcalldata", udata);
+ /*
+ Printf(stdout, "setting upcalldata, nodeType: %s %s::%s %p\n", nodeType(n), classname, Getattr(n, "name"), n);
+ */
+
+ Printf(director_callback_typedefs, " typedef %s (SWIGSTDCALL* SWIG_Callback%s_t)(", c_ret_type, methid);
+ Printf(director_callback_typedefs, "%s);\n", callback_typedef_parms);
+ Printf(director_callbacks, " SWIG_Callback%s_t swig_callback%s;\n", methid, overloaded_name);
+
+ Printf(director_delegate_definitions, " SwigDelegate%s_%s(%s);\n", classname, methid, delegate_parms);
+ Printf(director_delegate_instances, " private SwigDelegate%s_%s swigDelegate%s;\n", classname, methid, methid);
+ Printf(director_method_types, " private static global::System.Type[] swigMethodTypes%s = new global::System.Type[] { %s };\n", methid, proxy_method_types);
+ Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid);
+
+ Delete(imclass_dmethod);
+ Delete(member_name);
+ }
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(qualified_return);
+ Delete(declaration);
+ Delete(callback_typedef_parms);
+ Delete(delegate_parms);
+ Delete(proxy_method_types);
+ Delete(callback_def);
+ Delete(callback_code);
+ Delete(dirclassname);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *dirclassname = directorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ // TODO: Is this copy needed?
+ parms = CopyParmList(superparms);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+
+ 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(target);
+ Delete(call);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(parms);
+ Delete(dirclassname);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *dirclassname = directorClassName(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "%s::%s() : %s {", dirclassname, dirclassname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " %s();\n", dirclassname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(dirclassname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorInit()
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ Delete(none_comparison);
+ none_comparison = NewString(""); // not used
+
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ directorDeclaration(n);
+
+ Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
+ Printf(f_directors_h, "\npublic:\n");
+
+ /* Keep track of the director methods for this class */
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ director_callback_typedefs = NewString("");
+ director_callbacks = NewString("");
+ director_delegate_callback = NewString("");
+ director_delegate_definitions = NewString("");
+ director_delegate_instances = NewString("");
+ director_method_types = NewString("");
+ director_connect_parms = NewString("");
+
+ 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()
+ * ---------------------------------------------------------------------- */
+
+ int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *dirclassname = directorClassName(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
+ Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
+ Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
+ Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);
+ }
+
+ Printv(w->code, "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(dirclassname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ int i;
+ String *dirclassname = directorClassName(n);
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(director_callback_typedefs) > 0) {
+ Printf(f_directors_h, "\n%s", director_callback_typedefs);
+ }
+
+ Printf(f_directors_h, " void swig_connect_director(");
+
+ 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);
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+
+ Printf(f_directors_h, "SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->def, "SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->code, "swig_callback%s = callback%s;\n", overname, overname);
+ if (i != curr_class_dmethod - 1) {
+ Printf(f_directors_h, ", ");
+ Printf(w->def, ", ");
+ }
+ }
+
+ Printf(f_directors_h, ");\n");
+ Printf(w->def, ") {");
+
+
+ if (Len(director_callbacks) > 0) {
+ Printf(f_directors_h, "\nprivate:\n%s", director_callbacks);
+ }
+ Printf(f_directors_h, " void swig_init_callbacks();\n");
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n\n");
+
+ 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");
+ Printf(w->code, "swig_callback%s = 0;\n", overname);
+ }
+ Printf(w->code, "}");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(dirclassname);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* --------------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------------*/
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * directorDeclaration()
+ *
+ * Generate the director class's declaration
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *--------------------------------------------------------------------*/
+
+ void directorDeclaration(Node *n) {
+
+ String *base = Getattr(n, "classtype");
+ String *class_ctor = NewString("Swig::Director()");
+
+ String *dirclassname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, dirclassname);
+
+ Printf(declaration, " : public %s, public Swig::Director", base);
+
+ // Stash stuff for later.
+ Setattr(n, "director:decl", declaration);
+ Setattr(n, "director:ctor", class_ctor);
+
+ Delete(dirclassname);
+ }
+
+ /* ------------------------------------------------------------
+ * have_docstring()
+ *
+ * Check for Doxygen comments
+ *--------------------------------------------------------------------*/
+
+ bool have_docstring(Node *n) {
+ /* autodoc and docstring features not supported in C#
+ String *str = Getattr(n, "feature:docstring");
+
+ return ((str && Len(str) > 0)
+ || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"))
+ || (doxygen && doxygenTranslator->hasDocumentation(n))
+ );
+ */
+ return doxygen && doxygenTranslator->hasDocumentation(n);
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ *
+ * Get documentation comments, if any
+ *
+ * Return new documentation string to be deleted by caller (never NULL but
+ * may be empty if there is no docstring).
+ *--------------------------------------------------------------------*/
+
+ String *docstring(Node *n, const char *indent = "") {
+ String *docstr = NULL;
+
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ docstr = doxygenTranslator->getDocumentation(n, 0);
+ }
+
+ if (!docstr)
+ docstr = NewString("");
+
+ // If there is more than one line then make docstrings like this:
+ //
+ // This is line1
+ // And here is line2 followed by the rest of them
+ //
+ // otherwise, put it all on a single line
+ if (Strchr(docstr, '\n')) {
+ String *tmp = NewString("");
+ Append(tmp, indent_docstring(docstr, indent));
+ Delete(docstr);
+ docstr = tmp;
+ } else {
+ String *tmp = NewString(indent);
+ Append(tmp, "/// ");
+ Append(tmp, docstr);
+ Append(tmp, "\n");
+ Delete(docstr);
+ docstr = tmp;
+ }
+
+ return docstr;
+ }
+
+ /* ------------------------------------------------------------
+ * indent_docstring()
+ *
+ * Format (indent) a CSharp docstring.
+ * Remove leading whitespace from 'code' and re-indent using
+ * the indentation string in 'indent'.
+ * ------------------------------------------------------------ */
+
+ String *indent_docstring(const String *code, const char *indent) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+
+ Iterator si;
+
+ int truncate_characters_count = INT_MAX;
+ for (si = First(clist); si.item; si = Next(si)) {
+ const char *c = Char(si.item);
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (ch) {
+ // Found a line which isn't just whitespace
+ if (i < truncate_characters_count)
+ truncate_characters_count = i;
+ }
+ }
+
+ if (truncate_characters_count == INT_MAX)
+ truncate_characters_count = 0;
+
+ for (si = First(clist); si.item; si = Next(si)) {
+ const char *c = Char(si.item);
+
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (!ch) {
+ // Line is just whitespace - emit an empty line.
+ Printv(out, indent, "///", NIL);
+ Putc('\n', out);
+ continue;
+ }
+
+ Printv(out, indent, "/// ", c + truncate_characters_count, "\n", NIL);
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /*----------------------------------------------------------------------
+ * nestedClassesSupport()
+ *--------------------------------------------------------------------*/
+
+ NestedClassSupport nestedClassesSupport() const {
+ return NCS_Full;
+ }
+}; /* class CSHARP */
+
+/* -----------------------------------------------------------------------------
+ * swig_csharp() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_csharp() {
+ return new CSHARP();
+}
+extern "C" Language *swig_csharp(void) {
+ return new_swig_csharp();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+const char *CSHARP::usage = "\
+C# Options (available with -csharp)\n\
+ -dllimport <dl> - Override DllImport attribute name to <dl>\n\
+ -namespace <nm> - Generate wrappers into C# namespace <nm>\n\
+ -noproxy - Generate the low-level functional interface instead\n\
+ of proxy classes\n\
+ -oldvarnames - Old intermediary method names for variable wrappers\n\
+ -outfile <file> - Write all C# into a single <file> located in the output directory\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/d.cxx b/contrib/tools/swig/Source/Modules/d.cxx
new file mode 100644
index 00000000000..cf79ff58b7e
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/d.cxx
@@ -0,0 +1,4865 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * d.cxx
+ *
+ * D language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+// Hash type used for storing information about director callbacks for a class.
+typedef DOH UpcallData;
+
+class D : public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *private_string;
+ const String *protected_string;
+
+ /*
+ * Files and file sections containing C/C++ code.
+ */
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ List *filenames_list;
+
+ /*
+ * Command line-set modes of operation.
+ */
+ // Whether a single proxy D module is generated or classes and enums are
+ // written to their own files.
+ bool split_proxy_dmodule;
+
+ /*
+ * State variables which indicate what is being wrapped at the moment.
+ * This is probably not the most elegant way of handling state, but it has
+ * proven to work in the C# and Java modules.
+ */
+ // Indicates if wrapping a native function.
+ bool native_function_flag;
+
+ // Indicates if wrapping a static functions or member variables
+ bool static_flag;
+
+ // Indicates if wrapping a nonstatic member variable
+ bool variable_wrapper_flag;
+
+ // Indicates if wrapping a member variable/enum/const.
+ bool wrapping_member_flag;
+
+ // Indicates if wrapping a global variable.
+ bool global_variable_flag;
+
+ // Name of a variable being wrapped.
+ String *variable_name;
+
+ /*
+ * Variables temporarily holding the generated C++ code.
+ */
+ // C++ code for the generated wrapper functions for casts up the C++
+ // for inheritance hierarchies.
+ String *upcasts_code;
+
+ // Function pointer typedefs for handling director callbacks on the C++ side.
+ String *director_callback_typedefs;
+
+ // Variables for storing the function pointers to the director callbacks on
+ // the C++ side.
+ String *director_callback_pointers;
+
+ /*
+ * Names of generated D entities.
+ */
+ // The name of the D module containing the interface to the C wrapper.
+ String *im_dmodule_name;
+
+ // The fully qualified name of the wrap D module (package name included).
+ String *im_dmodule_fq_name;
+
+ // The name of the proxy module which exposes the (SWIG) module contents as a
+ // D module.
+ String *proxy_dmodule_name;
+
+ // The fully qualified name of the proxy D module.
+ String *proxy_dmodule_fq_name;
+
+ // Optional: Package the D modules are placed in (set via the -package
+ // command line option).
+ String *package;
+
+ // The directory the generated D module files are written to. Is constructed
+ // from the package path if a target package is set, points to the general
+ // output directory otherwise.
+ String *dmodule_directory;
+
+ // The name of the library which contains the C wrapper (used when generating
+ // the dynamic library loader). Can be overridden via the -wrapperlibrary
+ // command line flag.
+ String *wrap_library_name;
+
+ /*
+ * Variables temporarily holding the generated D code.
+ */
+ // Import statements written to the intermediary D module header set via
+ // %pragma(d) imdmoduleimports.
+ String *im_dmodule_imports;
+
+ // The code for the intermediary D module body.
+ String *im_dmodule_code;
+
+ // Import statements for all proxy modules (the main proxy module and, if in
+ // split proxy module mode, the proxy class modules) from
+ // %pragma(d) globalproxyimports.
+ String *global_proxy_imports;
+
+ // The D code for the main proxy modules. nspace_proxy_dmodules is a hash from
+ // the namespace name as key to an {"imports", "code"}. If the nspace feature
+ // is not active, only proxy_dmodule_imports and proxy_dmodule_code are used,
+ // which contain the code for the root proxy module.
+ //
+ // These variables should not be accessed directly but rather via the
+ // proxy{Imports, Code}Buffer)() helper functions which return the right
+ // buffer for a given namespace. If not in split proxy mode, they contain the
+ // whole proxy code.
+ String *proxy_dmodule_imports;
+ String *proxy_dmodule_code;
+ Hash *nspace_proxy_dmodules;
+
+ // The D code generated for the currently processed enum.
+ String *proxy_enum_code;
+
+ /*
+ * D data for the current proxy class.
+ *
+ * These strings are mainly used to temporarily accumulate code from the
+ * various member handling functions while a single class is processed and are
+ * no longer relevant once that class has been finished, i.e. after
+ * classHandler() has returned.
+ */
+ // The unqualified name of the current proxy class.
+ String *proxy_class_name;
+
+ // The name of the current proxy class, qualified with the name of the
+ // namespace it is in, if any.
+ String *proxy_class_qname;
+
+ // The import directives for the current proxy class. They are written to the
+ // same D module the proxy class is written to.
+ String *proxy_class_imports;
+
+ // Code for enumerations nested in the current proxy class. Is emitted earlier
+ // than the rest of the body to work around forward referencing-issues.
+ String *proxy_class_enums_code;
+
+ // The generated D code making up the body of the current proxy class.
+ String *proxy_class_body_code;
+
+ // D code which is emitted right after the proxy class.
+ String *proxy_class_epilogue_code;
+
+ // The full code for the current proxy class, including the epilogue.
+ String* proxy_class_code;
+
+ // Code generated at the begin of every D file
+ String *common_begin_code;
+
+ // Contains a D call to the function wrapping C++ the destructor of the
+ // current class (if there is a public C++ destructor).
+ String *destructor_call;
+
+ // D code for the director callbacks generated for the current class.
+ String *director_dcallbacks_code;
+
+ /*
+ * Code for dynamically loading the wrapper library on the D side.
+ */
+ // D code which is inserted into the im D module if dynamic linking is used.
+ String *wrapper_loader_code;
+
+ // The D code to bind a function pointer to a library symbol.
+ String *wrapper_loader_bind_command;
+
+ // The cumulated binding commands binding all the functions declared in the
+ // intermediary D module to the C/C++ library symbols.
+ String *wrapper_loader_bind_code;
+
+ /*
+ * Director data.
+ */
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+
+ /*
+ * SWIG types data.
+ */
+ // Collects information about encountered types SWIG does not know about (e.g.
+ // incomplete types). This is used later to generate type wrapper proxy
+ // classes for the unknown types.
+ Hash *unknown_types;
+
+
+public:
+ /* ---------------------------------------------------------------------------
+ * D::D()
+ * --------------------------------------------------------------------------- */
+ D():empty_string(NewString("")),
+ public_string(NewString("public")),
+ private_string(NewString("private")),
+ protected_string(NewString("protected")),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ filenames_list(NULL),
+ split_proxy_dmodule(false),
+ native_function_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ variable_name(NULL),
+ upcasts_code(NULL),
+ director_callback_typedefs(NULL),
+ director_callback_pointers(NULL),
+ im_dmodule_name(NULL),
+ im_dmodule_fq_name(NULL),
+ proxy_dmodule_name(NULL),
+ proxy_dmodule_fq_name(NULL),
+ package(NULL),
+ dmodule_directory(NULL),
+ wrap_library_name(NULL),
+ im_dmodule_imports(NULL),
+ im_dmodule_code(NULL),
+ global_proxy_imports(NULL),
+ proxy_dmodule_imports(NULL),
+ proxy_dmodule_code(NULL),
+ nspace_proxy_dmodules(NULL),
+ proxy_enum_code(NULL),
+ proxy_class_name(NULL),
+ proxy_class_qname(NULL),
+ proxy_class_imports(NULL),
+ proxy_class_enums_code(NULL),
+ proxy_class_body_code(NULL),
+ proxy_class_epilogue_code(NULL),
+ proxy_class_code(NULL),
+ common_begin_code(NULL),
+ destructor_call(NULL),
+ director_dcallbacks_code(NULL),
+ wrapper_loader_code(NULL),
+ wrapper_loader_bind_command(NULL),
+ wrapper_loader_bind_code(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ first_class_dmethod(0),
+ curr_class_dmethod(0),
+ unknown_types(NULL) {
+
+ // For now, multiple inheritance with directors is not possible. It should be
+ // easy to implement though.
+ director_multiple_inheritance = 0;
+ directorLanguage();
+
+ // Not used:
+ Delete(none_comparison);
+ none_comparison = NewString("");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::main()
+ * --------------------------------------------------------------------------- */
+ virtual void main(int argc, char *argv[]) {
+ SWIG_library_directory("d");
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if ((strcmp(argv[i], "-d2") == 0)) {
+ /* Keep for backward compatible only */
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-wrapperlibrary") == 0) {
+ if (argv[i + 1]) {
+ wrap_library_name = NewString("");
+ Printf(wrap_library_name, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString("");
+ Printf(package, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-splitproxy") == 0)) {
+ Swig_mark_arg(i);
+ split_proxy_dmodule = true;
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGD 1", 0);
+
+ // Also make the target D version available as preprocessor symbol for
+ // use in our library files.
+ Preprocessor_define("SWIG_D_VERSION 2", 0);
+
+ SWIG_config_file("d.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::top()
+ * --------------------------------------------------------------------------- */
+ virtual int top(Node *n) {
+ // Get any options set in the module directive
+ Node *module = Getattr(n, "module");
+ Node *optionsnode = Getattr(module, "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "imdmodulename")) {
+ im_dmodule_name = Copy(Getattr(optionsnode, "imdmodulename"));
+ }
+
+ if (Getattr(optionsnode, "directors")) {
+ // Check if directors are enabled for this module. Note: This is a
+ // "master switch", if it is not set, not director code will be emitted
+ // at all. %feature("director") statements are also required to enable
+ // directors for individual classes or methods.
+ //
+ // Use the »directors« attributte of the %module directive to enable
+ // director generation (e.g. »%module(directors="1") modulename«).
+ allow_directors();
+ }
+
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+
+ common_begin_code = Getattr(optionsnode, "dbegin");
+ if (common_begin_code)
+ Printf(common_begin_code, "\n");
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (Swig_directors_enabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ unknown_types = NewHash();
+ filenames_list = NewList();
+
+ // Make the package name and the resulting module output path.
+ if (package) {
+ // Append a dot so we can prepend the package variable directly to the
+ // module names in the rest of the code.
+ Printv(package, ".", NIL);
+ } else {
+ // Write the generated D modules to the »root« package by default.
+ package = NewString("");
+ }
+
+ dmodule_directory = Copy(SWIG_output_directory());
+ if (Len(package) > 0) {
+ String *package_directory = Copy(package);
+ Replaceall(package_directory, ".", SWIG_FILE_DELIMITER);
+ Printv(dmodule_directory, package_directory, NIL);
+ Delete(package_directory);
+ }
+
+ // Make the wrap and proxy D module names.
+ // The wrap module name can be set in the module directive.
+ if (!im_dmodule_name) {
+ im_dmodule_name = NewStringf("%s_im", Getattr(n, "name"));
+ }
+ im_dmodule_fq_name = NewStringf("%s%s", package, im_dmodule_name);
+ proxy_dmodule_name = Copy(Getattr(n, "name"));
+ proxy_dmodule_fq_name = NewStringf("%s%s", package, proxy_dmodule_name);
+
+ im_dmodule_code = NewString("");
+ proxy_class_imports = NewString("");
+ proxy_class_enums_code = NewString("");
+ proxy_class_body_code = NewString("");
+ proxy_class_epilogue_code = NewString("");
+ proxy_class_code = NewString("");
+ destructor_call = NewString("");
+ proxy_dmodule_code = NewString("");
+ proxy_dmodule_imports = NewString("");
+ nspace_proxy_dmodules = NewHash();
+ im_dmodule_imports = NewString("");
+ upcasts_code = NewString("");
+ global_proxy_imports = NewString("");
+ wrapper_loader_code = NewString("");
+ wrapper_loader_bind_command = NewString("");
+ wrapper_loader_bind_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+
+ // By default, expect the dynamically loaded wrapper library to be named
+ // [lib]<module>_wrap[.so/.dll].
+ if (!wrap_library_name)
+ wrap_library_name = NewStringf("%s_wrap", Getattr(n, "name"));
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "D");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", proxy_dmodule_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", proxy_dmodule_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ Printf(f_runtime, "\n");
+
+ Swig_name_register("wrapper", "D_%f");
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ // Emit all the wrapper code.
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (before %header section).
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ // Generate the wrap D module.
+ // TODO: Add support for »static« linking.
+ {
+ String *filen = NewStringf("%s%s.d", dmodule_directory, im_dmodule_name);
+ File *im_d_file = NewFile(filen, "w", SWIG_output_files());
+ if (!im_d_file) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the intermediary class file.
+ emitBanner(im_d_file);
+
+ Printf(im_d_file, "module %s;\n", im_dmodule_fq_name);
+
+ Printv(im_d_file, im_dmodule_imports, "\n", NIL);
+
+ Replaceall(wrapper_loader_code, "$wraplibrary", wrap_library_name);
+ Replaceall(wrapper_loader_code, "$wrapperloaderbindcode", wrapper_loader_bind_code);
+ Replaceall(wrapper_loader_code, "$module", proxy_dmodule_name);
+ Printf(im_d_file, "%s\n", wrapper_loader_code);
+
+ // Add the wrapper function declarations.
+ replaceModuleVariables(im_dmodule_code);
+ Printv(im_d_file, im_dmodule_code, NIL);
+
+ Delete(im_d_file);
+ }
+
+ // Generate the main D proxy module.
+ {
+ String *filen = NewStringf("%s%s.d", dmodule_directory, proxy_dmodule_name);
+ File *proxy_d_file = NewFile(filen, "w", SWIG_output_files());
+ if (!proxy_d_file) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(proxy_d_file);
+
+ Printf(proxy_d_file, "module %s;\n", proxy_dmodule_fq_name);
+ Printf(proxy_d_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ Printv(proxy_d_file, global_proxy_imports, NIL);
+ Printv(proxy_d_file, proxy_dmodule_imports, NIL);
+ Printv(proxy_d_file, "\n", NIL);
+
+ // Write a D type wrapper class for each SWIG type to the proxy module code.
+ for (Iterator swig_type = First(unknown_types); swig_type.key; swig_type = Next(swig_type)) {
+ writeTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Add the proxy functions (and classes, if they are not written to a separate file).
+ replaceModuleVariables(proxy_dmodule_code);
+ Printv(proxy_d_file, proxy_dmodule_code, NIL);
+
+ Delete(proxy_d_file);
+ }
+
+ // Generate the additional proxy modules for nspace support.
+ for (Iterator it = First(nspace_proxy_dmodules); it.key; it = Next(it)) {
+ String *module_name = createLastNamespaceName(it.key);
+
+ String *filename = NewStringf("%s%s.d", outputDirectory(it.key), module_name);
+ File *file = NewFile(filename, "w", SWIG_output_files());
+ if (!file) {
+ FileErrorDisplay(filename);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(filename);
+
+ emitBanner(file);
+
+ Printf(file, "module %s%s.%s;\n", package, it.key, module_name);
+ Printf(file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ Printv(file, global_proxy_imports, NIL);
+ Printv(file, Getattr(it.item, "imports"), NIL);
+ Printv(file, "\n", NIL);
+
+ String *code = Getattr(it.item, "code");
+ replaceModuleVariables(code);
+ Printv(file, code, NIL);
+
+ Delete(file);
+ Delete(module_name);
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(unknown_types);
+ unknown_types = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(im_dmodule_name);
+ im_dmodule_name = NULL;
+ Delete(im_dmodule_fq_name);
+ im_dmodule_fq_name = NULL;
+ Delete(im_dmodule_code);
+ im_dmodule_code = NULL;
+ Delete(proxy_class_imports);
+ proxy_class_imports = NULL;
+ Delete(proxy_class_enums_code);
+ proxy_class_enums_code = NULL;
+ Delete(proxy_class_body_code);
+ proxy_class_body_code = NULL;
+ Delete(proxy_class_epilogue_code);
+ proxy_class_epilogue_code = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(destructor_call);
+ destructor_call = NULL;
+ Delete(proxy_dmodule_name);
+ proxy_dmodule_name = NULL;
+ Delete(proxy_dmodule_fq_name);
+ proxy_dmodule_fq_name = NULL;
+ Delete(proxy_dmodule_code);
+ proxy_dmodule_code = NULL;
+ Delete(proxy_dmodule_imports);
+ proxy_dmodule_imports = NULL;
+ Delete(nspace_proxy_dmodules);
+ nspace_proxy_dmodules = NULL;
+ Delete(im_dmodule_imports);
+ im_dmodule_imports = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(global_proxy_imports);
+ global_proxy_imports = NULL;
+ Delete(wrapper_loader_code);
+ wrapper_loader_code = NULL;
+ Delete(wrapper_loader_bind_code);
+ wrapper_loader_bind_code = NULL;
+ Delete(wrapper_loader_bind_command);
+ wrapper_loader_bind_command = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ Delete(package);
+ package = NULL;
+ Delete(dmodule_directory);
+ dmodule_directory = NULL;
+ n_dmethods = 0;
+
+ // Merge all the generated C/C++ code and close the output files.
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::insertDirective()
+ * --------------------------------------------------------------------------- */
+ virtual int insertDirective(Node *n) {
+ int ret = SWIG_OK;
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ replaceModuleVariables(code);
+
+ if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
+ if (proxy_class_body_code) {
+ Swig_typemap_replace_embedded_typemap(code, n);
+ Printv(proxy_class_body_code, code, NIL);
+ }
+ } else {
+ ret = Language::insertDirective(n);
+ }
+ return ret;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::pragmaDirective()
+ *
+ * Valid Pragmas:
+ * imdmodulecode - text (D code) is copied verbatim to the wrap module
+ * imdmoduleimports - import statements for the im D module
+ *
+ * proxydmodulecode - text (D code) is copied verbatim to the proxy module
+ * (the main proxy module if in split proxy mode).
+ * globalproxyimports - import statements inserted into _all_ proxy modules.
+ *
+ * wrapperloadercode - D code for loading the wrapper library (is copied to
+ * the im D module).
+ * wrapperloaderbindcommand - D code for binding a symbol from the wrapper
+ * library to the declaration in the im D module.
+ * --------------------------------------------------------------------------- */
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "d") == 0) {
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "imdmodulecode") == 0) {
+ Printf(im_dmodule_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "imdmoduleimports") == 0) {
+ replaceImportTypeMacros(strvalue);
+ Chop(strvalue);
+ Printf(im_dmodule_imports, "%s\n", strvalue);
+ } else if (Strcmp(code, "proxydmodulecode") == 0) {
+ Printf(proxyCodeBuffer(0), "%s\n", strvalue);
+ } else if (Strcmp(code, "globalproxyimports") == 0) {
+ replaceImportTypeMacros(strvalue);
+ Chop(strvalue);
+ Printf(global_proxy_imports, "%s\n", strvalue);
+ } else if (Strcmp(code, "wrapperloadercode") == 0) {
+ Delete(wrapper_loader_code);
+ wrapper_loader_code = Copy(strvalue);
+ } else if (Strcmp(code, "wrapperloaderbindcommand") == 0) {
+ Delete(wrapper_loader_bind_command);
+ wrapper_loader_bind_command = Copy(strvalue);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::enumDeclaration()
+ *
+ * Wraps C/C++ enums as D enums.
+ * --------------------------------------------------------------------------- */
+ virtual int enumDeclaration(Node *n) {
+ if (ImportMode)
+ return SWIG_OK;
+
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ proxy_enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ // Emit the enum declaration.
+ if (typemap_lookup_type) {
+
+ // Enum base (underlying enum type)
+ Node *attributes = NewHash();
+ const String *pure_baseclass = lookupCodeTypemap(n, "dbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:dbase:replace") ? true : false;
+ Delete(attributes);
+
+ const String *baseclass = NULL;
+ if (!purebase_replace) {
+ String *underlying_enum_type = Getattr(n, "enumbase");
+ if (underlying_enum_type) {
+ baseclass = lookupCodeTypemap(n, "dtype", underlying_enum_type, WARN_D_TYPEMAP_DTYPE_UNDEF);
+ }
+ }
+
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, enum base %s ignored. Multiple enum bases is not supported in D enums. "
+ "Perhaps you need the 'replace' attribute in the dbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ const String *enummodifiers = lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
+ Printv(proxy_enum_code, "\n", enummodifiers, " ", symname, *Char(wanted_base) ? " : " : "", wanted_base, " {\n", NIL);
+ } else {
+ // Handle anonymous enums.
+ Printv(proxy_enum_code, "\nenum {\n", NIL);
+ }
+
+ // Emit each enum item.
+ Language::enumDeclaration(n);
+
+ if (GetFlag(n, "nonempty")) {
+ // Finish the enum.
+ if (typemap_lookup_type) {
+ Printv(proxy_enum_code,
+ lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), // Extra D code
+ "\n}\n", NIL);
+ } else {
+ // Handle anonymous enums.
+ Printv(proxy_enum_code, "\n}\n", NIL);
+ }
+ Replaceall(proxy_enum_code, "$dclassname", symname);
+ } else {
+ // D enum declarations must have at least one member to be legal, so emit
+ // an alias to int instead (their ctype/imtype is always int).
+ Delete(proxy_enum_code);
+ proxy_enum_code = NewStringf("\nalias int %s;\n", symname);
+ }
+
+ const String* imports =
+ lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
+ String* imports_trimmed;
+ if (Len(imports) > 0) {
+ imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(imports_trimmed, "\n", NIL);
+ } else {
+ imports_trimmed = NewString("");
+ }
+
+ if (is_wrapping_class()) {
+ // Enums defined within the C++ class are written into the proxy
+ // class.
+ Printv(proxy_class_imports, imports_trimmed, NIL);
+ Printv(proxy_class_enums_code, proxy_enum_code, NIL);
+ } else {
+ // Write non-anonymous enums to their own file if in split proxy module
+ // mode.
+ if (split_proxy_dmodule && typemap_lookup_type) {
+ assertClassNameValidity(proxy_class_name);
+
+ String *nspace = Getattr(n, "sym:nspace");
+ String *output_directory = outputDirectory(nspace);
+ String *filename = NewStringf("%s%s.d", output_directory, symname);
+ Delete(output_directory);
+
+ File *class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ if (nspace) {
+ Printf(class_file, "module %s%s.%s;\n", package, nspace, symname);
+ } else {
+ Printf(class_file, "module %s%s;\n", package, symname);
+ }
+ Printv(class_file, imports_trimmed, NIL);
+
+ Printv(class_file, proxy_enum_code, NIL);
+
+ Delete(class_file);
+ } else {
+ String *nspace = Getattr(n, "sym:nspace");
+ Printv(proxyImportsBuffer(nspace), imports, NIL);
+ Printv(proxyCodeBuffer(nspace), proxy_enum_code, NIL);
+ }
+ }
+
+ Delete(imports_trimmed);
+
+ Delete(proxy_enum_code);
+ proxy_enum_code = NULL;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::enumvalueDeclaration()
+ * --------------------------------------------------------------------------- */
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ String *tmpValue;
+
+ // Strange hack from parent method.
+ // RESEARCH: What is this doing?
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ {
+ String *numval = Getattr(n, "enumnumval");
+ if (numval) Setattr(n, "enumvalue", numval);
+ }
+
+ // Emit the enum item.
+ {
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(proxy_enum_code, ",\n");
+
+ Printf(proxy_enum_code, " %s", Getattr(n, "sym:name"));
+
+ // Check for the %dconstvalue feature
+ String *value = Getattr(n, "feature:d:constvalue");
+
+ // Note that in D, enum values must be compile-time constants. Thus,
+ // %dmanifestconst(0) (getting the enum values at runtime) is not supported.
+ value = value ? value : Getattr(n, "enumvalue");
+ if (value) {
+ Printf(proxy_enum_code, " = %s", value);
+ }
+
+ // Keep track that the currently processed enum has at least one value.
+ SetFlag(parent, "nonempty");
+ }
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::memberfunctionHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name =
+ Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ Setattr(n, "imfuncname", intermediary_function_name);
+
+ String *proxy_func_name = Getattr(n, "sym:name");
+ Setattr(n, "proxyfuncname", proxy_func_name);
+ if (split_proxy_dmodule &&
+ Len(Getattr(n, "parms")) == 0 &&
+ Strncmp(proxy_func_name, package, Len(proxy_func_name)) == 0) {
+ // If we are in split proxy mode and the function is named like the
+ // target package, the D compiler is unable to resolve the ambiguity
+ // between the package name and an argument-less function call.
+ // TODO: This might occur with nspace as well, augment the check.
+ Swig_warning(WARN_D_NAME_COLLISION, input_file, line_number,
+ "%s::%s might collide with the package name, consider using %%rename to resolve the ambiguity.\n",
+ proxy_class_name, proxy_func_name);
+ }
+
+ writeProxyClassFunction(n);
+
+ Delete(overloaded_name);
+
+ // For each function, look if we have to alias in the parent class function
+ // for the overload resolution process to work as expected from C++
+ // (http://www.digitalmars.com/d/2.0/function.html#function-inheritance).
+ // For multiple overloads, only emit the alias directive once (for the
+ // last method, »sym:nextSibling« is null then).
+ // Smart pointer classes do not mirror the inheritance hierarchy of the
+ // underlying types, so aliasing the base class methods in is not required
+ // for them.
+ // DMD BUG: We have to emit the alias after the last function because
+ // taking a delegate in the overload checking code fails otherwise
+ // (http://d.puremagic.com/issues/show_bug.cgi?id=4860).
+ if (!Getattr(n, "sym:nextSibling") && !is_smart_pointer() &&
+ !areAllOverloadsOverridden(n)) {
+ String *name = Getattr(n, "sym:name");
+ Printf(proxy_class_body_code, "\nalias $dbaseclass.%s %s;\n", name, name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::staticmemberfunctionHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int staticmemberfunctionHandler(Node *n) {
+ static_flag = true;
+
+ Language::staticmemberfunctionHandler(n);
+
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name =
+ Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ writeProxyClassFunction(n);
+ Delete(overloaded_name);
+
+ static_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::globalvariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int globalvariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+
+ return ret;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::membervariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int membervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::staticmembervariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int staticmembervariableHandler(Node *n) {
+ if (GetFlag(n, "feature:d:manifestconst") != 1) {
+ Delattr(n, "value");
+ }
+
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::memberconstantHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::constructorHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloadedprocess in D.
+ if (Getattr(n, "overload:ignore")) {
+ return SWIG_OK;
+ }
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *proxy_constructor_code = NewString("");
+ int i;
+
+ // Holds code for the constructor helper method generated only when the din
+ // typemap has code in the pre or post attributes.
+ String *helper_code = NewString("");
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ NewString("");
+
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
+ String *imcall = NewString("");
+
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ // Typemaps were attached earlier to the node, get the return type of the
+ // call to the C++ constructor wrapper.
+ const String *wrapper_return_type = lookupDTypemap(n, "imtype", true);
+
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type in
+ // the typemap itself.
+ wrapper_return_type = imtypeout;
+ }
+
+ Printf(proxy_constructor_code, "\n%s this(", methodmods);
+ Printf(helper_code, "static private %s SwigConstruct%s(",
+ wrapper_return_type, proxy_class_name);
+
+ Printv(imcall, im_dmodule_fq_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ Parm *p = l;
+ for (i = 0; p; i++) {
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ // Skip ignored varargs.
+ p = nextSibling(p);
+ continue;
+ }
+
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ // Skip ignored parameters.
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ // Get the D parameter type.
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+ String *parmtype = 0;
+
+ // Get the D code to convert the parameter value to the type used in the
+ // intermediary D module.
+ if ((tm = lookupDTypemap(p, "din"))) {
+ Replaceall(tm, "$dinput", arg);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ parmtype = Getattr(p, "tmap:din:parmtype");
+ if (parmtype)
+ Replaceall(parmtype, "$dinput", arg);
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(proxy_constructor_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ Printf(proxy_constructor_code, "%s %s", param_type, arg);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", parmtype ? parmtype : arg);
+ ++gencomma;
+
+ Delete(parmtype);
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(proxy_constructor_code, ")");
+ Printf(helper_code, ")");
+
+ // Insert the dconstructor typemap (replacing $directorconnect as needed).
+ Hash *attributes = NewHash();
+ String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
+ String *construct_tm = Copy(lookupCodeTypemap(n, "dconstructor",
+ typemap_lookup_type, WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes));
+ if (construct_tm) {
+ const bool use_director = (parentNode(n) && Swig_directorclass(n));
+ if (!use_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:dconstructor:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_D_NO_DIRECTORCONNECT_ATTR, input_file, line_number,
+ "\"directorconnect\" attribute missing in %s \"dconstructor\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(proxy_constructor_code, " ", construct_tm, NIL);
+ }
+
+ replaceExcode(n, proxy_constructor_code, "dconstructor", attributes);
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ if (is_terminator_code) {
+ Printv(helper_code, "\n", terminator_code, NIL);
+ }
+ Printf(helper_code, "\n}\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)",
+ proxy_class_name, proxy_class_name, helper_args);
+ Replaceall(proxy_constructor_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(proxy_constructor_code, "$imcall", imcall);
+ }
+
+ Printv(proxy_class_body_code, proxy_constructor_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::destructorHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(getNSpace(),symname), "(cast(void*)swigCPtr)", NIL);
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ if (methodmods)
+ Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int classHandler(Node *n) {
+ String *nspace = getNSpace();
+ File *class_file = NULL;
+
+ proxy_class_name = Copy(Getattr(n, "sym:name"));
+ if (nspace) {
+ proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
+ } else {
+ proxy_class_qname = Copy(proxy_class_name);
+ }
+
+ if (!addSymbol(proxy_class_name, n, nspace)) {
+ return SWIG_ERROR;
+ }
+
+ assertClassNameValidity(proxy_class_name);
+
+ if (split_proxy_dmodule) {
+ String *output_directory = outputDirectory(nspace);
+ String *filename = NewStringf("%s%s.d", output_directory, proxy_class_name);
+ class_file = NewFile(filename, "w", SWIG_output_files());
+ Delete(output_directory);
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ if (nspace) {
+ Printf(class_file, "module %s%s.%s;\n", package, nspace, proxy_class_name);
+ } else {
+ Printf(class_file, "module %s%s;\n", package, proxy_class_name);
+ }
+ Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ }
+
+ Clear(proxy_class_enums_code);
+ Clear(proxy_class_body_code);
+ Clear(proxy_class_epilogue_code);
+ Clear(proxy_class_code);
+ Clear(destructor_call);
+
+
+ // Traverse the tree for this class, using the *Handler()s to generate code
+ // to the proxy_class_* variables.
+ Language::classHandler(n);
+
+ // This function write super methods in proxy_class_body_code
+ writeDirectorSuperFunctions(n);
+
+ writeProxyClassAndUpcasts(n);
+ writeDirectorConnectWrapper(n);
+
+ Replaceall(proxy_class_code, "$dclassname", proxy_class_name);
+
+ String *dclazzname = Swig_name_member(getNSpace(), proxy_class_name, "");
+ Replaceall(proxy_class_code, "$dclazzname", dclazzname);
+ Delete(dclazzname);
+
+ if (split_proxy_dmodule) {
+ Printv(class_file, global_proxy_imports, NIL);
+ Printv(class_file, proxy_class_imports, NIL);
+
+ replaceModuleVariables(proxy_class_code);
+ Printv(class_file, proxy_class_code, NIL);
+
+ Delete(class_file);
+ } else {
+ Printv(proxyImportsBuffer(getNSpace()), proxy_class_imports, NIL);
+ Printv(proxyCodeBuffer(getNSpace()), proxy_class_code, NIL);
+ }
+
+ Clear(proxy_class_imports);
+ Delete(proxy_class_qname);
+ proxy_class_qname = NULL;
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::constantWrapper()
+ *
+ * Used for wrapping constants declared by #define or %constant and also for
+ * (primitive) static member constants initialised inline.
+ *
+ * If the %dmanifestconst feature is used, the C/C++ constant value is used to
+ * initialize a D »const«. If not, a »getter« method is generated which
+ * retrieves the value via a call to the C wrapper. However, if there is a
+ * %dconstvalue specified, it overrides all other settings.
+ * --------------------------------------------------------------------------- */
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+
+ // The %dmanifestconst feature determines if a D manifest constant
+ // (const/enum) or a getter function is created.
+ if (GetFlag(n, "feature:d:manifestconst") != 1) {
+ // Default constant handling will work with any type of C constant. It
+ // generates a getter function (which is the same as a read only property
+ // in D) which retrieves the value via by calling the C wrapper.
+ // Note that this is only called for global constants, static member
+ // constants are already handled in staticmemberfunctionHandler().
+
+ Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:dtype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:dtype:outattributes", NIL);
+
+ SetFlag(n, "feature:immutable");
+ int result = globalvariableHandler(n);
+
+ Swig_restore(n);
+ return result;
+ }
+
+ String *constants_code = NewString("");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+
+ // Attach the non-standard typemaps to the parameter list.
+ Swig_typemap_attach_parms("dtype", l, NULL);
+
+ // Get D return type.
+ String *return_type = getOutDtype(n);
+ if (!return_type) {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ return_type = NewString("");
+ }
+
+ const String *itemname = wrapping_member_flag ? variable_name : symname;
+
+ String *attributes = Getattr(n, "feature:d:methodmodifiers");
+ if (attributes) {
+ attributes = Copy(attributes);
+ } else {
+ attributes = Copy(is_public(n) ? public_string : protected_string);
+ }
+
+ Printf(constants_code, "\n%s enum %s %s = ", attributes, return_type, itemname);
+ Delete(attributes);
+
+ // Retrieve the override value set via %dconstvalue, if any.
+ String *override_value = Getattr(n, "feature:d:constvalue");
+ if (override_value) {
+ Printf(constants_code, "%s;\n", override_value);
+ } else {
+ // Just take the value from the C definition and hope it compiles in D.
+ if (Getattr(n, "wrappedasconstant")) {
+ Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ } else {
+ Printf(constants_code, "%s;\n", Getattr(n, "value"));
+ }
+ }
+
+ // Emit the generated code to appropriate place.
+ if (wrapping_member_flag) {
+ Printv(proxy_class_body_code, constants_code, NIL);
+ } else {
+ Printv(proxyCodeBuffer(getNSpace()), constants_code, NIL);
+ }
+
+ // Cleanup.
+ Delete(return_type);
+ Delete(constants_code);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::functionWrapper()
+ *
+ * Generates the C wrapper code for a function and the corresponding
+ * declaration in the wrap D module.
+ * --------------------------------------------------------------------------- */
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ int num_arguments = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(Getattr(n, "sym:name"), n))
+ return SWIG_ERROR;
+ }
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *wname = Swig_name_wrapper(overloaded_name);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("ctype", l, f);
+ Swig_typemap_attach_parms("imtype", l, f);
+
+ /* Get return types */
+ if ((tm = lookupDTypemap(n, "ctype"))) {
+ String *ctypeout = Getattr(n, "tmap:ctype:out");
+ if (ctypeout) {
+ // The type in the ctype typemap's out attribute overrides the type in
+ // the typemap itself.
+ tm = ctypeout;
+ }
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ if ((tm = lookupDTypemap(n, "imtype"))) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type in
+ // the typemap itself.
+ tm = imtypeout;
+ }
+ Printf(im_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ is_void_return = (Cmp(c_return_type, "void") == 0);
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
+
+ Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in D
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in D and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore")) {
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+
+ // Collect the parameter list for the intermediary D module declaration of
+ // the generated wrapper function.
+ String *im_dmodule_parameters = NewString("(");
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ int gencomma = 0;
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the ctype types of the parameter */
+ if ((tm = lookupDTypemap(p, "ctype", true))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = lookupDTypemap(p, "imtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
+ Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(im_dmodule_parameters, ", ");
+ Printf(im_dmodule_parameters, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
+
+ gencomma = 1;
+
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ canThrow(n, "in", p);
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->code, "%s\n", tm);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ }
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ canThrow(n, "check", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ canThrow(n, "freearg", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ canThrow(n, "argout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Look for usage of throws typemap and the canthrow flag
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ canThrow(n, "throws", p);
+ }
+ }
+ }
+
+ String *null_attribute = 0;
+ // Now write code to make the function call
+ if (!native_function_flag) {
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ canThrow(n, "out", n);
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ null_attribute = Getattr(n, "tmap:out:null");
+ if (Len(tm))
+ Printf(f->code, "\n");
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, returntype, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "newfree", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ canThrow(n, "ret", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ // Complete D im parameter list and emit the declaration/binding code.
+ Printv(im_dmodule_parameters, ")", NIL);
+ writeImDModuleFunction(overloaded_name, im_return_type,
+ im_dmodule_parameters, wname);
+ Delete(im_dmodule_parameters);
+
+ // Finish C function header.
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ Replaceall(f->code, "$isvoid", is_void_return ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
+ Setattr(n, "d:canthrow", "1");
+ }
+
+ if (!null_attribute)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", null_attribute);
+
+ /* Dump the function out */
+ if (!native_function_flag) {
+ Wrapper_print(f, f_wrappers);
+
+ // Handle %exception which sets the canthrow attribute.
+ if (Getattr(n, "feature:except:canthrow")) {
+ Setattr(n, "d:canthrow", "1");
+ }
+
+ // A very simple check (it is not foolproof) to assist typemap writers
+ // with setting the correct features when the want to throw D exceptions
+ // from C++ code. It checks for the common methods which set
+ // a pending D exception and issues a warning if one of them has been found
+ // in the typemap, but the »canthrow« attribute/feature is not set.
+ if (!Getattr(n, "d:canthrow")) {
+ if (Strstr(f->code, "SWIG_exception")) {
+ Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
+ "C code contains a call to SWIG_exception and D code does not handle pending exceptions via the canthrow attribute.\n");
+ } else if (Strstr(f->code, "SWIG_DSetPendingException")) {
+ Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
+ "C code contains a call to a SWIG_DSetPendingException method and D code does not handle pending exceptions via the canthrow attribute.\n");
+ }
+ }
+ }
+
+ // If we are not processing an enum or constant, and we were not generating
+ // a wrapper function which will be accessed via a proxy class, write a
+ // function to the proxy D module.
+ if (!is_wrapping_class()) {
+ writeProxyDModuleFunction(n);
+ }
+
+ // If we are processing a public member variable, write the property-style
+ // member function to the proxy class.
+ if (wrapping_member_flag) {
+ Setattr(n, "proxyfuncname", variable_name);
+ Setattr(n, "imfuncname", symname);
+
+ writeProxyClassFunction(n);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::nativeWrapper()
+ * --------------------------------------------------------------------------- */
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirector()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirector(Node *n) {
+ String *nspace = Getattr(n, "sym:nspace");
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+ if (nspace) {
+ proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
+ } else {
+ proxy_class_qname = Copy(proxy_class_name);
+ }
+
+ int success = Language::classDirector(n);
+
+ Delete(proxy_class_qname);
+ proxy_class_qname = NULL;
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+
+ return success;
+ }
+
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorInit()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorInit(Node *n) {
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ // Write C++ director class declaration, for example:
+ // class SwigDirector_myclass : public myclass, public Swig::Director {
+ String *classname = Swig_class_name(n);
+ String *directorname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, directorname);
+ const String *base = Getattr(n, "classtype");
+
+ Printf(f_directors_h,
+ "%s : public %s, public Swig::Director {\n", declaration, base);
+ Printf(f_directors_h, "\npublic:\n");
+
+ Delete(declaration);
+ Delete(directorname);
+ Delete(classname);
+
+ // Stash for later.
+ Setattr(n, "director:ctor", NewString("Swig::Director()"));
+
+ // Keep track of the director methods for this class.
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ director_callback_typedefs = NewString("");
+ director_callback_pointers = NewString("");
+ director_dcallbacks_code = NewString("");
+
+ return Language::classDirectorInit(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying D object.
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *overloaded_name = 0;
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = 0;
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = directorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ SwigType *c_ret_type = NULL;
+ String *dcallback_call_args = NewString("");
+ String *callback_typedef_parms = NewString("");
+ String *delegate_parms = NewString("");
+ String *proxy_method_param_list = NewString("");
+ String *proxy_callback_return_type = NewString("");
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ if (!ignored_method)
+ overloaded_name = getOverloadedName(n);
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a D exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ SwigType *noref_type = SwigType_del_reference(Copy(returntype));
+ String *noref_ltype = SwigType_lstr(noref_type, 0);
+ String *return_ltype = SwigType_lstr(returntype, 0);
+
+ Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
+ Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
+ Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
+ Printf(w->code, "c_result = &result_default;\n");
+ Delete(return_ltype);
+ Delete(noref_ltype);
+ Delete(noref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ /* Create the intermediate class wrapper */
+ tm = lookupDTypemap(n, "imtype");
+ if (tm) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type
+ // in the typemap.
+ tm = imtypeout;
+ }
+ Printf(callback_def, "\nprivate extern(C) %s swigDirectorCallback_%s_%s(void* dObject", tm, classname, overloaded_name);
+ Printv(proxy_callback_return_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number,
+ "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ if ((c_ret_type = Swig_typemap_lookup("ctype", n, "", 0))) {
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Swig_director_parms_fixup(l);
+
+ // Attach the standard typemaps.
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("ctype", l, 0);
+ Swig_typemap_attach_parms("imtype", l, 0);
+ Swig_typemap_attach_parms("dtype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("ddirectorin", l, 0);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ // Preamble code.
+ if (!ignored_method)
+ Printf(w->code, "if (!swig_callback_%s) {\n", overloaded_name);
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ else if (!ignored_method)
+ Printf(w->code, "return;\n");
+ }
+
+ if (!ignored_method)
+ Printf(w->code, "} else {\n");
+
+ // Go through argument list.
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ // Add each parameter to the D callback invocation arguments.
+ Printf(dcallback_call_args, ", %s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = lookupDTypemap(p, "ctype", true))) {
+ String *ctypeout = Getattr(p, "tmap:ctype:out");
+ if (ctypeout) {
+ // The type in the ctype typemap's out attribute overrides the type
+ // in the typemap itself.
+ c_param_type = ctypeout;
+ }
+ // ctype default assignment
+ const String *ctypedef = Getattr(p, "tmap:ctype:default");
+ String *ctypeassign;
+ if (ctypedef) {
+ ctypeassign = Copy(ctypedef);
+ } else if (SwigType_ispointer(pt) || SwigType_isreference(pt)) {
+ ctypeassign = NewString("= 0");
+ } else {
+ ctypeassign = NewString("");
+ }
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, ctypeassign, NIL);
+ Delete(ctypeassign);
+
+ /* Add input marshalling code */
+ if ((tm = Getattr(p, "tmap:directorin"))) {
+
+ Setattr(p, "emit:directorinput", arg);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ // Add parameter type to the C typedef for the D callback function.
+ Printf(callback_typedef_parms, ", %s", c_param_type);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = lookupDTypemap(p, "imtype", true))) {
+ String *imtypeout = Getattr(p, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the
+ // type in the typemap itself.
+ tm = imtypeout;
+ }
+ const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
+
+ // TODO: Is this copy really needed?
+ String *din = Copy(lookupDTypemap(p, "ddirectorin", true));
+
+ if (din) {
+ Replaceall(din, "$winput", ln);
+
+ Printf(delegate_parms, ", ");
+ if (i > 0) {
+ Printf(proxy_method_param_list, ", ");
+ Printf(imcall_args, ", ");
+ }
+ Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else {
+ Printv(imcall_args, ln, NIL);
+ }
+
+ Delete(din);
+
+ // Get the parameter type in the proxy D class (used later when
+ // generating the overload checking code for the directorConnect
+ // function).
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ Printf(proxy_method_param_list, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DDIRECTORIN_UNDEF, input_file, line_number,
+ "No ddirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number,
+ "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DDIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(arg);
+ Delete(c_decl);
+ Delete(c_param_type);
+ Delete(ln);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ // Finish the callback function declaraction.
+ Printf(callback_def, "%s)", delegate_parms);
+ Printf(callback_def, " {\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("(cast(%s)dObject).%s(%s)", classname, symname, imcall_args);
+
+ if (!is_void) {
+ if ((tm = lookupDTypemap(n, "ddirectorout"))) {
+ Replaceall(tm, "$dcall", upcall);
+ Printf(callback_code, " return %s;\n", tm);
+ }
+ } else {
+ Printf(callback_code, " %s;\n", upcall);
+ }
+
+ Printf(callback_code, "}\n");
+ Delete(upcall);
+
+ if (!ignored_method) {
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "swig_callback_%s(d_object%s);\n", overloaded_name, dcallback_call_args);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ canThrow(n, "directorargout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Terminate wrapper code */
+ Printf(w->code, "}\n");
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!ignored_method)
+ Printv(director_dcallbacks_code, callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ if (!ignored_method) {
+ // Register the upcall method so that the callback registering code can
+ // be written later.
+
+ // We cannot directly use n here because its »type« attribute does not
+ // the full return type any longer after Language::functionHandler has
+ // returned.
+ String *dp_return_type = getOutDtype(n);
+ if (!dp_return_type) {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ dp_return_type = NewString("");
+ }
+
+ String *member_name = Swig_name_member(getNSpace(), classname, overloaded_name);
+ String *imclass_dmethod = NewStringf("SwigDirector_%s", member_name);
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name, dp_return_type, proxy_method_param_list);
+
+ // Write the global callback function pointer on the C code.
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(director_callback_typedefs, " typedef %s (* SWIG_Callback%s_t)", c_ret_type, methid);
+ Printf(director_callback_typedefs, "(void *dobj%s);\n", callback_typedef_parms);
+ Printf(director_callback_pointers, " SWIG_Callback%s_t swig_callback_%s;\n", methid, overloaded_name);
+
+ // Write the type alias for the callback to the intermediary D module.
+ String *proxy_callback_type = NewString("");
+ String *dirClassName = directorClassName(parent);
+ Printf(proxy_callback_type, "%s_Callback%s", dirClassName, methid);
+ Printf(im_dmodule_code, "alias extern(C) %s function(void*%s) %s;\n", proxy_callback_return_type, delegate_parms, proxy_callback_type);
+
+ Delete(imclass_dmethod);
+ Delete(member_name);
+ Delete(dp_return_type);
+ Delete(proxy_callback_type);
+ Delete(dirClassName);
+ }
+
+ Delete(qualified_return);
+ Delete(c_ret_type);
+ Delete(declaration);
+ Delete(callback_typedef_parms);
+ Delete(delegate_parms);
+ Delete(proxy_method_param_list);
+ Delete(callback_def);
+ Delete(callback_code);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorConstructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");;
+ String *supername = Swig_class_name(parent);
+ String *dirclassname = directorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ // TODO: Is this copy needed?
+ parms = CopyParmList(superparms);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 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);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(parms);
+ Delete(dirclassname);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDefaultConstructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDefaultConstructor(Node *n) {
+ String *dirclassname = directorClassName(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "%s::%s() : %s {", dirclassname, dirclassname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " %s();\n", dirclassname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(dirclassname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDestructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *dirclassname = directorClassName(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirclassname);
+ Printf(w->def, "%s::~%s() noexcept {\n", dirclassname, dirclassname);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", dirclassname);
+ Printf(w->def, "%s::~%s() throw() {\n", dirclassname, dirclassname);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", dirclassname);
+ Printf(w->def, "%s::~%s() {\n", dirclassname, dirclassname);
+ }
+
+ Printv(w->code, "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(dirclassname);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorEnd()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorEnd(Node *n) {
+ int i;
+ String *director_classname = directorClassName(n);
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(director_callback_typedefs) > 0) {
+ Printf(f_directors_h, "\n%s", director_callback_typedefs);
+ }
+
+ Printf(f_directors_h, " void swig_connect_director(void* dobj");
+
+ Printf(w->def, "void %s::swig_connect_director(void* dobj", director_classname);
+ Printf(w->code, "d_object = dobj;");
+
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+
+ Printf(f_directors_h, ", SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->def, ", SWIG_Callback%s_t callback_%s", methid, overname);
+ Printf(w->code, "swig_callback_%s = callback_%s;\n", overname, overname);
+ }
+
+ Printf(f_directors_h, ");\n");
+ Printf(w->def, ") {");
+
+ Printf(f_directors_h, "\nprivate:\n");
+ Printf(f_directors_h, " void swig_init_callbacks();\n");
+ Printf(f_directors_h, " void *d_object;\n");
+ if (Len(director_callback_pointers) > 0) {
+ Printf(f_directors_h, "%s", director_callback_pointers);
+ }
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n\n");
+
+ Printf(w->code, "void %s::swig_init_callbacks() {\n", director_classname);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *overname = Getattr(udata, "overname");
+ Printf(w->code, "swig_callback_%s = 0;\n", overname);
+ }
+ Printf(w->code, "}");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDisown()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceSpecialVariables()
+ * --------------------------------------------------------------------------- */
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+
+ // Just assume that this goes to the proxy class, we cannot know.
+ replaceClassname(tm, type);
+ }
+
+protected:
+ /* ---------------------------------------------------------------------------
+ * D::extraDirectorProtectedCPPMethodsRequired()
+ * --------------------------------------------------------------------------- */
+ virtual bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+private:
+ /* ---------------------------------------------------------------------------
+ * D::writeImDModuleFunction()
+ *
+ * Writes a function declaration for the given (C) wrapper function to the
+ * intermediary D module.
+ *
+ * d_name - The name the function in the intermediary D module will get.
+ * return type - The return type of the function in the C wrapper.
+ * parameters - The parameter list of the C wrapper function.
+ * wrapper_function_name - The name of the exported function in the C wrapper
+ * (usually d_name prefixed by »D_«).
+ * --------------------------------------------------------------------------- */
+ void writeImDModuleFunction(const_String_or_char_ptr d_name,
+ const_String_or_char_ptr return_type, const_String_or_char_ptr parameters,
+ const_String_or_char_ptr wrapper_function_name) {
+
+ // TODO: Add support for static linking here.
+ Printf(im_dmodule_code, "SwigExternC!(%s function%s) %s;\n", return_type,
+ parameters, d_name);
+ Printv(wrapper_loader_bind_code, wrapper_loader_bind_command, NIL);
+ Replaceall(wrapper_loader_bind_code, "$function", d_name);
+ Replaceall(wrapper_loader_bind_code, "$symbol", wrapper_function_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyClassFunction()
+ *
+ * Creates a D proxy function for a C++ function in the wrapped class. Used
+ * for both static and non-static C++ class functions.
+ *
+ * The Node must contain two extra attributes.
+ * - "proxyfuncname": The name of the D proxy function.
+ * - "imfuncname": The corresponding function in the intermediary D module.
+ * --------------------------------------------------------------------------- */
+ void writeProxyClassFunction(Node *n, bool super = false) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ // Wrappers not wanted for some methods where the parameters cannot be
+ // overloaded in D.
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in
+ // directors.
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ // RESEARCH: What is this good for?
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ // Get return types.
+ String *return_type = getOutDtype(n);
+ if (!return_type) {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ return_type = NewString("");
+ }
+
+ if (wrapping_member_flag) {
+ // Check if this is a setter method for a public member.
+ const String *setter_name = Swig_name_set(getNSpace(),
+ Swig_name_member(0, proxy_class_name, variable_name));
+
+ if (Cmp(Getattr(n, "sym:name"), setter_name) == 0) {
+ setter_flag = true;
+ }
+ }
+
+ // We move the modifiers after the parameter list
+ // as we need the D parametes to catch D override of functions
+ String *param_function_code = NewString("");
+
+ if (super) {
+ Printf(imcall, "super.$funcname(");
+ } else {
+ // Write the wrapper function call up to the parameter list.
+ Printv(imcall, im_dmodule_fq_name, ".$imfuncname(", NIL);
+ if (!static_flag) {
+ Printf(imcall, "cast(void*)swigCPtr");
+ }
+ }
+
+ String *proxy_param_types = NewString("");
+
+ // Write the parameter list for the proxy function declaration and the
+ // wrapper function call.
+ emit_mark_varargs(l);
+ int gencomma = !static_flag && !super;
+ for (i = 0, p = l; p; i++) {
+ // Ignored varargs.
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ Setattr(p, "d:type", NewString(""));
+ p = nextSibling(p);
+ continue;
+ }
+
+ // Ignored parameters.
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ Setattr(p, "d:type", NewString(""));
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ // Ignore the 'this' argument for variable wrappers.
+ if (!(variable_wrapper_flag && i == 0)) {
+ String *param_name = makeParameterName(n, p, i, setter_flag);
+ SwigType *pt = Getattr(p, "type");
+
+ // Write the wrapper function call argument.
+ {
+ if (gencomma) {
+ Printf(imcall, ", ");
+ }
+
+ if ((tm = lookupDTypemap(p, "din", true))) {
+ Replaceall(tm, "$dinput", param_name);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", param_name);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", param_name);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", param_name);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ }
+
+ // Write the D proxy function parameter.
+ {
+ String *proxy_type = NewString("");
+
+ if ((tm = lookupDTypemap(p, "dtype"))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(proxy_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ {
+ int ln = Len(package);
+ /* If proxy_type uses the package name, it must be larger */
+ if (Len(proxy_type) > ln && Strncmp(package, proxy_type, ln) == 0) {
+ Setattr(p, "d:type", NewString(Char(proxy_type) + ln));
+ } else {
+ Setattr(p, "d:type", Copy(proxy_type));
+ }
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma >= 2) {
+ Printf(param_function_code, ", ");
+ Printf(proxy_param_types, ", ");
+ }
+ gencomma = 2;
+ Printf(param_function_code, "%s %s", proxy_type, param_name);
+ Append(proxy_param_types, proxy_type);
+
+ Delete(proxy_type);
+ }
+
+ Delete(param_name);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ // Complete the function declaration up to the parameter list.
+ // Write function modifiers.
+ {
+ const String *mods_override = Getattr(n, "feature:d:methodmodifiers");
+ bool isPrivate = false;
+ if (mods_override) {
+ isPrivate = Strcmp(mods_override, private_string) == 0;
+ } else {
+ mods_override = is_public(n) ? public_string : protected_string;
+ }
+ String *modifiers = Copy(mods_override);
+ Setattr(n, "dmodify", Copy(mods_override));
+
+ /* private function are never override */
+ if (super || (!isPrivate && isDOverride(n, l))) {
+ Printf(modifiers, " override");
+ }
+
+ Chop(modifiers);
+
+ if (static_flag) {
+ Printf(modifiers, " static");
+ }
+
+ Printf(function_code, "%s ", modifiers);
+ Delete(modifiers);
+ }
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+
+ // Add Body the parameter list part after the modifiers
+ Append(function_code, param_function_code);
+
+ Printf(imcall, ")");
+ Printf(function_code, ") ");
+
+ if (wrapping_member_flag) {
+ Printf(function_code, "@property ");
+ }
+
+ if (wrapMemberFunctionAsDConst(n)) {
+ Printf(function_code, "const ");
+ }
+
+ if (super) {
+ Replaceall(imcall, "$funcname", proxy_function_name);
+ if (!Cmp(return_type, "void")) {
+ tm = NewString("{\n $imcall;\n}");
+ } else {
+ tm = NewString("{\n return $imcall;\n}");
+ }
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ // Lookup the code used to convert the wrapper return value to the proxy
+ // function return type.
+ if ((tm = lookupDTypemap(n, "dout"))) {
+ replaceExcode(n, tm, "dout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printv(tm, "}", NIL);
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ replaceClassname(tm, t);
+
+ // For director methods: generate code to selectively make a normal
+ // polymorphic call or an explicit method call. Needed to prevent infinite
+ // recursion when calling director methods.
+ Node *explicit_n = Getattr(n, "explicitcallnode");
+ if (explicit_n && Swig_directorclass(getCurrentClass())) {
+ String *ex_overloaded_name = getOverloadedName(explicit_n);
+ String *ex_intermediary_function_name = Swig_name_member(getNSpace(), proxy_class_name, ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+
+ String *override_use_const = NewString("");
+ if (wrapMemberFunctionAsDConst(n)) {
+ Printf(override_use_const, "Const");
+ }
+ String *excode = NewString("");
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (swigIsMethodOverridden%s!(%s delegate(%s), %s function(%s), %s)()) %s; else %s",
+ override_use_const, return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall);
+ else
+ Printf(excode, "((swigIsMethodOverridden%s!(%s delegate(%s), %s function(%s), %s)()) ? %s : %s)",
+ override_use_const, return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ Delete(ex_overloaded_name);
+ Delete(excode);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+ Replaceall(tm, "$imfuncname", intermediary_function_name);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
+ "No dout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+
+ Delete(proxy_param_types);
+
+ // The whole function body is now in stored tm (if there was a matching type
+ // map, of course), so simply append it to the code buffer. The braces are
+ // included in the typemap.
+ Printv(function_code, tm, NIL);
+
+ // Write function code buffer to the class code.
+ Printv(proxy_class_body_code, "\n", function_code, "\n", NIL);
+
+ Delete(tm);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyDModuleFunction()
+ * --------------------------------------------------------------------------- */
+ void writeProxyDModuleFunction(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ // RESEARCH: What is this good for?
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ /* Get return types */
+ String *return_type = getOutDtype(n);
+ if (!return_type) {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ return_type = NewString("");
+ }
+
+ /* Change function name for global variables */
+ if (global_variable_flag) {
+ // RESEARCH: Is the Copy() needed here?
+ func_name = Copy(variable_name);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *outattributes = Getattr(n, "tmap:dtype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ // TODO: Check if is_public(n) could possibly make any sense here
+ // (private global functions would be useless anyway?).
+ methodmods = methodmods ? methodmods : empty_string;
+
+ Printf(function_code, "\n%s%s %s(", methodmods, return_type, func_name);
+ Printv(imcall, im_dmodule_fq_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ // Get the D parameter type.
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ const bool generating_setter = global_variable_flag || wrapping_member_flag;
+ String *arg = makeParameterName(n, p, i, generating_setter);
+
+ // Get the D code to convert the parameter value to the type used in the
+ // wrapper D module.
+ if ((tm = lookupDTypemap(p, "din", true))) {
+ Replaceall(tm, "$dinput", arg);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ") ");
+
+ if (global_variable_flag) {
+ Printf(function_code, "@property ");
+ }
+
+ // Lookup the code used to convert the wrapper return value to the proxy
+ // function return type.
+ if ((tm = lookupDTypemap(n, "dout"))) {
+ replaceExcode(n, tm, "dout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, " {");
+ Printf(tm, "\n}");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ replaceClassname(tm, t);
+ Replaceall(tm, "$imfuncname", overloaded_name);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
+ "No dout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ // The whole function code is now stored in tm (if there was a matching
+ // type map, of course), so simply append it to the code buffer.
+ Printf(function_code, "%s\n", tm ? (const String *) tm : empty_string);
+ Printv(proxyCodeBuffer(getNSpace()), function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyClassAndUpcasts()
+ *
+ * Collects all the code fragments generated by the handler function while
+ * traversing the tree from the proxy_class_* variables and writes the
+ * class definition (including any epilogue code) to proxy_class_code.
+ *
+ * Also writes the upcast function to the wrapper layer when processing a
+ * derived class.
+ *
+ * Inputs:
+ * n – The class node currently processed.
+ * --------------------------------------------------------------------------- */
+ void writeProxyClassAndUpcasts(Node *n) {
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+
+ /*
+ * Handle inheriting from D and C++ classes.
+ */
+
+ String *c_classname = Getattr(n, "name");
+ String *c_baseclassname = NULL;
+ Node *basenode = NULL;
+ String *baseclass = NULL;
+ SwigType *bsmart = 0;
+
+ // Inheritance from pure D classes.
+ Node *attributes = NewHash();
+ const String *pure_baseclass =
+ lookupCodeTypemap(n, "dbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:dbase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:dbase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance.
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ SwigType *baseclassname = Getattr(base.item, "name");
+ if (!c_baseclassname) {
+ basenode = base.item;
+ String *name = createProxyName(baseclassname);
+ if (name) {
+ c_baseclassname = baseclassname;
+ baseclass = name;
+ bsmart = Getattr(base.item, "smart");
+ }
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Base %s of class %s ignored: multiple inheritance is not supported in D.\n", SwigType_namestr(baseclassname), SwigType_namestr(proxyclassname));
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+
+ bool derived = baseclass != NULL;
+
+ if (derived && purebase_notderived) {
+ pure_baseclass = empty_string;
+ }
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ basenode = NULL;
+ baseclass = NULL;
+ if (purebase_notderived) {
+ Swig_error(Getfile(n), Getline(n),
+ "The dbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n",
+ typemap_lookup_type);
+ }
+ } else if (baseclass && Len(pure_baseclass) > 0) {
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base class %s ignored. Multiple inheritance is not supported in D. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the dbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
+ if (derived) {
+ writeClassUpcast(n, bsmart, proxy_class_name, c_classname, c_baseclassname);
+ }
+
+ /*
+ * Write needed imports.
+ */
+ // If this class is derived from a C++ class, we need to have the D class
+ // generated for it in scope.
+ if (derived) {
+ requireDType(Getattr(basenode, "sym:nspace"), Getattr(basenode, "sym:name"));
+ }
+
+ // Write any custom import statements to the proxy module header.
+ const String *imports = lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
+ if (Len(imports) > 0) {
+ String* imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(proxy_class_imports, imports_trimmed, "\n", NIL);
+ Delete(imports_trimmed);
+ }
+
+ /*
+ * Write the proxy class header.
+ */
+ // Class modifiers.
+ const String *modifiers =
+ lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
+
+ // User-defined interfaces.
+ const String *interfaces =
+ lookupCodeTypemap(n, derived ? "dinterfaces_derived" : "dinterfaces", typemap_lookup_type, WARN_NONE);
+
+ Printv(proxy_class_code,
+ "\n",
+ modifiers,
+ " $dclassname",
+ (*Char(wanted_base) || *Char(interfaces)) ? " : " : "", wanted_base,
+ (*Char(wanted_base) && *Char(interfaces)) ? ", " : "", interfaces, " {",
+ NIL);
+
+ /*
+ * Write the proxy class body.
+ */
+ String* body = NewString("");
+
+ // Default class body.
+ const String *dbody;
+ if (derived) {
+ dbody = lookupCodeTypemap(n, "dbody_derived", typemap_lookup_type, WARN_D_TYPEMAP_DBODY_UNDEF);
+ } else {
+ dbody = lookupCodeTypemap(n, "dbody", typemap_lookup_type, WARN_D_TYPEMAP_DBODY_UNDEF);
+ }
+
+ Printv(body, dbody, NIL);
+
+ // Destructor and dispose().
+ // If the C++ destructor is accessible (public), it is wrapped by the
+ // dispose() method which is also called by the emitted D constructor. If it
+ // is not accessible, no D destructor is written and the generated dispose()
+ // method throws an exception.
+ // This enables C++ classes with protected or private destructors to be used
+ // in D as it would be used in C++ (GC finalization is a no-op then because
+ // of the empty D destructor) while preventing usage in »scope« variables.
+ // The method name for the dispose() method is specified in a typemap
+ // attribute called »methodname«.
+ const String *tm = NULL;
+
+ const String *dispose_methodname;
+ const String *dispose_methodmodifiers;
+ const String *dispose_parameters;
+ attributes = NewHash();
+ if (derived) {
+ tm = lookupCodeTypemap(n, "ddispose_derived", typemap_lookup_type, WARN_NONE, attributes);
+ dispose_methodname = Getattr(attributes, "tmap:ddispose_derived:methodname");
+ dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose_derived:methodmodifiers");
+ dispose_parameters = Getattr(attributes, "tmap:ddispose_derived:parameters");
+ } else {
+ tm = lookupCodeTypemap(n, "ddispose", typemap_lookup_type, WARN_NONE, attributes);
+ dispose_methodname = Getattr(attributes, "tmap:ddispose:methodname");
+ dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose:methodmodifiers");
+ dispose_parameters = Getattr(attributes, "tmap:ddispose:parameters");
+ }
+
+ if (tm && *Char(tm)) {
+ if (!dispose_methodname) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodname attribute defined in the ddispose%s typemap for %s\n",
+ (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!dispose_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodmodifiers attribute defined in ddispose%s typemap for %s.\n",
+ (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!dispose_parameters)
+ dispose_parameters = empty_string;
+ }
+
+ if (tm) {
+ // Write the destructor if the C++ one is accessible.
+ if (*Char(destructor_call)) {
+ Printv(body,
+ lookupCodeTypemap(n, "ddestructor", typemap_lookup_type, WARN_NONE), NIL);
+ }
+
+ // Write the dispose() method.
+ String *dispose_code = NewString("");
+ Printv(dispose_code, tm, NIL);
+
+ if (*Char(destructor_call)) {
+ Replaceall(dispose_code, "$imcall", destructor_call);
+ } else {
+ Replaceall(dispose_code, "$imcall", "throw new object.Exception(\"C++ destructor does not have public access\")");
+ }
+
+ if (*Char(dispose_code)) {
+ Printv(body, "\n", NIL);
+ const String *methodmods = Getattr(n, "destructmethodmodifiers");
+ if (methodmods)
+ Printv(body, methodmods, NIL);
+ else
+ Printv(body, dispose_methodmodifiers, (derived ? " override" : ""), NIL);
+ Printv(body, " void ", dispose_methodname, "(", dispose_parameters, ") ", dispose_code, "\n", NIL);
+ }
+ }
+
+ if (Swig_directorclass(n)) {
+ // If directors are enabled for the current class, generate the
+ // director connect helper function which is called from the constructor
+ // and write it to the class body.
+ writeDirectorConnectProxy(n);
+ }
+
+ // Write all constants and enumerations first to prevent forward reference
+ // errors.
+ Printv(body, proxy_class_enums_code, NIL);
+
+ // Write the code generated in other methods to the class body.
+ Printv(body, proxy_class_body_code, NIL);
+
+ // Append extra user D code to the class body.
+ Printv(body,
+ lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), "\n", NIL);
+
+ // Write the class body and the curly bracket closing the class definition
+ // to the proxy module.
+ indentCode(body);
+ Replaceall(body, "$dbaseclass", baseclass);
+
+ Printv(proxy_class_code, body, "\n}\n", NIL);
+ Delete(body);
+
+ // Write the epilogue code if there is any.
+ Printv(proxy_class_code, proxy_class_epilogue_code, NIL);
+ }
+
+
+ /* ---------------------------------------------------------------------------
+ * D::writeClassUpcast()
+ * --------------------------------------------------------------------------- */
+ void writeClassUpcast(Node *n, SwigType *bsmart, const String *d_class_name, SwigType *c_classname, SwigType *c_baseclassname) {
+
+ SwigType *smart = Getattr(n, "smart");
+ String *upcast_name = Swig_name_member(getNSpace(), d_class_name, (smart != 0 ? "SmartPtrUpcast" : "Upcast"));
+ String *upcast_wrapper_name = Swig_name_wrapper(upcast_name);
+
+ writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)", upcast_wrapper_name);
+
+ String *classname = SwigType_namestr(c_classname);
+ String *baseclassname = SwigType_namestr(c_baseclassname);
+
+ if (smart) {
+ if (bsmart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(bsmart);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name,
+ "(", smartnamestr, " *objectRef) {\n",
+ " return objectRef ? new ", bsmartnamestr, "(*objectRef) : 0;\n"
+ "}\n",
+ "\n", NIL);
+
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ }
+ } else {
+ Printv(upcasts_code,
+ "SWIGEXPORT ", baseclassname, " * ", upcast_wrapper_name,
+ "(", classname, " *objectRef) {\n",
+ " return (", baseclassname, " *)objectRef;\n"
+ "}\n",
+ "\n", NIL);
+ }
+
+ Replaceall(upcasts_code, "$cclass", classname);
+ Replaceall(upcasts_code, "$cbaseclass", baseclassname);
+
+ Delete(baseclassname);
+ Delete(classname);
+ Delete(upcast_wrapper_name);
+ Delete(upcast_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeTypeWrapperClass()
+ * --------------------------------------------------------------------------- */
+ void writeTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ assertClassNameValidity(classname);
+
+ String* imports_target;
+ String* code_target;
+ File *class_file = NULL;
+ if (split_proxy_dmodule) {
+ String *filename = NewStringf("%s%s.d", dmodule_directory, classname);
+ class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ Printf(class_file, "module %s%s;\n", package, classname);
+ Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+
+ imports_target = NewString("");
+ code_target = NewString("");
+ } else {
+ imports_target = proxyImportsBuffer(0);
+ code_target = proxyCodeBuffer(0);
+ }
+
+ // Import statements.
+ const String *imports = lookupCodeTypemap(n, "dimports", type, WARN_NONE);
+ if (Len(imports) > 0) {
+ String *imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(imports_target, imports_trimmed, "\n", NIL);
+ Delete(imports_trimmed);
+ }
+
+ // Pure D baseclass and interfaces (no C++ inheritance possible.
+ const String *pure_baseclass = lookupCodeTypemap(n, "dbase", type, WARN_NONE);
+ const String *pure_interfaces = lookupCodeTypemap(n, "dinterfaces", type, WARN_NONE);
+
+ // Emit the class.
+ Printv(code_target,
+ "\n",
+ lookupCodeTypemap(n, "dclassmodifiers", type, WARN_D_TYPEMAP_CLASSMOD_UNDEF),
+ " $dclassname",
+ (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass,
+ ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? ", " : "", pure_interfaces,
+ " {", NIL);
+
+ String* body = NewString("");
+ Printv(body, lookupCodeTypemap(n, "dbody", type, WARN_D_TYPEMAP_DBODY_UNDEF),
+ lookupCodeTypemap(n, "dcode", type, WARN_NONE), NIL);
+ indentCode(body);
+ Printv(code_target, body, "\n}\n", NIL);
+ Delete(body);
+
+ Replaceall(code_target, "$dclassname", classname);
+
+ if (split_proxy_dmodule) {
+ Printv(class_file, imports_target, NIL);
+ Delete(imports_target);
+
+ replaceModuleVariables(code_target);
+ Printv(class_file, code_target, NIL);
+ Delete(code_target);
+
+ Delete(class_file);
+ }
+
+ Delete(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorConnectProxy(Node *classNode)
+ *
+ * Writes the helper method which registers the director callbacks by calling
+ * the director connect function from the D side to the proxy class.
+ * --------------------------------------------------------------------------- */
+ void writeDirectorConnectProxy(Node* classNode) {
+ String *dirClassName = directorClassName(classNode);
+ String *connect_name = Swig_name_member(getNSpace(),
+ proxy_class_name, "director_connect");
+ Printf(proxy_class_body_code, "\nprivate void swigDirectorConnect() {\n");
+
+ int i;
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *method = Getattr(udata, "method");
+ String *overloaded_name = Getattr(udata, "overname");
+ String *return_type = Getattr(udata, "return_type");
+ String *param_list = Getattr(udata, "param_list");
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_body_code, " %s.%s_Callback%s callback%s;\n", im_dmodule_fq_name, dirClassName, methid, methid);
+ Printf(proxy_class_body_code, " if (swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) {\n", return_type, param_list, return_type, param_list, method);
+ Printf(proxy_class_body_code, " callback%s = &swigDirectorCallback_%s_%s;\n", methid, proxy_class_name, overloaded_name);
+ Printf(proxy_class_body_code, " }\n\n");
+ }
+ Printf(proxy_class_body_code, " %s.%s(cast(void*)swigCPtr, cast(void*)this", im_dmodule_fq_name, connect_name);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_body_code, ", callback%s", methid);
+ }
+ Printf(proxy_class_body_code, ");\n");
+ Printf(proxy_class_body_code, "}\n");
+
+ // Helper function to determine if a method has been overridden in a
+ // subclass of the wrapped class. If not, we just pass null to the
+ // director_connect_function since the method from the C++ class should
+ // be called as usual (see above).
+ // Only emit it if the proxy class has at least one method.
+ if (first_class_dmethod < curr_class_dmethod) {
+ Printf(proxy_class_body_code, "\n");
+ Printf(proxy_class_body_code, "private bool swigIsMethodOverridden(DelegateType, FunctionType, alias fn)() {\n");
+ Printf(proxy_class_body_code, " DelegateType dg = &fn;\n");
+ Printf(proxy_class_body_code, " return dg.funcptr != SwigNonVirtualAddressOf!(FunctionType, fn);\n");
+ Printf(proxy_class_body_code, "}\n");
+ Printf(proxy_class_body_code, "private bool swigIsMethodOverriddenConst(DelegateType, FunctionType, alias fn)() inout {\n");
+ Printf(proxy_class_body_code, " DelegateType dg = &fn;\n");
+ Printf(proxy_class_body_code, " return dg.funcptr != SwigNonVirtualAddressOf!(FunctionType, fn);\n");
+ Printf(proxy_class_body_code, "}\n");
+ Printf(proxy_class_body_code, "\n");
+ Printf(proxy_class_body_code, "private static Function SwigNonVirtualAddressOf(Function, alias fn)() {\n");
+ Printf(proxy_class_body_code, " return cast(Function) &fn;\n");
+ Printf(proxy_class_body_code, "}\n");
+ }
+
+ if (Len(director_dcallbacks_code) > 0) {
+ Printv(proxy_class_epilogue_code, director_dcallbacks_code, NIL);
+ }
+
+ Delete(director_callback_typedefs);
+ director_callback_typedefs = NULL;
+ Delete(director_callback_pointers);
+ director_callback_pointers = NULL;
+ Delete(director_dcallbacks_code);
+ director_dcallbacks_code = NULL;
+ Delete(dirClassName);
+ Delete(connect_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorSuperFunctions()
+ *
+ * Writes super methods for protected methods in virtual table
+ * which are not implemented in class.
+ * So the director connect function can call them.
+ * As function outside the class, can call module protected methods
+ * but not protected of clases outside this module!
+ * --------------------------------------------------------------------------- */
+ // TODO WORK
+ void writeDirectorSuperFunctions(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ Node *vtable = Getattr(n, "vtable");
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ if (GetFlag(item, "director")) {
+ Node *method = Getattr(item, "methodNode");
+ Node *p = parentNode(method);
+ if (p && p != n && is_protected(method)) {
+ const String *nodeType = nodeType(method);
+ if (Strcmp(nodeType, "cdecl") == 0) {
+ Setattr(method, "proxyfuncname", Getattr(method, "sym:name"));
+ writeProxyClassFunction(method, true);
+ }
+ }
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorConnectWrapper()
+ *
+ * Writes the director connect function and the corresponding declaration to
+ * the C++ wrapper respectively the D wrapper.
+ * --------------------------------------------------------------------------- */
+ void writeDirectorConnectWrapper(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // Output the director connect method.
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+ String *connect_name = Swig_name_member(getNSpace(),
+ proxy_class_name, "director_connect");
+ String *dirClassName = directorClassName(n);
+ Wrapper *code_wrap;
+
+ Printv(wrapper_loader_bind_code, wrapper_loader_bind_command, NIL);
+ Replaceall(wrapper_loader_bind_code, "$function", connect_name);
+ Replaceall(wrapper_loader_bind_code, "$symbol", Swig_name_wrapper(connect_name));
+
+ Printf(im_dmodule_code, "extern(C) void function(void* cObject, void* dObject");
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def, "SWIGEXPORT void D_%s(void *objarg, void *dobj", connect_name);
+
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
+
+ Printf(code_wrap->code, " director->swig_connect_director(dobj");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(code_wrap->def, ", %s::SWIG_Callback%s_t callback%s", dirClassName, methid, methid);
+ Printf(code_wrap->code, ", callback%s", methid);
+ Printf(im_dmodule_code, ", %s_Callback%s callback%s", dirClassName, methid, methid);
+ }
+
+ Printf(code_wrap->def, ") {\n");
+ Printf(code_wrap->code, ");\n");
+ Printf(im_dmodule_code, ") %s;\n", connect_name);
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(connect_name);
+ Delete(dirClassName);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::requireDType()
+ *
+ * If the given type is not already in scope in the current module, adds an
+ * import statement for it. The name is considered relative to the global root
+ * package if one is set.
+ *
+ * This is only used for dependencies created in generated code, user-
+ * (i.e. typemap-) specified import statements are handled separately.
+ * --------------------------------------------------------------------------- */
+ void requireDType(const String *nspace, const String *symname) {
+ String *dmodule = createModuleName(nspace, symname);
+
+ if (!inProxyModule(dmodule)) {
+ String *import = createImportStatement(dmodule);
+ Append(import, "\n");
+ if (is_wrapping_class()) {
+ addImportStatement(proxy_class_imports, import);
+ } else {
+ addImportStatement(proxyImportsBuffer(getNSpace()), import);
+ }
+ Delete(import);
+ }
+ Delete(dmodule);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::addImportStatement()
+ *
+ * Adds the given import statement to the given list of import statements if
+ * there is no statement importing that module present yet.
+ * --------------------------------------------------------------------------- */
+ void addImportStatement(String *target, const String *import) const {
+ char *position = Strstr(target, import);
+ if (position) {
+ // If the import statement has been found in the target string, we have to
+ // check if the previous import was static, which would lead to problems
+ // if this import is not.
+ // Thus, we check if the seven characters in front of the occurrence are
+ // »static «. If the import string passed is also static, the checks fail
+ // even if the found statement is also static because the last seven
+ // characters would be part of the previous import statement then.
+
+ if (position - Char(target) < 7) {
+ return;
+ }
+ if (strncmp(position - 7, "static ", 7)) {
+ return;
+ }
+ }
+
+ Printv(target, import, NIL);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createImportStatement()
+ *
+ * Creates a string containing an import statement for the given module.
+ * --------------------------------------------------------------------------- */
+ String *createImportStatement(const String *dmodule_name,
+ bool static_import = true) const {
+
+ if (static_import) {
+ return NewStringf("static import %s%s;", package, dmodule_name);
+ } else {
+ return NewStringf("import %s%s;", package, dmodule_name);
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::inProxyModule()
+ *
+ * Determines if the specified proxy type is declared in the currently
+ * processed proxy D module.
+ *
+ * This function is used to determine if fully qualified type names have to
+ * be used (package, module and type name). If the split proxy mode is not
+ * used, this solely depends on whether the type is in the current namespace.
+ * --------------------------------------------------------------------------- */
+ bool inProxyModule(const String *type_name) const {
+ if (!split_proxy_dmodule) {
+ String *nspace = createOuterNamespaceNames(type_name);
+
+ // Check if strings are either both null (no namespace) or are both
+ // non-null and have the same contents. Cannot use Strcmp for this
+ // directly because of its strange way of handling the case where only
+ // one argument is 0 ("<").
+ bool result = !nspace && !getNSpace();
+ if (nspace && getNSpace())
+ result = (Strcmp(nspace, getNSpace()) == 0);
+
+ Delete(nspace);
+ return result;
+ }
+
+ if (!is_wrapping_class()) {
+ return false;
+ }
+
+ return (Strcmp(proxy_class_qname, type_name) == 0);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::addUpcallMethod()
+ *
+ * Adds new director upcall signature.
+ * --------------------------------------------------------------------------- */
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method,
+ String *decl, String *overloaded_name, String *return_type, String *param_list) {
+
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ Hash *new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+ Setattr(new_udata, "overname", Copy(overloaded_name));
+ Setattr(new_udata, "return_type", Copy(return_type));
+ Setattr(new_udata, "param_list", Copy(param_list));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::assertClassNameValidity()
+ * --------------------------------------------------------------------------- */
+ void assertClassNameValidity(const String* class_name) const {
+ // TODO: With nspace support, there could arise problems also when not in
+ // split proxy mode, warnings for these should be added.
+ if (split_proxy_dmodule) {
+ if (Cmp(class_name, im_dmodule_name) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be equal to intermediary D module name: %s\n",
+ class_name);
+ Exit(EXIT_FAILURE);
+ }
+
+ String *nspace = getNSpace();
+ if (nspace) {
+ // Check the root package/outermost namespace (a class A in module
+ // A.B leads to problems if another module A.C is also imported)
+ if (Len(package) > 0) {
+ String *dotless_package = NewStringWithSize(package, Len(package) - 1);
+ if (Cmp(class_name, dotless_package) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the root package it is in: %s\n",
+ class_name);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(dotless_package);
+ } else {
+ String *outer = createFirstNamespaceName(nspace);
+ if (Cmp(class_name, outer) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the outermost namespace it is in: %s\n",
+ class_name);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(outer);
+ }
+
+ // … and the innermost one (because of the conflict with the main proxy
+ // module named like the namespace).
+ String *inner = createLastNamespaceName(nspace);
+ if (Cmp(class_name, inner) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be the same as the innermost namespace it is in: %s\n",
+ class_name);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(inner);
+ } else {
+ if (Cmp(class_name, proxy_dmodule_name) == 0) {
+ Swig_error(input_file, line_number,
+ "Class name cannot be equal to proxy D module name: %s\n",
+ class_name);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getPrimitiveDptype()
+ *
+ * Returns the D proxy type for the passed type if it is a primitive type in
+ * both C and D.
+ * --------------------------------------------------------------------------- */
+ String *getPrimitiveDptype(Node *node, SwigType *type) {
+ SwigType *stripped_type = SwigType_typedef_resolve_all(type);
+
+ // A reference can only be the »outermost element« of a type.
+ bool mutable_ref = false;
+ if (SwigType_isreference(stripped_type)) {
+ SwigType_del_reference(stripped_type);
+
+ if (SwigType_isconst(stripped_type)) {
+ SwigType_del_qualifier(stripped_type);
+ } else {
+ mutable_ref = true;
+ }
+ }
+
+ // Strip all the pointers from the type.
+ int indirection_count = 0;
+ while (SwigType_ispointer(stripped_type)) {
+ ++indirection_count;
+ SwigType_del_pointer(stripped_type);
+ }
+
+ // Now that we got rid of the pointers, see if we are dealing with a
+ // primitive type.
+ String *dtype = 0;
+ if (SwigType_isfunction(stripped_type) && indirection_count > 0) {
+ // type was a function pointer, split it up.
+ SwigType_add_pointer(stripped_type);
+ --indirection_count;
+
+ SwigType *return_type = Copy(stripped_type);
+ SwigType *params_type = SwigType_functionpointer_decompose(return_type);
+ String *return_dtype = getPrimitiveDptype(node, return_type);
+ Delete(return_type);
+ if (!return_dtype) {
+ return 0;
+ }
+
+ List *parms = SwigType_parmlist(params_type);
+ List *param_dtypes = NewList();
+ for (Iterator it = First(parms); it.item; it = Next(it)) {
+ String *current_dtype = getPrimitiveDptype(node, it.item);
+ if (Cmp(current_dtype, "void") == 0) {
+ // void somefunc(void) is legal syntax in C, but not in D, so simply
+ // skip the void parameter.
+ Delete(current_dtype);
+ continue;
+ }
+ if (!current_dtype) {
+ Delete(return_dtype);
+ Delete(param_dtypes);
+ return 0;
+ }
+ Append(param_dtypes, current_dtype);
+ }
+
+ String *param_list = NewString("");
+ {
+ bool gen_comma = false;
+ for (Iterator it = First(param_dtypes); it.item; it = Next(it)) {
+ if (gen_comma) {
+ Append(param_list, ", ");
+ }
+ Append(param_list, it.item);
+ Delete(it.item);
+ gen_comma = true;
+ }
+ }
+
+ dtype = NewStringf("%s.SwigExternC!(%s function(%s))", im_dmodule_fq_name,
+ return_dtype, param_list);
+ Delete(param_list);
+ Delete(param_dtypes);
+ Delete(return_dtype);
+ } else {
+ Hash *attributes = NewHash();
+ const String *tm =
+ lookupCodeTypemap(node, "dtype", stripped_type, WARN_NONE, attributes);
+ if(!GetFlag(attributes, "tmap:dtype:cprimitive")) {
+ dtype = 0;
+ } else {
+ dtype = Copy(tm);
+
+ // We need to call replaceClassname here with the stripped type to avoid
+ // $dclassname in the enum typemaps being replaced later with the full
+ // type.
+ replaceClassname(dtype, stripped_type);
+ }
+ Delete(attributes);
+ }
+ Delete(stripped_type);
+
+ if (!dtype) {
+ // The type passed is no primitive type.
+ return 0;
+ }
+
+ // The type is ultimately a primitive type, now append the right number of
+ // indirection levels (pointers).
+ for (int i = 0; i < indirection_count; ++i) {
+ Append(dtype, "*");
+ }
+
+ // Add a level of indirection for a mutable reference since it is wrapped
+ // as a pointer.
+ if (mutable_ref) {
+ Append(dtype, "*");
+ }
+
+ return dtype;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::lookupCodeTypemap()
+ *
+ * Looks up a D code fragment for generating the wrapper class for the given
+ * type.
+ *
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * --------------------------------------------------------------------------- */
+ const String *lookupCodeTypemap(Node *n, const_String_or_char_ptr tmap_method,
+ SwigType *type, int warning, Node *typemap_attributes = 0) const {
+
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE) {
+ Swig_warning(warning, Getfile(n), Getline(n),
+ "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ }
+ if (!typemap_attributes) {
+ Delete(node);
+ }
+
+ return tm;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::lookupDTypemap()
+ *
+ * Looks up a D typemap for the given node, replacing D-specific special
+ * variables as needed.
+ *
+ * The method parameter specifies the typemap method to use. If attached is
+ * true, the value is just fetched from the tmap:<method> node attribute,
+ * Swig_typemap_lookup is used otherwise.
+ * --------------------------------------------------------------------------- */
+ String *lookupDTypemap(Node *n, const_String_or_char_ptr method, bool attached = false) {
+ String *result = 0;
+
+ if (attached) {
+ String *attr_name = NewStringf("tmap:%s", method);
+ result = Copy(Getattr(n, attr_name));
+ Delete(attr_name);
+ } else {
+ // FIXME: As a workaround for a bug so far only surfacing in the
+ // smart_pointer_const_overload test case, remove the nativepointer
+ // typemap attribute since it seems to be already there from a dout
+ // typemap of a different type in that test.
+ String *np_key = NewStringf("tmap:%s:nativepointer", method);
+ Delattr(n, np_key);
+ Delete(np_key);
+
+ result = Swig_typemap_lookup(method, n, "", 0);
+ }
+
+ if (!result) {
+ return 0;
+ }
+
+ // Check if the passed node actually has type information attached. This
+ // is not the case e.g. in constructorWrapper.
+ SwigType *type = Getattr(n, "type");
+ if (type) {
+ String *np_key = NewStringf("tmap:%s:nativepointer", method);
+ String *np_value = Getattr(n, np_key);
+ Delete(np_key);
+ String *dtype;
+ if (np_value && (dtype = getPrimitiveDptype(n, type))) {
+ // If the typemap in question has a »nativepointer« attribute and we
+ // are dealing with a primitive type, use it instead.
+ result = Copy(np_value);
+ Replaceall(result, "$dtype", dtype);
+ }
+
+ replaceClassname(result, type);
+ }
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceClassname()
+ *
+ * Replaces the special variable $dclassname with the proxy class name for
+ * classes/structs/unions SWIG knows about. Also substitutes the enumeration
+ * name for non-anonymous enums. Otherwise, $classname is replaced with a
+ * $descriptor(type)-like name.
+ *
+ * $*dclassname and $&classname work like with descriptors (see manual section
+ * 10.4.3), they remove a prointer from respectively add a pointer to the type.
+ *
+ * Inputs:
+ * tm - String to perform the substitution at (will usually come from a
+ * typemap.
+ * pt - The type to substitute for the variables.
+ * Outputs:
+ * tm - String with the variables substituted.
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * --------------------------------------------------------------------------- */
+ bool replaceClassname(String *tm, SwigType *pt) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ replaceClassnameVariable(tm, "$dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ replaceClassnameVariable(tm, "$*dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ replaceClassnameVariable(tm, "$&dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceClassnameVariable()
+ *
+ * See D::replaceClassname().
+ * --------------------------------------------------------------------------- */
+ void replaceClassnameVariable(String *target, const char *variable, SwigType *type) {
+ // TODO: Fix const-correctness of methods called in here and make type const.
+
+ // We make use of the fact that this function is called at least once for
+ // every type encountered which is written to a separate file, which allows
+ // us to handle imports here.
+ // When working in split proxy module mode, each generated proxy class/enum
+ // is written to a separate module. This requires us to add a corresponding
+ // import when a type is used in another generated module. If we are not
+ // working in split proxy module mode, this is not relevant and the
+ // generated module name is discarded.
+ String *type_name;
+
+ if (SwigType_isenum(type)) {
+ // RESEARCH: Make sure that we really cannot get here for anonymous enums.
+ Node *n = enumLookup(type);
+ if (n) {
+ String *enum_name = Getattr(n, "sym:name");
+
+ Node *p = parentNode(n);
+ if (p && !Strcmp(nodeType(p), "class")) {
+ // This is a nested enum.
+ String *parent_name = Getattr(p, "sym:name");
+ String *nspace = Getattr(p, "sym:nspace");
+
+ // An enum nested in a class is not written to a separate module (this
+ // would not even be possible in D), so just import the parent.
+ requireDType(nspace, parent_name);
+
+ String *module = createModuleName(nspace, parent_name);
+ if (inProxyModule(module)) {
+ type_name = NewStringf("%s.%s", parent_name, enum_name);
+ } else {
+ type_name = NewStringf("%s%s.%s.%s", package, module, parent_name, enum_name);
+ }
+ } else {
+ // A non-nested enum is written to a separate module, import it.
+ String *nspace = Getattr(n, "sym:nspace");
+ requireDType(nspace, enum_name);
+
+ String *module = createModuleName(nspace, enum_name);
+ if (inProxyModule(module)) {
+ type_name = Copy(enum_name);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, enum_name);
+ }
+ }
+ } else {
+ type_name = NewStringf("int");
+ }
+ } else {
+ Node *n = classLookup(type);
+ if (n) {
+ String *class_name = Getattr(n, "sym:name");
+ String *nspace = Getattr(n, "sym:nspace");
+ requireDType(nspace, class_name);
+
+ String *module = createModuleName(nspace, class_name);
+ if (inProxyModule(module)) {
+ type_name = Copy(class_name);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, class_name);
+ }
+ Delete(module);
+ } else {
+ // SWIG does not know anything about the type (after resolving typedefs).
+ // Just mangle the type name string like $descriptor(type) would do.
+ String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
+ requireDType(NULL, descriptor);
+
+ String *module = createModuleName(NULL, descriptor);
+ if (inProxyModule(module)) {
+ type_name = Copy(descriptor);
+ } else {
+ type_name = NewStringf("%s%s.%s", package, module, descriptor);
+ }
+ Delete(module);
+
+ // Add to hash table so that a type wrapper class can be created later.
+ Setattr(unknown_types, descriptor, type);
+
+ Delete(descriptor);
+ }
+ }
+
+ Replaceall(target, variable, type_name);
+ Delete(type_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createModuleName()
+ *
+ * Returns a string holding the name of the module to import to bring the
+ * given type in scope.
+ * --------------------------------------------------------------------------- */
+ String *createModuleName(const String *nspace, const String *type_name) const {
+ String *module;
+ if (nspace) {
+ module = NewStringf("%s.", nspace);
+ if (split_proxy_dmodule) {
+ Printv(module, type_name, NIL);
+ } else {
+ String *inner = createLastNamespaceName(nspace);
+ Printv(module, inner, NIL);
+ Delete(inner);
+ }
+ } else {
+ if (split_proxy_dmodule) {
+ module = Copy(type_name);
+ } else {
+ module = Copy(proxy_dmodule_name);
+ }
+ }
+ return module;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceModuleVariables()
+ *
+ * Replaces the $imdmodule and $module variables with their values in the
+ * target string.
+ * --------------------------------------------------------------------------- */
+ void replaceModuleVariables(String *target) const {
+ Replaceall(target, "$imdmodule", im_dmodule_fq_name);
+ Replaceall(target, "$module", proxy_dmodule_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceExcode()
+ *
+ * If a C++ method can throw a exception, additional code is added to the
+ * proxy method to check if an exception is pending so that it can be
+ * rethrown on the D side.
+ *
+ * This method replaces the $excode variable with the exception handling code
+ * in the excode typemap attribute if it »canthrow« an exception.
+ * --------------------------------------------------------------------------- */
+ void replaceExcode(Node *n, String *code, const String *typemap, Node *parameter) const {
+ String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
+ String *excode = Getattr(parameter, excode_attribute);
+ if (Getattr(n, "d:canthrow")) {
+ int count = Replaceall(code, "$excode", excode);
+ if (count < 1 || !excode) {
+ Swig_warning(WARN_D_EXCODE_MISSING, input_file, line_number,
+ "D exception may not be thrown – no $excode or excode attribute in '%s' typemap.\n",
+ typemap);
+ }
+ } else {
+ Replaceall(code, "$excode", "");
+ }
+ Delete(excode_attribute);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceImportTypeMacros()
+ *
+ * Replaces the $importtype(SomeDClass) macro with an import statement if it
+ * is required to get SomeDClass in scope for the currently generated proxy
+ * D module.
+ * --------------------------------------------------------------------------- */
+ void replaceImportTypeMacros(String *target) const {
+ // Code from replace_embedded_typemap.
+ char *start = 0;
+ while ((start = Strstr(target, "$importtype("))) {
+ char *end = 0;
+ char *param_start = 0;
+ char *param_end = 0;
+ int level = 0;
+ char *c = start;
+ while (*c) {
+ if (*c == '(') {
+ if (level == 0) {
+ param_start = c + 1;
+ }
+ level++;
+ }
+ if (*c == ')') {
+ level--;
+ if (level == 0) {
+ param_end = c;
+ end = c + 1;
+ break;
+ }
+ }
+ c++;
+ }
+
+ if (end) {
+ String *current_macro = NewStringWithSize(start, (int)(end - start));
+ String *current_param = NewStringWithSize(param_start, (int)(param_end - param_start));
+
+
+ if (inProxyModule(current_param)) {
+ Replace(target, current_macro, "", DOH_REPLACE_ANY);
+ } else {
+ String *import = createImportStatement(current_param, false);
+ Replace(target, current_macro, import, DOH_REPLACE_ANY);
+ Delete(import);
+ }
+
+ Delete(current_param);
+ Delete(current_macro);
+ } else {
+ String *current_macro = NewStringWithSize(start, (int)(c - start));
+ Swig_error(Getfile(target), Getline(target), "Syntax error in: %s\n", current_macro);
+ Replace(target, current_macro, "<error in $importtype macro>", DOH_REPLACE_ANY);
+ Delete(current_macro);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getOverloadedName()
+ * --------------------------------------------------------------------------- */
+ String *getOverloadedName(Node *n) const {
+
+ // A void* parameter is used for all wrapped classes in the wrapper code.
+ // Thus, the wrapper function names for overloaded functions are postfixed
+ // with a counter string to make them unique.
+ String *overloaded_name = Copy(Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Append(overloaded_name, Getattr(n, "sym:overname"));
+ }
+
+ return overloaded_name;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createProxyName()
+ *
+ * Returns the D class name if a type corresponds to something wrapped with a
+ * proxy class, NULL otherwise.
+ * --------------------------------------------------------------------------- */
+ String *createProxyName(SwigType *t) {
+ String *proxyname = NULL;
+ Node *n = classLookup(t);
+ if (n) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Getattr(n, "sym:name");
+
+ String *module = createModuleName(nspace, symname);
+ if (inProxyModule(module)) {
+ proxyname = Copy(symname);
+ } else {
+ proxyname = NewStringf("%s%s.%s", package, module, symname);
+ }
+ }
+ return proxyname;
+ }
+
+ String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
+ String *arg = Language::makeParameterName(n, p, arg_num, setter);
+
+ if (split_proxy_dmodule && Strncmp(arg, package, Len(arg)) == 0) {
+ // If we are in split proxy mode and the argument is named like the target
+ // package, we append an underscore to its name to avoid clashes.
+ Append(arg, "_");
+ }
+
+ return arg;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::canThrow()
+ *
+ * Determines whether the code in the typemap can throw a D exception.
+ * If so, note it for later when excodeSubstitute() is called.
+ * --------------------------------------------------------------------------- */
+ void canThrow(Node *n, const String *typemap, Node *parameter) const {
+ String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
+ String *canthrow = Getattr(parameter, canthrow_attribute);
+ if (canthrow)
+ Setattr(n, "d:canthrow", "1");
+ Delete(canthrow_attribute);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::wrapMemberFunctionAsDConst()
+ *
+ * Determines whether the member function represented by the passed node is
+ * wrapped as D »const« or not.
+ * --------------------------------------------------------------------------- */
+ bool wrapMemberFunctionAsDConst(Node *n) const {
+ if (static_flag) return false; // Never emit »const« for static member functions.
+ return GetFlag(n, "memberget") || SwigType_isconst(Getattr(n, "decl"));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::areAllOverloadsOverridden()
+ *
+ * Determines whether the class the passed function node belongs to overrides
+ * all the overlaods for the passed function node defined somewhere up the
+ * inheritance hierarchy.
+ * --------------------------------------------------------------------------- */
+ bool areAllOverloadsOverridden(Node *n) const {
+ List *base_list = Getattr(parentNode(n), "bases");
+ if (!base_list) {
+ // If the class which contains n is not derived from any other class,
+ // there cannot be any not-overridden overloads.
+ return true;
+ }
+
+ // In case of multiple base classes, skip to the one which has not been
+ // ignored.
+ // RESEARCH: Also emit a warning in case of multiple inheritance here?
+ Iterator it = First(base_list);
+ while (it.item && GetFlag(it.item, "feature:ignore")) {
+ it = Next(it);
+ }
+ Node *base_class = it.item;
+
+ if (!base_class) {
+ // If all base classes have been ignored, there cannot be one either.
+ return true;
+ }
+
+ // We try to find at least a single overload which exists in the base class
+ // so we can progress up the inheritance hierarchy even if there have been
+ // new overloads introduced after the topmost class.
+ Node *base_function = NULL;
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ for (Node *tmp = firstChild(base_class); tmp; tmp = nextSibling(tmp)) {
+ String *child_symname = Getattr(tmp, "sym:name");
+ if (child_symname && (Strcmp(child_symname, symname) == 0)) {
+ base_function = tmp;
+ break;
+ }
+ }
+ }
+
+ if (!base_function) {
+ // If there is no overload which also exists in the super class, there
+ // cannot be any base class overloads not overridden.
+ return true;
+ }
+
+ size_t base_overload_count = 0;
+ for (Node *tmp = firstSibling(base_function); tmp; tmp = Getattr(tmp, "sym:nextSibling")) {
+ if (is_protected(base_function) &&
+ !(Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode())) {
+ // If the base class function is »protected« and were are not in
+ // director mode, it is not emitted to the base class and thus we do
+ // not count it. Otherwise, we would run into issues if the visibility
+ // of some functions was changed from protected to public in a child
+ // class with the using directive.
+ continue;
+ }
+ ++base_overload_count;
+ }
+
+ return ((base_overload_count <= overridingOverloadCount(n)) &&
+ areAllOverloadsOverridden(base_function));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::checkClassBaseOver()
+ *
+ * Search a class for a method that can override the current method.
+ * --------------------------------------------------------------------------- */
+ bool checkClassBaseOver(Node *b, const String *name, ParmList *l, const int llen, const String *bname = NULL)
+ {
+ if (bname == NULL) {
+ bname = Getattr(b, "name");
+ }
+ for(Node *e = firstChild(b); e; e = nextSibling(e)) {
+ /* We look for D only fuctions! */
+ const String *ename = Getattr(e, "name");
+ const String *etype = nodeType(e);
+ if (Strcmp(etype, "extend") == 0) {
+ /* extend of class do not have a name attribute,
+ * it is the same class. */
+ if (checkClassBaseOver(e, name, l, llen, bname)) {
+ return true;
+ }
+ } else if (Strcmp(etype, "cdecl") == 0 || Strcmp(etype, "using") == 0) {
+ /* 'using' is marked in markDOverride() same as 'cdecl' */
+ if (Strcmp(name, ename) == 0) {
+ if (GetFlag(e, "d:override_property")) {
+ return true;
+ }
+ /* Do we need a full compare of ParmList? How about in typemaps? */
+ ParmList *el = Getattr(e, "d:override_parms");
+ const int ellen = ParmList_len(el);
+ if (GetFlag(e, "d:can_override") && ellen == llen) {
+ bool eq = true;
+ String *detd = NewString("");
+ if (llen > 0) {
+ for(ParmList *le = el, *ln = l; eq && le && ln; le = nextSibling(le), ln = nextSibling(ln)) {
+ const String *ntd = Getattr(ln, "d:type");
+ const String *etd = Getattr(le, "d:type");
+ Printf(detd, "%s.%s", etd, etd);
+ /* Parameter types are equal, or the type is 'class.class' */
+ eq = etd && ntd && (Strcmp(ntd, etd) == 0 || Strcmp(ntd, detd) == 0);
+ }
+ }
+ Delete(detd);
+ if (eq) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::checkBaseOver()
+ *
+ * Traverse all base classes and look for a method the current method override.
+ * --------------------------------------------------------------------------- */
+ bool checkBaseOver(Node *c, const String *name, ParmList *l, const int llen)
+ {
+ // * Member template functions?
+ if (!c) {
+ return false;
+ }
+ List *bases = Getattr(c, "bases");
+ if (!bases) {
+ return false;
+ }
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ if (checkClassBaseOver(b, name, l, llen)) {
+ return true;
+ }
+ if (checkBaseOver(b, name, l, llen)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::markDOverride()
+ *
+ * Mark current method for methods in derived classes.
+ * --------------------------------------------------------------------------- */
+ void markDOverride(Node *n, const String *name, ParmList *l, Node *p, const String *pname, const String *ptype) {
+ if (!pname && Strcmp(ptype, "extend") == 0) {
+ Node *pp = parentNode(p);
+ if (pp) {
+ pname = Getattr(pp, "name");
+ }
+ }
+ for(Node *e = firstChild(p); e; e = nextSibling(e)) {
+ /* Am I in my class? */
+ if (n == e) {
+ SetFlag(n, "d:can_override");
+ if (wrapping_member_flag) {
+ SetFlag(n, "d:override_property");
+ } else {
+ Setattr(n, "d:override_parms", CopyParmList(l));
+ }
+ return;
+ }
+ }
+ /*
+ * I am a 'using' method.
+ * Our method is using a method definition from a different class.
+ * We need to mark the original 'using' method in our class,
+ * as this node is not accessibale in derived classes.
+ */
+ for(Node *e = firstChild(p); e; e = nextSibling(e)) {
+ const String *ename = Getattr(e, "name");
+ const String *ntype = nodeType(e);
+ if (ename && Strcmp(ename, name) == 0 && ntype && Strcmp(ntype, "using") == 0) {
+ SetFlag(e, "d:can_override");
+ Setattr(e, "d:override_parms", CopyParmList(l));
+ return;
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::isDOverride()
+ *
+ * Override should be used for override D existing method.
+ * Class D methods, non static and non private.
+ * Check if current method override,
+ * anf mark it for derived classes use.
+ * --------------------------------------------------------------------------- */
+ bool isDOverride(Node *n, ParmList *l) {
+ if (is_smart_pointer()) {
+ /* Smart pointer classes do not mirror the inheritance hierarchy of the
+ * underlying pointer type, so no override required. */
+ return false;
+ }
+ if (static_flag) { /* Static are never override */
+ return false;
+ }
+ Node *p = parentNode(n);
+ if (!p) {
+ return false;
+ }
+ const String *name = Getattr(n, "name");
+ const int llen = ParmList_len(l);
+ const String *ptype = nodeType(p);
+ const String *pname = Getattr(p, "name");
+ markDOverride(n, name, l, p, pname, ptype);
+ if (Strcmp(ptype, "extend") == 0) {
+ /* The 'bases' are in the class we extend */
+ p = parentNode(p);
+ }
+ return checkBaseOver(p, name, l, llen);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::overridingOverloadCount()
+ *
+ * Given a member function node, this function counts how many of the
+ * overloads of the function (including itself) override a function in the
+ * base class.
+ * --------------------------------------------------------------------------- */
+ size_t overridingOverloadCount(Node *n) const {
+ size_t result = 0;
+
+ Node *tmp = firstSibling(n);
+ do {
+ // KLUDGE: We also have to count the function if the access attribute is
+ // not present, since this means that it has been promoted into another
+ // protection level in the base class with the C++ »using« directive, and
+ // is thus taken into account when counting the base class overloads, even
+ // if it is not marked as »override« by the SWIG parser.
+ if (Getattr(n, "override") || !Getattr(n, "access")) {
+ ++result;
+ }
+ } while((tmp = Getattr(tmp, "sym:nextSibling")));
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::firstSibling()
+ *
+ * Returns the first sibling of the passed node.
+ * --------------------------------------------------------------------------- */
+ Node *firstSibling(Node *n) const {
+ Node *result = n;
+ while (Node *tmp = Getattr(result, "sym:previousSibling")) {
+ result = tmp;
+ }
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::indentCode()
+ *
+ * Helper function to indent a code (string) by one level.
+ * --------------------------------------------------------------------------- */
+ void indentCode(String* code) const {
+ Replaceall(code, "\n", "\n ");
+ Replaceall(code, " \n", "\n");
+ Chop(code);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::emitBanner()
+ * --------------------------------------------------------------------------- */
+ void emitBanner(File *f) const {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
+ Printv(f, common_begin_code, NIL);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getOutDtype()
+ *
+ * Returns the return (out) D type and check the Dtype out typemap.
+ * --------------------------------------------------------------------------- */
+ String *getOutDtype(Node *n) {
+ String *result = lookupDTypemap(n, "dtype");
+ if (result) {
+ String *dtypeout = Copy(Getattr(n, "tmap:dtype:out"));
+ if (dtypeout) {
+ /* The type in the out attribute of the typemap overrides the type
+ * in the dtype typemap. */
+ Delete(result);
+ result = dtypeout;
+ replaceClassname(result, Getattr(n, "type"));
+ }
+ }
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::outputDirectory()
+ *
+ * Returns the directory to write the D modules for the given namespace to and
+ * and creates the subdirectory if it doesn't exist.
+ * --------------------------------------------------------------------------- */
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(dmodule_directory);
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ Exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::proxyCodeBuffer()
+ *
+ * Returns the buffer to write proxy code for the given namespace to.
+ * --------------------------------------------------------------------------- */
+ String *proxyCodeBuffer(String *nspace) {
+ if (!nspace) {
+ return proxy_dmodule_code;
+ }
+
+ Hash *hash = Getattr(nspace_proxy_dmodules, nspace);
+ if (!hash) {
+ hash = NewHash();
+ Setattr(hash, "code", NewString(""));
+ Setattr(hash, "imports", NewString(""));
+ Setattr(nspace_proxy_dmodules, nspace, hash);
+ }
+ return Getattr(hash, "code");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::proxyCodeBuffer()
+ *
+ * Returns the buffer to write imports for the proxy code for the given
+ * namespace to.
+ * --------------------------------------------------------------------------- */
+ String *proxyImportsBuffer(String *nspace) {
+ if (!nspace) {
+ return proxy_dmodule_imports;
+ }
+
+ Hash *hash = Getattr(nspace_proxy_dmodules, nspace);
+ if (!hash) {
+ hash = NewHash();
+ Setattr(hash, "code", NewString(""));
+ Setattr(hash, "imports", NewString(""));
+ Setattr(nspace_proxy_dmodules, nspace, hash);
+ }
+ return Getattr(hash, "imports");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createFirstNamespaceName()
+ *
+ * Returns a new string containing the name of the outermost namespace, e.g.
+ * »A« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createFirstNamespaceName(const String *nspace) const {
+ char *tmp = Char(nspace);
+ char *c = tmp;
+ char *co = 0;
+ if (!strchr(c, '.'))
+ return 0;
+
+ co = c + Len(nspace);
+
+ while (*c && (c != co)) {
+ if (*c == '.') {
+ break;
+ }
+ c++;
+ }
+ if (!*c || (c == tmp)) {
+ return NULL;
+ }
+ return NewStringWithSize(tmp, (int)(c - tmp));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createLastNamespaceName()
+ *
+ * Returns a new string containing the name of the innermost namespace, e.g.
+ * »C« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createLastNamespaceName(const String *nspace) const {
+ if (!nspace) return NULL;
+ char *c = Char(nspace);
+ char *cc = c;
+ if (!strchr(c, '.'))
+ return NewString(nspace);
+
+ while (*c) {
+ if (*c == '.') {
+ cc = c;
+ }
+ ++c;
+ }
+ return NewString(cc + 1);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createOuterNamespaceNames()
+ *
+ * Returns a new string containing the name of the outer namespace, e.g.
+ * »A.B« for the argument »A.B.C«.
+ * --------------------------------------------------------------------------- */
+ String *createOuterNamespaceNames(const String *nspace) const {
+ if (!nspace) return NULL;
+ char *tmp = Char(nspace);
+ char *c = tmp;
+ char *cc = c;
+ if (!strchr(c, '.'))
+ return NULL;
+
+ while (*c) {
+ if (*c == '.') {
+ cc = c;
+ }
+ ++c;
+ }
+ if (cc == tmp) {
+ return NULL;
+ }
+ return NewStringWithSize(tmp, (int)(cc - tmp));
+ }
+};
+
+static Language *new_swig_d() {
+ return new D();
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_d() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+extern "C" Language *swig_d(void) {
+ return new_swig_d();
+}
+
+/* -----------------------------------------------------------------------------
+ * Usage information displayed at the command line.
+ * ----------------------------------------------------------------------------- */
+const char *D::usage = "\
+D Options (available with -d)\n\
+ -d2 - Generate code for D2/Phobos (The default, left for backward compatibility)\n\
+ -package <pkg> - Write generated D modules into package <pkg>\n\
+ -splitproxy - Write each D type to a dedicated file instead of\n\
+ generating a single proxy D module.\n\
+ -wrapperlibrary <wl> - Set the name of the wrapper library to <wl>\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/directors.cxx b/contrib/tools/swig/Source/Modules/directors.cxx
new file mode 100644
index 00000000000..14e2e846619
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/directors.cxx
@@ -0,0 +1,270 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * directors.cxx
+ *
+ * Director support functions.
+ * Not all of these may be necessary, and some may duplicate existing functionality
+ * in SWIG. --MR
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+/* -----------------------------------------------------------------------------
+ * Swig_csuperclass_call()
+ *
+ * Generates a fully qualified method call, including the full parameter list.
+ * e.g. "base::method(i, j)"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_csuperclass_call(String *base, String *method, ParmList *l) {
+ String *call = NewString("");
+ int arg_idx = 0;
+ Parm *p;
+ if (base) {
+ Printf(call, "%s::", base);
+ }
+ Printf(call, "%s(", method);
+ for (p = l; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+ if (!pname && Cmp(Getattr(p, "type"), "void")) {
+ pname = NewString("");
+ Printf(pname, "arg%d", arg_idx++);
+ }
+ if (p != l)
+ Printf(call, ", ");
+ Printv(call, pname, NIL);
+ }
+ Printf(call, ")");
+ return call;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_class_declaration()
+ *
+ * Generate the start of a class/struct declaration.
+ * e.g. "class myclass"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_class_declaration(Node *n, String *name) {
+ if (!name) {
+ name = Getattr(n, "sym:name");
+ }
+ String *result = NewString("");
+ String *kind = Getattr(n, "kind");
+ Printf(result, "%s %s", kind, name);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_class_name()
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_class_name(Node *n) {
+ String *name;
+ name = Copy(Getattr(n, "sym:name"));
+ return name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_declaration()
+ *
+ * Generate the full director class declaration, complete with base classes.
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_director_declaration(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *directorname = Language::instance()->directorClassName(n);
+ String *base = Getattr(n, "classtype");
+ String *declaration = Swig_class_declaration(n, directorname);
+
+ Printf(declaration, " : public %s, public Swig::Director {\n", base);
+ Delete(classname);
+ Delete(directorname);
+ return declaration;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_method_call()
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms) {
+ String *func;
+ int comma = 0;
+ Parm *p = parms;
+ SwigType *pt;
+ String *nname;
+
+ func = NewString("");
+ nname = SwigType_namestr(name);
+ Printf(func, "%s(", nname);
+ while (p) {
+ String *pname;
+ pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ if (comma)
+ Printf(func, ",");
+ pname = Getattr(p, "name");
+ Printf(func, "%s", pname);
+ comma = 1;
+ }
+ p = nextSibling(p);
+ }
+ Printf(func, ")");
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_method_decl()
+ *
+ * Return a stringified version of a C/C++ declaration.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args) {
+ String *result = NewString("");
+ bool conversion_operator = Strstr(id, "operator ") != 0 && !return_base_type;
+
+ Parm *parm = args;
+ int arg_idx = 0;
+ while (parm) {
+ String *type = Getattr(parm, "type");
+ String *name = Getattr(parm, "name");
+ if (!name && Cmp(type, "void")) {
+ name = NewString("");
+ Printf(name, "arg%d", arg_idx++);
+ Setattr(parm, "name", name);
+ }
+ parm = nextSibling(parm);
+ }
+
+ String *rettype = Copy(decl);
+ String *quals = SwigType_pop_function_qualifiers(rettype);
+ String *qualifiers = 0;
+ if (quals)
+ qualifiers = SwigType_str(quals, 0);
+
+ String *popped_decl = SwigType_pop_function(rettype);
+ if (return_base_type)
+ Append(rettype, return_base_type);
+
+ if (!conversion_operator) {
+ SwigType *rettype_stripped = SwigType_strip_qualifiers(rettype);
+ String *rtype = SwigType_str(rettype, 0);
+ Append(result, rtype);
+ if ((SwigType_issimple(rettype_stripped) && return_base_type) || SwigType_isqualifier(rettype))
+ Append(result, " ");
+ Delete(rtype);
+ Delete(rettype_stripped);
+ }
+
+ if (id)
+ Append(result, id);
+
+ String *args_string = default_args ? ParmList_str_defaultargs(args) : ParmList_str(args);
+ Printv(result, "(", args_string, ")", NIL);
+
+ if (qualifiers)
+ Printv(result, " ", qualifiers, NIL);
+
+ Delete(args_string);
+ Delete(popped_decl);
+ Delete(qualifiers);
+ Delete(quals);
+ Delete(rettype);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_emit_dynamic_cast()
+ *
+ * In order to call protected virtual director methods from the target language, we need
+ * to add an extra dynamic_cast to call the public C++ wrapper in the director class.
+ * Also for non-static protected members when the allprotected option is on.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f) {
+ // TODO: why is the storage element removed in staticmemberfunctionHandler ??
+ if ((!is_public(n) && (is_member_director(n) || GetFlag(n, "explicitcall"))) ||
+ (is_non_virtual_protected_access(n) && !(Swig_storage_isstatic_custom(n, "staticmemberfunctionHandler:storage") ||
+ Swig_storage_isstatic(n))
+ && !Equal(nodeType(n), "constructor"))) {
+ Node *parent = Getattr(n, "parentNode");
+ String *dirname;
+ String *dirdecl;
+ dirname = Language::instance()->directorClassName(parent);
+ dirdecl = NewStringf("%s *darg = 0", dirname);
+ Wrapper_add_local(f, "darg", dirdecl);
+ Printf(f->code, "darg = dynamic_cast<%s *>(arg1);\n", dirname);
+ Delete(dirname);
+ Delete(dirdecl);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_parms_fixup()
+ *
+ * For each parameter in the C++ member function, copy the parameter name
+ * to its "lname"; this ensures that Swig_typemap_attach_parms() will do
+ * the right thing when it sees strings like "$1" in "directorin" typemaps.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_director_parms_fixup(ParmList *parms) {
+ Parm *p;
+ int i;
+ for (i = 0, p = parms; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname = 0;
+
+ if (!arg && !Equal(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i);
+ Setattr(p, "name", lname);
+ } else
+ lname = Copy(arg);
+
+ Setattr(p, "lname", lname);
+ Delete(lname);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_director_can_unwrap()
+ *
+ * Determine whether a function's return type can be returned as an existing
+ * target language object instead of creating a new target language object.
+ * Must be a director class and only for return by pointer or reference only
+ * (not by value or by pointer to pointer etc).
+ * ----------------------------------------------------------------------------- */
+
+bool Swig_director_can_unwrap(Node *n) {
+
+ // FIXME: this will not try to unwrap directors returned as non-director
+ // base class pointers!
+
+ bool unwrap = false;
+
+ String *type = Getattr(n, "type");
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ SwigType *t1 = SwigType_strip_qualifiers(t);
+ SwigType *prefix = SwigType_prefix(t1);
+
+ if (Strcmp(prefix, "p.") == 0 || Strcmp(prefix, "r.") == 0) {
+ Node *parent = Swig_methodclass(n);
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, t1);
+ if (target)
+ unwrap = true;
+ }
+
+ Delete(prefix);
+ Delete(t1);
+ Delete(t);
+
+ return unwrap;
+}
diff --git a/contrib/tools/swig/Source/Modules/emit.cxx b/contrib/tools/swig/Source/Modules/emit.cxx
new file mode 100644
index 00000000000..7039196d37a
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/emit.cxx
@@ -0,0 +1,534 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * emit.cxx
+ *
+ * Useful functions for emitting various pieces of code.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+/* -----------------------------------------------------------------------------
+ * emit_return_variable()
+ *
+ * Emits a variable declaration for a function return value.
+ * The variable name is always called result.
+ * n => Node of the method being wrapped
+ * rt => the return type
+ * f => the wrapper to generate code into
+ * ----------------------------------------------------------------------------- */
+
+void emit_return_variable(Node *n, SwigType *rt, Wrapper *f) {
+
+ if (!GetFlag(n, "tmap:out:optimal")) {
+ if (rt && (SwigType_type(rt) != T_VOID)) {
+ SwigType *vt = cplus_value_type(rt);
+ SwigType *tt = vt ? vt : rt;
+ SwigType *lt = SwigType_ltype(tt);
+ String *lstr = SwigType_str(lt, Swig_cresult_name());
+ if (SwigType_ispointer(lt)) {
+ Wrapper_add_localv(f, Swig_cresult_name(), lstr, "= 0", NULL);
+ } else {
+ Wrapper_add_local(f, Swig_cresult_name(), lstr);
+ }
+ if (vt) {
+ Delete(vt);
+ }
+ Delete(lt);
+ Delete(lstr);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_parameter_variables()
+ *
+ * Emits a list of variable declarations for function parameters.
+ * The variable names are always called arg1, arg2, etc...
+ * l => the parameter list
+ * f => the wrapper to generate code into
+ * ----------------------------------------------------------------------------- */
+
+void emit_parameter_variables(ParmList *l, Wrapper *f) {
+
+ Parm *p;
+ String *tm;
+
+ /* Emit function arguments */
+ Swig_cargs(f, l);
+
+ /* Attach typemaps to parameters */
+ Swig_typemap_attach_parms("default", l, f);
+ Swig_typemap_attach_parms("arginit", l, f);
+
+ /* Apply the arginit and default */
+ p = l;
+ while (p) {
+ tm = Getattr(p, "tmap:arginit");
+ if (tm) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:arginit:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Apply the default typemap */
+ p = l;
+ while (p) {
+ tm = Getattr(p, "tmap:default");
+ if (tm) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:default:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_attach_parmmaps()
+ *
+ * Attach the standard parameter related typemaps.
+ * ----------------------------------------------------------------------------- */
+
+void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
+ Swig_typemap_attach_parms("in", l, f);
+ Swig_typemap_attach_parms("typecheck", l, 0);
+ Swig_typemap_attach_parms("argout", l, f);
+ Swig_typemap_attach_parms("check", l, f);
+ Swig_typemap_attach_parms("freearg", l, f);
+
+ {
+ /* Handle in typemaps with numinputs=0. */
+ Parm *p = l;
+ while (p) {
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Perform a sanity check on "in" and "freearg" typemaps. These
+ must exactly match to avoid chaos. If a mismatch occurs, we
+ nuke the freearg typemap */
+ {
+ Parm *p = l;
+ Parm *npin, *npfreearg;
+ while (p) {
+ npin = Getattr(p, "tmap:in:next");
+
+ if (Getattr(p, "tmap:freearg")) {
+ npfreearg = Getattr(p, "tmap:freearg:next");
+ if (npin != npfreearg) {
+ while (p != npin) {
+ Delattr(p, "tmap:freearg");
+ Delattr(p, "tmap:freearg:next");
+ p = nextSibling(p);
+ }
+ }
+ }
+ p = npin;
+ }
+ }
+
+ /* Check for variable length arguments with no input typemap.
+ If no input is defined, we set this to ignore and print a
+ message.
+ */
+ {
+ Parm *p = l;
+ Parm *lp = 0;
+ while (p) {
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+ lp = p;
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+ if (SwigType_isvarargs(Getattr(p, "type"))) {
+ Swig_warning(WARN_LANG_VARARGS, input_file, line_number, "Variable length arguments discarded.\n");
+ Setattr(p, "tmap:in", "");
+ }
+ lp = 0;
+ p = nextSibling(p);
+ }
+
+ /* Check if last input argument is variable length argument */
+ if (lp) {
+ p = lp;
+ while (p) {
+ if (SwigType_isvarargs(Getattr(p, "type"))) {
+ // Mark the head of the ParmList that it has varargs
+ Setattr(l, "emit:varargs", lp);
+//Printf(stdout, "setting emit:varargs %s ... %s +++ %s\n", Getattr(l, "emit:varargs"), Getattr(l, "type"), Getattr(p, "type"));
+ break;
+ }
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /*
+ * An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent
+ * target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer
+ * are seen as equivalent types in the target language.
+ */
+ {
+ Parm *p = l;
+ while (p) {
+ String *tm = Getattr(p, "tmap:typecheck");
+ if (tm) {
+ String *equivalent = Getattr(p, "tmap:typecheck:equivalent");
+ if (equivalent) {
+ String *precedence = Getattr(p, "tmap:typecheck:precedence");
+ if (precedence && Strcmp(precedence, "0") != 0)
+ Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0));
+ SwigType *cpt = Swig_cparse_type(equivalent);
+ if (cpt) {
+ Setattr(p, "equivtype", cpt);
+ Delete(cpt);
+ } else {
+ Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+ p = Getattr(p, "tmap:typecheck:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_num_arguments()
+ *
+ * Calculate the total number of arguments. This function is safe for use
+ * with multi-argument typemaps which may change the number of arguments in
+ * strange ways.
+ * ----------------------------------------------------------------------------- */
+
+int emit_num_arguments(ParmList *parms) {
+ Parm *p = parms;
+ int nargs = 0;
+
+ while (p) {
+ if (Getattr(p, "tmap:in")) {
+ nargs += GetInt(p, "tmap:in:numinputs");
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
+ /*
+ if (parms && (p = Getattr(parms,"emit:varargs"))) {
+ if (!nextSibling(p)) {
+ nargs--;
+ }
+ }
+ */
+ return nargs;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_num_required()
+ *
+ * Computes the number of required arguments. This function is safe for
+ * use with multi-argument typemaps and knows how to skip over everything
+ * properly. Note that parameters with default values are counted unless
+ * the compact default args option is on.
+ * ----------------------------------------------------------------------------- */
+
+int emit_num_required(ParmList *parms) {
+ Parm *p = parms;
+ int nargs = 0;
+ Parm *first_default_arg = 0;
+ int compactdefargs = ParmList_is_compactdefargs(p);
+
+ while (p) {
+ if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ if (Getattr(p, "tmap:default"))
+ break;
+ if (Getattr(p, "value")) {
+ if (!first_default_arg)
+ first_default_arg = p;
+ if (compactdefargs)
+ break;
+ }
+ nargs += GetInt(p, "tmap:in:numinputs");
+ if (Getattr(p, "tmap:in")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* Print error message for non-default arguments following default arguments */
+ /* The error message is printed more than once with most language modules, this ought to be fixed */
+ if (first_default_arg) {
+ p = first_default_arg;
+ while (p) {
+ if (Getattr(p, "tmap:in") && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ if (!Getattr(p, "value") && (!Getattr(p, "tmap:default"))) {
+ Swig_error(Getfile(p), Getline(p), "Non-optional argument '%s' follows an optional argument.\n", Getattr(p, "name"));
+ }
+ if (Getattr(p, "tmap:in")) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+ }
+
+ /* DB 04/02/2003: Not sure this is necessary with tmap:in:numinputs */
+ /*
+ if (parms && (p = Getattr(parms,"emit:varargs"))) {
+ if (!nextSibling(p)) {
+ nargs--;
+ }
+ }
+ */
+ return nargs;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_isvarargs()
+ *
+ * Checks if a ParmList is a parameter list containing varargs.
+ * This function requires emit_attach_parmmaps to have been called beforehand.
+ * ----------------------------------------------------------------------------- */
+
+int emit_isvarargs(ParmList *p) {
+ if (!p)
+ return 0;
+ if (Getattr(p, "emit:varargs"))
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * emit_isvarargs_function()
+ *
+ * Checks for varargs in a function/constructor (can be overloaded)
+ * ----------------------------------------------------------------------------- */
+
+bool emit_isvarargs_function(Node *n) {
+ bool has_varargs = false;
+ Node *over = Getattr(n, "sym:overloaded");
+ if (over) {
+ for (Node *sibling = over; sibling; sibling = Getattr(sibling, "sym:nextSibling")) {
+ if (ParmList_has_varargs(Getattr(sibling, "parms"))) {
+ has_varargs = true;
+ break;
+ }
+ }
+ } else {
+ has_varargs = ParmList_has_varargs(Getattr(n, "parms")) ? true : false;
+ }
+ return has_varargs;
+}
+
+/* -----------------------------------------------------------------------------
+ * void emit_mark_vararg_parms()
+ *
+ * Marks the vararg parameters which are to be ignored.
+ * Vararg parameters are marked as ignored if there is no 'in' varargs (...)
+ * typemap.
+ * ----------------------------------------------------------------------------- */
+
+void emit_mark_varargs(ParmList *l) {
+ Parm *p = l;
+ while (p) {
+ if (SwigType_isvarargs(Getattr(p, "type")))
+ if (!Getattr(p, "tmap:in"))
+ Setattr(p, "varargs:ignore", "1");
+ p = nextSibling(p);
+ }
+}
+
+#if 0
+/* replace_contract_args. This function replaces argument names in contract
+ specifications. Used in conjunction with the %contract directive. */
+
+static void replace_contract_args(Parm *cp, Parm *rp, String *s) {
+ while (cp && rp) {
+ String *n = Getattr(cp, "name");
+ if (n) {
+ Replace(s, n, Getattr(rp, "lname"), DOH_REPLACE_ID);
+ }
+ cp = nextSibling(cp);
+ rp = nextSibling(rp);
+ }
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * int emit_action_code()
+ *
+ * Emits action code for a wrapper. Adds in exception handling code (%exception).
+ * eaction -> the action code to emit
+ * wrappercode -> the emitted code (output)
+ * ----------------------------------------------------------------------------- */
+int emit_action_code(Node *n, String *wrappercode, String *eaction) {
+ assert(Getattr(n, "wrap:name"));
+
+ /* Look for except feature (%exception) */
+ String *tm = GetFlagAttr(n, "feature:except");
+ if (tm)
+ tm = Copy(tm);
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ if (Strchr(tm, '$')) {
+ Swig_replace_special_variables(n, parentNode(n), tm);
+ Replaceall(tm, "$function", eaction); // deprecated
+ Replaceall(tm, "$action", eaction);
+ }
+ Printv(wrappercode, tm, "\n", NIL);
+ Delete(tm);
+ return 1;
+ } else {
+ Printv(wrappercode, eaction, "\n", NIL);
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * int emit_action()
+ *
+ * Emits the call to the wrapped function.
+ * Adds in exception specification exception handling and %exception code.
+ * ----------------------------------------------------------------------------- */
+String *emit_action(Node *n) {
+ String *actioncode = NewStringEmpty();
+ String *tm;
+ String *action;
+ String *wrap;
+ ParmList *catchlist = Getattr(n, "catchlist");
+
+ /* Look for fragments */
+ {
+ String *fragment = Getattr(n, "feature:fragment");
+ if (fragment) {
+ char *c, *tok;
+ String *t = Copy(fragment);
+ c = Char(t);
+ tok = strtok(c, ",");
+ while (tok) {
+ String *fname = NewString(tok);
+ Setfile(fname, Getfile(n));
+ Setline(fname, Getline(n));
+ Swig_fragment_emit(fname);
+ Delete(fname);
+ tok = strtok(NULL, ",");
+ }
+ Delete(t);
+ }
+ }
+
+ /* Emit wrapper code (if any) */
+ wrap = Getattr(n, "wrap:code");
+ if (wrap && Swig_filebyname("header") != Getattr(n, "wrap:code:done")) {
+ File *f_code = Swig_filebyname("header");
+ if (f_code) {
+ Printv(f_code, wrap, NIL);
+ }
+ Setattr(n, "wrap:code:done", f_code);
+ }
+
+ action = Getattr(n, "feature:action");
+ if (!action)
+ action = Getattr(n, "wrap:action");
+ assert(action != 0);
+
+ /* Emit contract code (if any) */
+ if (Swig_contract_mode_get()) {
+ /* Preassertion */
+ tm = Getattr(n, "contract:preassert");
+ if (Len(tm)) {
+ Printv(actioncode, tm, "\n", NIL);
+ }
+ }
+ /* Exception handling code */
+
+ /* saves action -> eaction for postcatching exception */
+ String *eaction = NewString("");
+
+ /* If we are in C++ mode and there is an exception specification. We're going to
+ enclose the block in a try block */
+ if (catchlist) {
+ Printf(eaction, "try {\n");
+ }
+
+ String *preaction = Getattr(n, "wrap:preaction");
+ if (preaction)
+ Printv(eaction, preaction, NIL);
+
+ Printv(eaction, action, NIL);
+
+ String *postaction = Getattr(n, "wrap:postaction");
+ if (postaction)
+ Printv(eaction, postaction, NIL);
+
+ if (catchlist) {
+ int unknown_catch = 0;
+ int has_varargs = 0;
+ Printf(eaction, "}");
+ for (Parm *ep = catchlist; ep; ep = nextSibling(ep)) {
+ String *em = Swig_typemap_lookup("throws", ep, "_e", 0);
+ if (em) {
+ SwigType *et = Getattr(ep, "type");
+ SwigType *etr = SwigType_typedef_resolve_all(et);
+ if (SwigType_isreference(etr) || SwigType_ispointer(etr) || SwigType_isarray(etr)) {
+ Printf(eaction, " catch(%s) {", SwigType_str(et, "_e"));
+ } else if (SwigType_isvarargs(etr)) {
+ Printf(eaction, " catch(...) {");
+ has_varargs = 1;
+ } else {
+ Printf(eaction, " catch(%s) {", SwigType_str(et, "&_e"));
+ }
+ Printv(eaction, em, "\n", NIL);
+ Printf(eaction, "}");
+ } else {
+ Swig_warning(WARN_TYPEMAP_THROW, Getfile(n), Getline(n), "No 'throws' typemap defined for exception type '%s'\n", SwigType_str(Getattr(ep, "type"), 0));
+ unknown_catch = 1;
+ }
+ }
+ if (unknown_catch && !has_varargs) {
+ Printf(eaction, " catch(...) {\nthrow;\n}");
+ }
+ }
+
+ /* emit the except feature code */
+ emit_action_code(n, actioncode, eaction);
+
+ Delete(eaction);
+
+ /* Emit contract code (if any) */
+ if (Swig_contract_mode_get()) {
+ /* Postassertion */
+ tm = Getattr(n, "contract:postassert");
+ if (Len(tm)) {
+ Printv(actioncode, tm, "\n", NIL);
+ }
+ }
+
+ return actioncode;
+}
diff --git a/contrib/tools/swig/Source/Modules/go.cxx b/contrib/tools/swig/Source/Modules/go.cxx
new file mode 100644
index 00000000000..f3fb956cc51
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/go.cxx
@@ -0,0 +1,5669 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * go.cxx
+ *
+ * Go language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* ----------------------------------------------------------------------
+ * siphash()
+ *
+ * 64-bit SipHash-2-4 to generate unique id for each module
+ * ---------------------------------------------------------------------- */
+
+// An unsigned 64-bit integer that works on a 32-bit host.
+typedef struct {
+ // Assume unsigned long is at least 32 bits.
+ unsigned long hi;
+ unsigned long lo;
+} swig_uint64;
+
+// Rotate v left by bits, which must be <= 32.
+static inline void _rotl(swig_uint64 *v, int bits) {
+ assert(bits <= 32);
+ unsigned long tmp = v->hi;
+ if (bits == 32) {
+ v->hi = v->lo;
+ v->lo = tmp;
+ } else {
+ v->hi = (tmp << bits) | ((0xfffffffful & v->lo) >> (32 - bits));
+ v->lo = (v->lo << bits) | ((0xfffffffful & tmp) >> (32 - bits));
+ }
+}
+
+// dst ^= src
+static inline void _xor(swig_uint64 *dst, swig_uint64 *src) {
+ dst->lo ^= src->lo;
+ dst->hi ^= src->hi;
+}
+
+// dst += src
+static inline void _add(swig_uint64 *dst, swig_uint64 *src) {
+ dst->lo += src->lo;
+ dst->hi += src->hi + ((dst->lo & 0xfffffffful) < (src->lo&0xfffffffful) ? 1 : 0);
+}
+#define SIPROUND \
+ do { \
+ _add(&v0, &v1); _rotl(&v1, 13); _xor(&v1, &v0); _rotl(&v0, 32); \
+ _add(&v2, &v3); _rotl(&v3, 16); _xor(&v3, &v2); \
+ _add(&v0, &v3); _rotl(&v3, 21); _xor(&v3, &v0); \
+ _add(&v2, &v1); _rotl(&v1, 17); _xor(&v1, &v2); _rotl(&v2, 32); \
+ } while(0)
+
+// Set out to the hash of inc/inlen.
+static void siphash(swig_uint64 *out, const char *inc, unsigned long inlen) {
+ /* "somepseudorandomlygeneratedbytes" */
+ swig_uint64 v0 = {0x736f6d65UL, 0x70736575UL};
+ swig_uint64 v1 = {0x646f7261UL, 0x6e646f6dUL};
+ swig_uint64 v2 = {0x6c796765UL, 0x6e657261UL};
+ swig_uint64 v3 = {0x74656462UL, 0x79746573UL};
+ swig_uint64 b;
+ /* hard-coded k. */
+ swig_uint64 k0 = {0x07060504UL, 0x03020100UL};
+ swig_uint64 k1 = {0x0F0E0D0CUL, 0x0B0A0908UL};
+ int i;
+ const int cROUNDS = 2, dROUNDS = 4;
+ const unsigned char *in = (const unsigned char *)inc;
+ const unsigned char *end = in + inlen - (inlen % 8);
+ int left = inlen & 7;
+ _xor(&v3, &k1); _xor(&v2, &k0); _xor(&v1, &k1); _xor(&v0, &k0);
+ for (; in != end; in += 8) {
+ b.hi = 0; b.lo = 0;
+ for (i = 0; i < 4; i++) {
+ b.lo |= ((unsigned long)in[i]) << (8*i);
+ }
+ for (i = 0; i < 4; i++) {
+ b.hi |= ((unsigned long)in[i+4]) << (8*i);
+ }
+ _xor(&v3, &b);
+ for (i = 0; i < cROUNDS; i++) {
+ SIPROUND;
+ }
+ _xor(&v0, &b);
+ }
+ b.hi = (inlen & 0xff)<<24; b.lo = 0;
+ for (; left; left--) {
+ if (left > 4) {
+ b.hi |= ((unsigned long)in[left-1]) << (8*left-8-32);
+ } else {
+ b.lo |= ((unsigned long)in[left-1]) << (8*left-8);
+ }
+ }
+ _xor(&v3, &b);
+ for(i=0; i<cROUNDS; i++) {
+ SIPROUND;
+ }
+ _xor(&v0, &b); v2.lo ^= 0xff;
+ for(i=0; i<dROUNDS; i++) {
+ SIPROUND;
+ }
+ out->lo = 0; out->hi = 0;
+ _xor(out, &v0); _xor(out, &v1); _xor(out, &v2); _xor(out, &v3);
+}
+#undef SIPROUND
+
+class GO:public Language {
+ static const char *const usage;
+
+ // Go package name.
+ String *package;
+ // SWIG module name.
+ String *module;
+ // Flag for generating gccgo output.
+ bool gccgo_flag;
+ // Prefix to use with gccgo.
+ String *go_prefix;
+ // -fgo-prefix option.
+ String *prefix_option;
+ // -fgo-pkgpath option.
+ String *pkgpath_option;
+ // Prefix for translating %import directive to import statements.
+ String *import_prefix;
+ // Whether to use a shared library.
+ bool use_shlib;
+ // Name of shared library to import.
+ String *soname;
+ // Size in bits of the Go type "int". 0 if not specified.
+ int intgo_type_size;
+
+ /* Output files */
+ File *f_c_begin;
+ File *f_go_begin;
+
+ /* Output fragments */
+ File *f_c_runtime;
+ File *f_c_header;
+ File *f_c_wrappers;
+ File *f_c_init;
+ File *f_c_directors;
+ File *f_c_directors_h;
+ File *f_go_imports;
+ File *f_go_runtime;
+ File *f_go_header;
+ File *f_go_wrappers;
+ File *f_go_directors;
+ File *f_cgo_comment;
+ File *f_cgo_comment_typedefs;
+
+ // True if we imported a module.
+ bool saw_import;
+ // If not NULL, name of import package being processed.
+ String *imported_package;
+ // Build interface methods while handling a class. This is only
+ // non-NULL when we are handling methods.
+ String *interfaces;
+ // The class node while handling a class. This is only non-NULL
+ // when we are handling methods.
+ Node *class_node;
+ // The class name while handling a class. This is only non-NULL
+ // when we are handling methods. This is the name of the class as
+ // SWIG sees it.
+ String *class_name;
+ // The receiver name while handling a class. This is only non-NULL
+ // when we are handling methods. This is the name of the class
+ // as run through goCPointerType.
+ String *class_receiver;
+ // A hash table of method names that we have seen when processing a
+ // class. This lets us detect base class methods that we don't want
+ // to use.
+ Hash *class_methods;
+ // True when we are generating the wrapper functions for a variable.
+ bool making_variable_wrappers;
+ // True when working with a static member function.
+ bool is_static_member_function;
+ // A hash table of enum types that we have seen but which may not have
+ // been defined. The index is a SwigType.
+ Hash *undefined_enum_types;
+ // A hash table of types that we have seen but which may not have
+ // been defined. The index is a SwigType.
+ Hash *undefined_types;
+ // A hash table of classes which were defined. The index is a Go
+ // type name.
+ Hash *defined_types;
+ // A hash table of all the go_imports already imported. The index is a full
+ // import name e.g. '"runtime"' or '_ "runtime/cgo"' or 'sc "syscall"'.
+ Hash *go_imports;
+ // A unique ID used to make public symbols unique.
+ String *unique_id;
+
+public:
+ GO():package(NULL),
+ module(NULL),
+ gccgo_flag(false),
+ go_prefix(NULL),
+ prefix_option(NULL),
+ pkgpath_option(NULL),
+ import_prefix(NULL),
+ use_shlib(false),
+ soname(NULL),
+ intgo_type_size(0),
+ f_c_begin(NULL),
+ f_go_begin(NULL),
+ f_c_runtime(NULL),
+ f_c_header(NULL),
+ f_c_wrappers(NULL),
+ f_c_init(NULL),
+ f_c_directors(NULL),
+ f_c_directors_h(NULL),
+ f_go_imports(NULL),
+ f_go_runtime(NULL),
+ f_go_header(NULL),
+ f_go_wrappers(NULL),
+ f_go_directors(NULL),
+ f_cgo_comment(NULL),
+ f_cgo_comment_typedefs(NULL),
+ saw_import(false),
+ imported_package(NULL),
+ interfaces(NULL),
+ class_node(NULL),
+ class_name(NULL),
+ class_receiver(NULL),
+ class_methods(NULL),
+ making_variable_wrappers(false),
+ is_static_member_function(false),
+ undefined_enum_types(NULL),
+ undefined_types(NULL),
+ defined_types(NULL),
+ go_imports(NULL),
+ unique_id(NULL) {
+ director_multiple_inheritance = 1;
+ directorLanguage();
+ director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");");
+ }
+
+private:
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("go");
+ bool saw_nocgo_flag = false;
+
+ // Process command line options.
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-cgo") == 0) {
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-no-cgo") == 0) {
+ Swig_mark_arg(i);
+ saw_nocgo_flag = true;
+ } else if (strcmp(argv[i], "-gccgo") == 0) {
+ Swig_mark_arg(i);
+ gccgo_flag = true;
+ } else if (strcmp(argv[i], "-go-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix_option = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-go-pkgpath") == 0) {
+ if (argv[i + 1]) {
+ pkgpath_option = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-import-prefix") == 0) {
+ if (argv[i + 1]) {
+ import_prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-use-shlib") == 0) {
+ Swig_mark_arg(i);
+ use_shlib = true;
+ } else if (strcmp(argv[i], "-soname") == 0) {
+ if (argv[i + 1]) {
+ soname = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-longsize") == 0) {
+ // Ignore for backward compatibility.
+ if (argv[i + 1]) {
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ ++i;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-intgosize") == 0) {
+ if (argv[i + 1]) {
+ intgo_type_size = atoi(argv[i + 1]);
+ if (intgo_type_size != 32 && intgo_type_size != 64) {
+ Printf(stderr, "-intgosize not 32 or 64\n");
+ Swig_arg_error();
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ ++i;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ if (saw_nocgo_flag) {
+ Printf(stderr, "SWIG -go: -no-cgo option is no longer supported\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ if (gccgo_flag && !pkgpath_option && !prefix_option) {
+ prefix_option = NewString("go");
+ }
+
+ // Add preprocessor symbol to parser.
+ Preprocessor_define("SWIGGO 1", 0);
+
+ if (gccgo_flag) {
+ Preprocessor_define("SWIGGO_GCCGO 1", 0);
+ }
+
+ if (intgo_type_size == 32) {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 32", 0);
+ } else if (intgo_type_size == 64) {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 64", 0);
+ } else {
+ Preprocessor_define("SWIGGO_INTGO_SIZE 0", 0);
+ }
+
+ SWIG_config_file("go.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ *
+ * For gc, we are going to create the following files:
+ *
+ * 1) A .c or .cxx file compiled with gcc. This file will contain
+ * function wrappers. Each wrapper will take a pointer to a
+ * struct holding the arguments, unpack them, and call the real
+ * function.
+ *
+ * 2) A .go file which defines the Go form of all types, and which
+ * defines Go function wrappers. Each wrapper will call the C
+ * function wrapper in the second file.
+ *
+ * 3) A .c file compiled with 6c/8c. This file will define
+ * Go-callable C function wrappers. Each wrapper will use
+ * cgocall to call the function wrappers in the first file.
+ *
+ * When generating code for gccgo, we don't need the third file, and
+ * the function wrappers in the first file have a different form.
+ *
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+ if (optionsnode) {
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ module = Getattr(n, "name");
+ if (!package) {
+ package = Copy(module);
+ }
+ if (!soname && use_shlib) {
+ soname = Copy(package);
+ Append(soname, ".so");
+ }
+
+ if (gccgo_flag) {
+ String *pref;
+ if (pkgpath_option) {
+ pref = pkgpath_option;
+ } else {
+ pref = prefix_option;
+ }
+ go_prefix = NewString("");
+ for (char *p = Char(pref); *p != '\0'; p++) {
+ if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '.' || *p == '$') {
+ Putc(*p, go_prefix);
+ } else {
+ Putc('_', go_prefix);
+ }
+ }
+ if (!pkgpath_option) {
+ Append(go_prefix, ".");
+ Append(go_prefix, getModuleName(package));
+ }
+ }
+
+ // Get filenames.
+
+ String *swig_filename = Getattr(n, "infile");
+ String *c_filename = Getattr(n, "outfile");
+ String *c_filename_h = Getattr(n, "outfile_h");
+
+ String *go_filename = NewString("");
+ Printf(go_filename, "%s%s.go", SWIG_output_directory(), module);
+
+ // Generate a unique ID based on a hash of the SWIG input.
+ swig_uint64 hash = {0, 0};
+ FILE *swig_input = Swig_open(swig_filename);
+ if (swig_input == NULL) {
+ FileErrorDisplay(swig_filename);
+ Exit(EXIT_FAILURE);
+ }
+ String *swig_input_content = Swig_read_file(swig_input);
+ siphash(&hash, Char(swig_input_content), Len(swig_input_content));
+ Delete(swig_input_content);
+ fclose(swig_input);
+ unique_id = NewString("");
+ Printf(unique_id, "_%s_%08x%08x", getModuleName(package), hash.hi, hash.lo);
+
+ // Open files.
+
+ f_c_begin = NewFile(c_filename, "w", SWIG_output_files());
+ if (!f_c_begin) {
+ FileErrorDisplay(c_filename);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (Swig_directors_enabled()) {
+ if (!c_filename_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ Exit(EXIT_FAILURE);
+ }
+ f_c_directors_h = NewFile(c_filename_h, "w", SWIG_output_files());
+ if (!f_c_directors_h) {
+ FileErrorDisplay(c_filename_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ f_go_begin = NewFile(go_filename, "w", SWIG_output_files());
+ if (!f_go_begin) {
+ FileErrorDisplay(go_filename);
+ Exit(EXIT_FAILURE);
+ }
+
+ f_c_runtime = NewString("");
+ f_c_header = NewString("");
+ f_c_wrappers = NewString("");
+ f_c_init = NewString("");
+ f_c_directors = NewString("");
+ f_go_imports = NewString("");
+ f_go_runtime = NewString("");
+ f_go_header = NewString("");
+ f_go_wrappers = NewString("");
+ f_go_directors = NewString("");
+ f_cgo_comment = NewString("");
+ f_cgo_comment_typedefs = NewString("");
+
+ Swig_register_filebyname("begin", f_c_begin);
+ Swig_register_filebyname("runtime", f_c_runtime);
+ Swig_register_filebyname("header", f_c_header);
+ Swig_register_filebyname("wrapper", f_c_wrappers);
+ Swig_register_filebyname("init", f_c_init);
+ Swig_register_filebyname("director", f_c_directors);
+ Swig_register_filebyname("director_h", f_c_directors_h);
+ Swig_register_filebyname("go_begin", f_go_begin);
+ Swig_register_filebyname("go_imports", f_go_imports);
+ Swig_register_filebyname("go_runtime", f_go_runtime);
+ Swig_register_filebyname("go_header", f_go_header);
+ Swig_register_filebyname("go_wrapper", f_go_wrappers);
+ Swig_register_filebyname("go_director", f_go_directors);
+ Swig_register_filebyname("cgo_comment", f_cgo_comment);
+ Swig_register_filebyname("cgo_comment_typedefs", f_cgo_comment_typedefs);
+
+ Swig_banner(f_c_begin);
+
+ Swig_obligatory_macros(f_c_runtime, "GO");
+
+ if (CPlusPlus) {
+ Printf(f_c_begin, "\n// source: %s\n\n", swig_filename);
+ } else {
+ Printf(f_c_begin, "\n/* source: %s */\n\n", swig_filename);
+ }
+
+ Printf(f_c_runtime, "#define SWIGMODULE %s\n", module);
+
+ if (gccgo_flag) {
+ Printf(f_c_runtime, "#define SWIGGO_PREFIX %s\n", go_prefix);
+ }
+
+ if (Swig_directors_enabled()) {
+ Printf(f_c_runtime, "#define SWIG_DIRECTORS\n");
+
+ Swig_banner(f_c_directors_h);
+ Printf(f_c_directors_h, "\n// source: %s\n\n", swig_filename);
+
+ Printf(f_c_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module);
+ Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module);
+ Printf(f_c_directors_h, "class Swig_memory;\n\n");
+
+ Printf(f_c_directors, "\n// C++ director class methods.\n");
+ String *filename = Swig_file_filename(c_filename_h);
+ Printf(f_c_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ Swig_banner(f_go_begin);
+ Printf(f_go_begin, "\n// source: %s\n", swig_filename);
+
+ Printv(f_cgo_comment_typedefs, "/*\n", NULL);
+
+ // The cgo program defines the intgo type after our function
+ // definitions, but we want those definitions to be able to use
+ // intgo also.
+ Printv(f_cgo_comment_typedefs, "#define intgo swig_intgo\n", NULL);
+ Printv(f_cgo_comment_typedefs, "typedef void *swig_voidp;\n", NULL);
+
+ // Output module initialization code.
+
+ Printf(f_go_begin, "\npackage %s\n\n", getModuleName(package));
+
+ // All the C++ wrappers should be extern "C".
+
+ Printv(f_c_wrappers, "#ifdef __cplusplus\n", "extern \"C\" {\n", "#endif\n\n", NULL);
+
+ // Set up the hash table for types not defined by SWIG.
+
+ undefined_enum_types = NewHash();
+ undefined_types = NewHash();
+ defined_types = NewHash();
+ go_imports = NewHash();
+
+ // Emit code.
+
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_c_runtime);
+ Swig_insert_file("director.swg", f_c_runtime);
+ }
+
+ Delete(go_imports);
+
+ // Write out definitions for the types not defined by SWIG.
+
+ if (Len(undefined_enum_types) > 0)
+ Printv(f_go_wrappers, "\n", NULL);
+ for (Iterator p = First(undefined_enum_types); p.key; p = Next(p)) {
+ String *name = p.item;
+ Printv(f_go_wrappers, "type ", name, " int\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+ for (Iterator p = First(undefined_types); p.key; p = Next(p)) {
+ String *ty = goType(NULL, p.key);
+ if (!Getattr(defined_types, ty)) {
+ String *cp = goCPointerType(p.key, false);
+ if (!Getattr(defined_types, cp)) {
+ Printv(f_go_wrappers, "type ", cp, " uintptr\n", NULL);
+ Printv(f_go_wrappers, "type ", ty, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\tSwigcptr() uintptr;\n", NULL);
+ Printv(f_go_wrappers, "}\n", NULL);
+ Printv(f_go_wrappers, "func (p ", cp, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn uintptr(p)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+ Delete(cp);
+ }
+ Delete(ty);
+ }
+ Delete(undefined_enum_types);
+ Delete(undefined_types);
+ Delete(defined_types);
+
+ /* Write and cleanup */
+
+ Dump(f_c_header, f_c_runtime);
+
+ if (Swig_directors_enabled()) {
+ Printf(f_c_directors_h, "#endif\n");
+ Delete(f_c_directors_h);
+ f_c_directors_h = NULL;
+
+ Dump(f_c_directors, f_c_runtime);
+ Delete(f_c_directors);
+ f_c_directors = NULL;
+ }
+
+ // End the extern "C".
+ Printv(f_c_wrappers, "#ifdef __cplusplus\n", "}\n", "#endif\n\n", NULL);
+
+ // End the cgo comment.
+ Printv(f_cgo_comment, "#undef intgo\n", NULL);
+ Printv(f_cgo_comment, "*/\n", NULL);
+ Printv(f_cgo_comment, "import \"C\"\n", NULL);
+ Printv(f_cgo_comment, "\n", NULL);
+
+ bool need_panic = false;
+ if (Strstr(f_c_runtime, "SWIG_contract_assert(") != 0 || Strstr(f_c_wrappers, "SWIG_contract_assert(") != 0) {
+ Printv(f_c_begin, "\n#define SWIG_contract_assert(expr, msg) if (!(expr)) { _swig_gopanic(msg); } else\n\n", NULL);
+ need_panic = true;
+ }
+
+ if (!gccgo_flag && (need_panic || Strstr(f_c_runtime, "_swig_gopanic") != 0 || Strstr(f_c_wrappers, "_swig_gopanic") != 0)) {
+ Printv(f_go_header, "//export cgo_panic_", unique_id, "\n", NULL);
+ Printv(f_go_header, "func cgo_panic_", unique_id, "(p *byte) {\n", NULL);
+ Printv(f_go_header, "\ts := (*[1024]byte)(unsafe.Pointer(p))[:]\n", NULL);
+ Printv(f_go_header, "\tfor i, b := range s {\n", NULL);
+ Printv(f_go_header, "\t\tif b == 0 {\n", NULL);
+ Printv(f_go_header, "\t\t\tpanic(string(s[:i]))\n", NULL);
+ Printv(f_go_header, "\t\t}\n", NULL);
+ Printv(f_go_header, "\t}\n", NULL);
+ Printv(f_go_header, "\tpanic(string(s))\n", NULL);
+ Printv(f_go_header, "}\n\n", NULL);
+
+ Printv(f_c_begin, "\nextern\n", NULL);
+ Printv(f_c_begin, "#ifdef __cplusplus\n", NULL);
+ Printv(f_c_begin, " \"C\"\n", NULL);
+ Printv(f_c_begin, "#endif\n", NULL);
+ Printv(f_c_begin, " void cgo_panic_", unique_id, "(const char*);\n", NULL);
+ Printv(f_c_begin, "static void _swig_gopanic(const char *p) {\n", NULL);
+ Printv(f_c_begin, " cgo_panic_", unique_id, "(p);\n", NULL);
+ Printv(f_c_begin, "}\n\n", NULL);
+ }
+
+ Dump(f_c_runtime, f_c_begin);
+ Dump(f_c_wrappers, f_c_begin);
+ Dump(f_c_init, f_c_begin);
+ Dump(f_cgo_comment_typedefs, f_go_begin);
+ Dump(f_cgo_comment, f_go_begin);
+ Dump(f_go_imports, f_go_begin);
+ Dump(f_go_header, f_go_begin);
+ Dump(f_go_runtime, f_go_begin);
+ Dump(f_go_wrappers, f_go_begin);
+ if (Swig_directors_enabled()) {
+ Dump(f_go_directors, f_go_begin);
+ }
+ Delete(f_c_runtime);
+ Delete(f_c_header);
+ Delete(f_c_wrappers);
+ Delete(f_c_init);
+ Delete(f_go_imports);
+ Delete(f_go_runtime);
+ Delete(f_go_header);
+ Delete(f_go_wrappers);
+ Delete(f_go_directors);
+ Delete(f_cgo_comment);
+ Delete(f_cgo_comment_typedefs);
+ Delete(f_c_begin);
+ Delete(f_go_begin);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ *
+ * Handle a SWIG import statement by generating a Go import
+ * statement.
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ String *hold_import = imported_package;
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ if (!Getattr(go_imports, modname)) {
+ Setattr(go_imports, modname, modname);
+ Printv(f_go_imports, "import \"", NULL);
+ if (import_prefix) {
+ Printv(f_go_imports, import_prefix, "/", NULL);
+ }
+ Printv(f_go_imports, modname, "\"\n", NULL);
+ }
+ imported_package = modname;
+ saw_import = true;
+ }
+ int r = Language::importDirective(n);
+ imported_package = hold_import;
+ return r;
+ }
+
+ /* ----------------------------------------------------------------------
+ * Language::insertDirective()
+ *
+ * If the section is go_imports, store them for later.
+ * ---------------------------------------------------------------------- */
+ virtual int insertDirective(Node *n) {
+ char *section = Char(Getattr(n, "section"));
+ if ((ImportMode && !Getattr(n, "generated")) ||
+ !section || (strcmp(section, "go_imports") != 0)) {
+ return Language::insertDirective(n);
+ }
+
+ char *code = Char(Getattr(n, "code"));
+ char *pch = strtok(code, ",");
+ while (pch != NULL) {
+ // Do not import same thing more than once.
+ if (!Getattr(go_imports, pch)) {
+ Setattr(go_imports, pch, pch);
+ Printv(f_go_imports, "import ", pch, "\n", NULL);
+ }
+ pch = strtok(NULL, ",");
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Implement a function.
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ if (GetFlag(n, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ // We don't need explicit calls.
+ if (GetFlag(n, "explicitcall")) {
+ return SWIG_OK;
+ }
+
+ String *name = Getattr(n, "sym:name");
+ String *nodetype = Getattr(n, "nodeType");
+ bool is_static = is_static_member_function || isStatic(n);
+ bool is_friend = isFriend(n);
+ bool is_ctor_dtor = false;
+
+ SwigType *result = Getattr(n, "type");
+
+ // For some reason SWIG changs the "type" value during the call to
+ // functionWrapper. We need to remember the type for possible
+ // overload processing.
+ Setattr(n, "go:type", Copy(result));
+
+ String *go_name;
+
+ String *r1 = NULL;
+ if (making_variable_wrappers) {
+ // Change the name of the variable setter and getter functions
+ // to be more Go like.
+
+ bool is_set = Strcmp(Char(name) + Len(name) - 4, "_set") == 0;
+ assert(is_set || Strcmp(Char(name) + Len(name) - 4, "_get") == 0);
+
+ // Start with Set or Get.
+ go_name = NewString(is_set ? "Set" : "Get");
+
+ // If this is a static variable, put in the class name,
+ // capitalized.
+ if (is_static && class_name) {
+ String *ccn = exportedName(class_name);
+ Append(go_name, ccn);
+ Delete(ccn);
+ }
+
+ // Add the rest of the name, capitalized, dropping the _set or
+ // _get.
+ String *c1 = removeClassname(name);
+ String *c2 = exportedName(c1);
+ char *p = Char(c2);
+ int len = Len(p);
+ for (int i = 0; i < len - 4; ++i) {
+ Putc(p[i], go_name);
+ }
+ Delete(c2);
+ Delete(c1);
+
+ if (!checkIgnoredParameters(n, go_name)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+ } else if (Cmp(nodetype, "constructor") == 0) {
+ is_ctor_dtor = true;
+
+ // Change the name of a constructor to be more Go like. Change
+ // new_ to New, and capitalize the class name.
+ assert(Strncmp(name, "new_", 4) == 0);
+ String *c1 = NewString(Char(name) + 4);
+ String *c2 = exportedName(c1);
+ go_name = NewString("New");
+ Append(go_name, c2);
+ Delete(c2);
+ Delete(c1);
+
+ if (Swig_methodclass(n) && Swig_directorclass(n)) {
+ // The core SWIG code skips the first parameter when
+ // generating the $nondirector_new string. Recreate the
+ // action in this case. But don't it if we are using the
+ // special code for an abstract class.
+ String *call = Swig_cppconstructor_call(getClassType(),
+ Getattr(n, "parms"));
+ SwigType *type = Copy(getClassType());
+ SwigType_add_pointer(type);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ if (!Equal(Getattr(n, "wrap:action"), director_prot_ctor_code)) {
+ Setattr(n, "wrap:action", cres);
+ }
+ }
+ } else if (Cmp(nodetype, "destructor") == 0) {
+ // No need to emit protected destructors.
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+
+ is_ctor_dtor = true;
+
+ // Change the name of a destructor to be more Go like. Change
+ // delete_ to Delete and capitalize the class name.
+ assert(Strncmp(name, "delete_", 7) == 0);
+ String *c1 = NewString(Char(name) + 7);
+ String *c2 = exportedName(c1);
+ go_name = NewString("Delete");
+ Append(go_name, c2);
+ Delete(c2);
+ Delete(c1);
+
+ result = NewString("void");
+ r1 = result;
+ } else {
+ if (!checkFunctionVisibility(n, NULL)) {
+ return SWIG_OK;
+ }
+
+ go_name = buildGoName(name, is_static, is_friend);
+
+ if (!checkIgnoredParameters(n, go_name)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ String *scope;
+ if (!class_name || is_static || is_ctor_dtor) {
+ scope = NULL;
+ } else {
+ scope = NewString("swiggoscope.");
+ Append(scope, class_name);
+ }
+ if (!checkNameConflict(go_name, n, scope)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *wname = Swig_name_wrapper(name);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ int r = makeWrappers(n, go_name, overname, wname, NULL, parms, result, is_static);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) {
+ String *scope ;
+ if (!class_name || is_static || is_ctor_dtor) {
+ scope = NULL;
+ } else {
+ scope = NewString("swiggoscope.");
+ Append(scope, class_name);
+ }
+ if (!checkNameConflict(go_name, n, scope)) {
+ Delete(go_name);
+ return SWIG_NOWRAP;
+ }
+
+ String *receiver = class_receiver;
+ if (is_static || is_ctor_dtor) {
+ receiver = NULL;
+ }
+ r = makeDispatchFunction(n, go_name, receiver, is_static, NULL, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(wname);
+ Delete(go_name);
+ Delete(r1);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * For some reason the language code removes the "storage" attribute
+ * for a static function before calling functionWrapper, which means
+ * that we have no way of knowing whether a function is static or
+ * not. That makes no sense in the Go context. Here we note that a
+ * function is static.
+ * ---------------------------------------------------------------------- */
+
+ int staticmemberfunctionHandler(Node *n) {
+ assert(!is_static_member_function);
+ is_static_member_function = true;
+ int r = Language::staticmemberfunctionHandler(n);
+ is_static_member_function = false;
+ return r;
+ }
+
+ /* ----------------------------------------------------------------------
+ * makeWrappers()
+ *
+ * Write out the various function wrappers.
+ * n: The function we are emitting.
+ * go_name: The name of the function in Go.
+ * overname: The overload string for overloaded function.
+ * wname: The SWIG wrapped name--the name of the C function.
+ * base: A list of the names of base classes, in the case where this
+ * is a virtual method not defined in the current class.
+ * parms: The parameters.
+ * result: The result type.
+ * is_static: Whether this is a static method or member.
+ * ---------------------------------------------------------------------- */
+
+ int makeWrappers(Node *n, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+
+ assert(result);
+
+ int ret = SWIG_OK;
+
+ int r = makeCgoWrappers(n, go_name, overname, wname, base, parms, result, is_static);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ if (class_methods) {
+ Setattr(class_methods, Getattr(n, "name"), NewString(""));
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * struct cgoWrapperInfo
+ *
+ * Information needed by the CGO wrapper functions.
+ * ---------------------------------------------------------------------- */
+
+ struct cgoWrapperInfo {
+ // The function we are generating code for.
+ Node *n;
+ // The name of the Go function.
+ String *go_name;
+ // The overload string for an overloaded function.
+ String *overname;
+ // The name of the C wrapper function.
+ String *wname;
+ // The base classes.
+ List *base;
+ // The parameters.
+ ParmList *parms;
+ // The result type.
+ SwigType *result;
+ // Whether this is a static function, not a class method.
+ bool is_static;
+ // The Go receiver type.
+ String *receiver;
+ // Whether this is a class constructor.
+ bool is_constructor;
+ // Whether this is a class destructor.
+ bool is_destructor;
+ };
+
+ /* ----------------------------------------------------------------------
+ * makeCgoWrappers()
+ *
+ * Write out the wrappers for a function when producing cgo input
+ * files.
+ * ---------------------------------------------------------------------- */
+
+ int makeCgoWrappers(Node *n, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
+ Swig_save("makeCgoWrappers", n, "emit:cgotype", "emit:cgotypestruct", NULL);
+
+ cgoWrapperInfo info;
+
+ info.n = n;
+ info.go_name = go_name;
+ info.overname = overname;
+ info.wname = wname;
+ info.base = base;
+ info.parms = parms;
+ info.result = result;
+ info.is_static = is_static;
+
+ info.receiver = class_receiver;
+ if (is_static) {
+ info.receiver = NULL;
+ }
+
+ String *nodetype = Getattr(n, "nodeType");
+ info.is_constructor = Cmp(nodetype, "constructor") == 0;
+ info.is_destructor = Cmp(nodetype, "destructor") == 0;
+ if (info.is_constructor || info.is_destructor) {
+ assert(class_receiver);
+ assert(!base);
+ info.receiver = NULL;
+ }
+
+ int ret = SWIG_OK;
+
+ int r = cgoGoWrapper(&info);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ r = cgoCommentWrapper(&info);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ r = cgoGccWrapper(&info);
+ if (r != SWIG_OK) {
+ ret = r;
+ }
+
+ Swig_restore(n);
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoGoWrapper()
+ *
+ * Write out Go code to call a cgo function. This code will go into
+ * the generated Go output file.
+ * ---------------------------------------------------------------------- */
+ int cgoGoWrapper(const cgoWrapperInfo *info) {
+
+ Wrapper *dummy = initGoTypemaps(info->parms);
+
+ bool add_to_interface = interfaces && !info->is_constructor && !info->is_destructor && !info->is_static && !info->overname && checkFunctionVisibility(info->n, NULL);
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ Parm *p = info->parms;
+ int pi = 0;
+
+ // Add the receiver first if this is a method.
+ if (info->receiver) {
+ Printv(f_go_wrappers, "(", NULL);
+ if (info->base && info->receiver) {
+ Printv(f_go_wrappers, "_swig_base", NULL);
+ } else {
+ Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ ++pi;
+ }
+ Printv(f_go_wrappers, " ", info->receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, info->go_name, NULL);
+ if (info->overname) {
+ Printv(f_go_wrappers, info->overname, NULL);
+ }
+ Printv(f_go_wrappers, "(", NULL);
+
+ // If we are doing methods, add this method to the interface.
+ if (add_to_interface) {
+ Printv(interfaces, "\t", info->go_name, "(", NULL);
+ }
+
+ // Write out the parameters to both the function definition and
+ // the interface.
+
+ String *parm_print = NewString("");
+
+ int parm_count = emit_num_arguments(info->parms);
+ int required_count = emit_num_required(info->parms);
+ int args = 0;
+
+ for (; pi < parm_count; ++pi) {
+ p = getParm(p);
+ if (pi == 0 && info->is_destructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
+ Delete(cl);
+ ++args;
+ } else {
+ if (args > 0) {
+ Printv(parm_print, ", ", NULL);
+ }
+ ++args;
+ if (pi >= required_count) {
+ Printv(parm_print, "_swig_args ...interface{}", NULL);
+ break;
+ }
+ Printv(parm_print, Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(parm_print, tm, NULL);
+ Delete(tm);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(parm_print, ")", NULL);
+
+ // Write out the result type.
+ if (info->is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(parm_print, " (_swig_ret ", cl, ")", NULL);
+ Delete(cl);
+ } else {
+ if (SwigType_type(info->result) != T_VOID) {
+ String *tm = goType(info->n, info->result);
+ Printv(parm_print, " (_swig_ret ", tm, ")", NULL);
+ Delete(tm);
+ }
+ }
+
+ Printv(f_go_wrappers, parm_print, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, parm_print, "\n", NULL);
+ }
+
+ // Write out the function body.
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ if (parm_count > required_count) {
+ Parm *p = info->parms;
+ int i;
+ for (i = 0; i < required_count; ++i) {
+ p = getParm(p);
+ p = nextParm(p);
+ }
+ for (; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL);
+ Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count);
+ Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+ }
+
+ String *call = NewString("\t");
+
+ String *ret_type = NULL;
+ bool memcpy_ret = false;
+ String *wt = NULL;
+ if (SwigType_type(info->result) != T_VOID) {
+ if (info->is_constructor) {
+ ret_type = exportedName(class_name);
+ } else {
+ ret_type = goImType(info->n, info->result);
+ }
+ Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(info->n, info->result, &c_struct_type));
+ if (c_struct_type) {
+ memcpy_ret = true;
+ }
+
+ if (memcpy_ret) {
+ Printv(call, "swig_r_p := ", NULL);
+ } else {
+ Printv(call, "swig_r = (", ret_type, ")(", NULL);
+ }
+
+ if (info->is_constructor || goTypeIsInterface(info->n, info->result)) {
+ if (info->is_constructor) {
+ wt = Copy(class_receiver);
+ } else {
+ wt = goWrapperType(info->n, info->result, true);
+ }
+ Printv(call, wt, "(", NULL);
+ }
+ }
+
+ Printv(call, "C.", info->wname, "(", NULL);
+
+ args = 0;
+
+ if (parm_count > required_count) {
+ Printv(call, "C.swig_intgo(len(_swig_args))", NULL);
+ ++args;
+ }
+
+ if (info->base && info->receiver) {
+ if (args > 0) {
+ Printv(call, ", ", NULL);
+ }
+ ++args;
+ Printv(call, "C.uintptr_t(_swig_base)", NULL);
+ }
+
+ p = info->parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (args > 0) {
+ Printv(call, ", ", NULL);
+ }
+ ++args;
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
+ if ((i == 0 && info->is_destructor) || ((i > 0 || !info->receiver || info->base || info->is_constructor) && goTypeIsInterface(p, pt))) {
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ Setattr(p, "emit:goinput", ivar);
+ }
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+ Delete(ct);
+
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, call, ")", NULL);
+ Delete(call);
+
+ if (wt) {
+ // Close the type conversion to the wrapper type.
+ Printv(f_go_wrappers, ")", NULL);
+ }
+ if (SwigType_type(info->result) != T_VOID && !memcpy_ret) {
+ // Close the type conversion of the return value.
+ Printv(f_go_wrappers, ")", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+
+ if (memcpy_ret) {
+ Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+ }
+ if (ret_type) {
+ Delete(ret_type);
+ }
+
+ goargout(info->parms);
+
+ if (SwigType_type(info->result) != T_VOID) {
+
+ Swig_save("cgoGoWrapper", info->n, "type", "tmap:goout", NULL);
+ Setattr(info->n, "type", info->result);
+
+ String *goout = goTypemapLookup("goout", info->n, "swig_r");
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(info->n, info->result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ goout = Copy(goout);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+
+ Swig_restore(info->n);
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ DelWrapper(dummy);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoCommentWrapper()
+ *
+ * Write out a cgo function to call a C/C++ function. This code
+ * will go into the cgo comment in the generated Go output file.
+ * ---------------------------------------------------------------------- */
+ int cgoCommentWrapper(const cgoWrapperInfo *info) {
+ String *ret_type;
+ if (SwigType_type(info->result) == T_VOID) {
+ ret_type = NewString("void");
+ } else {
+ bool c_struct_type;
+ ret_type = cgoTypeForGoValue(info->n, info->result, &c_struct_type);
+ }
+
+ Printv(f_cgo_comment, "extern ", ret_type, " ", info->wname, "(", NULL);
+
+ Delete(ret_type);
+
+ int parm_count = emit_num_arguments(info->parms);
+ int required_count = emit_num_required(info->parms);
+ int args = 0;
+
+ if (parm_count > required_count) {
+ Printv(f_cgo_comment, "intgo _swig_args", NULL);
+ ++args;
+ }
+
+ if (info->base && info->receiver) {
+ if (args > 0) {
+ Printv(f_cgo_comment, ", ", NULL);
+ }
+ ++args;
+ Printv(f_cgo_comment, "uintptr_t _swig_base", NULL);
+ }
+
+ Parm *p = info->parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (args > 0) {
+ Printv(f_cgo_comment, ", ", NULL);
+ }
+ ++args;
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ Printv(f_cgo_comment, ct, " ", ln, NULL);
+ Delete(ct);
+
+ p = nextParm(p);
+ }
+
+ if (args == 0) {
+ Printv(f_cgo_comment, "void", NULL);
+ }
+
+ Printv(f_cgo_comment, ");\n", NULL);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoGccWrapper()
+ *
+ * Write out code to the C/C++ wrapper file. This code will be
+ * called by the code generated by cgoCommentWrapper.
+ * ---------------------------------------------------------------------- */
+ int cgoGccWrapper(const cgoWrapperInfo *info) {
+ Wrapper *f = NewWrapper();
+
+ Swig_save("cgoGccWrapper", info->n, "parms", NULL);
+
+ ParmList *parms = info->parms;
+
+ Parm *base_parm = NULL;
+ if (info->base && !isStatic(info->n)) {
+ SwigType *base_type = Copy(getClassType());
+ SwigType_add_pointer(base_type);
+ base_parm = NewParm(base_type, NewString("arg1"), info->n);
+ set_nextSibling(base_parm, parms);
+ parms = base_parm;
+ }
+
+ emit_parameter_variables(parms, f);
+ emit_attach_parmmaps(parms, f);
+ int parm_count = emit_num_arguments(parms);
+ int required_count = emit_num_required(parms);
+
+ emit_return_variable(info->n, info->result, f);
+
+ // Start the function definition.
+
+ String *fnname = NewString("");
+ Printv(fnname, info->wname, "(", NULL);
+
+ int args = 0;
+
+ if (parm_count > required_count) {
+ Printv(fnname, "intgo _swig_optargc", NULL);
+ ++args;
+ }
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ if (args > 0) {
+ Printv(fnname, ", ", NULL);
+ }
+ ++args;
+
+ p = getParm(p);
+
+ SwigType *pt = Copy(Getattr(p, "type"));
+ if (SwigType_isarray(pt) && Getattr(p, "tmap:gotype") == NULL) {
+ SwigType_del_array(pt);
+ SwigType_add_pointer(pt);
+ }
+ String *pn = NewStringf("_swig_go_%d", i);
+ String *ct = gcCTypeForGoValue(p, pt, pn);
+ Printv(fnname, ct, NULL);
+ Delete(ct);
+ Delete(pn);
+ Delete(pt);
+
+ p = nextParm(p);
+ }
+
+ Printv(fnname, ")", NULL);
+
+ if (SwigType_type(info->result) == T_VOID) {
+ Printv(f->def, "void ", fnname, NULL);
+ } else {
+ String *ct = gcCTypeForGoValue(info->n, info->result, fnname);
+ Printv(f->def, ct, NULL);
+ Delete(ct);
+
+ String *ln = NewString("_swig_go_result");
+ ct = gcCTypeForGoValue(info->n, info->result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
+ }
+
+ Delete(fnname);
+
+ Printv(f->def, " {\n", NULL);
+
+ // Apply the in typemaps.
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = Getattr(p, "tmap:in");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ String *pn = NewStringf("_swig_go_%d", i);
+ Replaceall(tm, "$input", pn);
+ if (i < required_count) {
+ Printv(f->code, "\t", tm, "\n", NULL);
+ } else {
+ Printf(f->code, "\tif (_swig_optargc > %d) {\n", i - required_count);
+ Printv(f->code, "\t\t", tm, "\n", NULL);
+ Printv(f->code, "\t}\n", NULL);
+ }
+ Delete(tm);
+ Setattr(p, "emit:input", pn);
+ }
+ p = nextParm(p);
+ }
+
+ Printv(f->code, "\n", NULL);
+
+ // Do the real work of the function.
+
+ checkConstraints(parms, f);
+
+ emitGoAction(info->n, info->base, parms, info->result, f);
+
+ argout(parms, f);
+
+ cleanupFunction(info->n, f, parms);
+
+ if (SwigType_type(info->result) != T_VOID) {
+ Printv(f->code, "\treturn _swig_go_result;\n", NULL);
+ }
+
+ Printv(f->code, "}\n", NULL);
+
+ Wrapper_print(f, f_c_wrappers);
+
+ Swig_restore(info->n);
+
+ DelWrapper(f);
+ if (base_parm) {
+ Delete(base_parm);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * initGoTypemaps()
+ *
+ * Initialize the typenames for a Go wrapper, returning a dummy
+ * Wrapper*. Also set consistent names for the parameters.
+ * ---------------------------------------------------------------------- */
+
+ Wrapper* initGoTypemaps(ParmList *parms) {
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+
+ Parm *p = parms;
+ int parm_count = emit_num_arguments(parms);
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
+ Swig_typemap_attach_parms("default", parms, dummy);
+ Swig_typemap_attach_parms("gotype", parms, dummy);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+ Swig_typemap_attach_parms("imtype", parms, dummy);
+
+ return dummy;
+ }
+
+ /* -----------------------------------------------------------------------
+ * checkConstraints()
+ *
+ * Check parameter constraints if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void checkConstraints(ParmList *parms, Wrapper *f) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:check");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:check:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * emitGoAction()
+ *
+ * Emit the action of the function. This is used for the C/C++ function.
+ * ----------------------------------------------------------------------- */
+
+ void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
+ String *actioncode;
+ if (!base || isStatic(n)) {
+ Swig_director_emit_dynamic_cast(n, f);
+ actioncode = emit_action(n);
+ } else {
+ // Call the base class method.
+ actioncode = NewString("");
+
+ String *current = NewString("");
+ Printv(current, Getattr(parms, "lname"), NULL);
+
+ int vc = 0;
+ for (Iterator bi = First(base); bi.item; bi = Next(bi)) {
+ Printf(actioncode, " %s *swig_b%d = (%s *)%s;\n", bi.item, vc, bi.item, current);
+ Delete(current);
+ current = NewString("");
+ Printf(current, "swig_b%d", vc);
+ ++vc;
+ }
+
+ String *code = Copy(Getattr(n, "wrap:action"));
+ Replace(code, Getattr(parms, "lname"), current, DOH_REPLACE_ANY | DOH_REPLACE_ID);
+ Delete(current);
+ Printv(actioncode, code, "\n", NULL);
+ }
+
+ Swig_save("emitGoAction", n, "type", "tmap:out", NULL);
+
+ Setattr(n, "type", result);
+
+ String *tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s\n", SwigType_str(result, 0));
+ } else {
+ Replaceall(tm, "$result", "_swig_go_result");
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ }
+
+ Swig_restore(n);
+ }
+
+ /* -----------------------------------------------------------------------
+ * argout()
+ *
+ * Handle argument output code if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void argout(ParmList *parms, Wrapper *f) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:argout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", Swig_cresult_name());
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:argout:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * goargout()
+ *
+ * Handle Go argument output code if any. This is used for the Go
+ * function. This assumes that each parameter has an "emit:goinput"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void goargout(ParmList *parms) {
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:goargout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "swig_r");
+ Replaceall(tm, "$input", Getattr(p, "emit:goinput"));
+ Printv(f_go_wrappers, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:goargout:next");
+ }
+ }
+
+ // If we need to memcpy a parameter to pass it to the C code, the
+ // compiler may think that the parameter is not live during the
+ // function call. If the garbage collector runs while the C/C++
+ // function is running, the parameter may be freed. Force the
+ // compiler to see the parameter as live across the C/C++ function.
+ int parm_count = emit_num_arguments(parms);
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type));
+ if (c_struct_type) {
+ Printv(f_go_wrappers, "\tif Swig_escape_always_false {\n", NULL);
+ Printv(f_go_wrappers, "\t\tSwig_escape_val = ", Getattr(p, "emit:goinput"), "\n", NULL);
+ Printv(f_go_wrappers, "\t}\n", NULL);
+ }
+ p = nextParm(p);
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ * freearg()
+ *
+ * Handle argument cleanup code if any. This is used for the C/C++
+ * function. This assumes that each parameter has an "emit:input"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ String *freearg(ParmList *parms) {
+ String *ret = NewString("");
+ Parm *p = parms;
+ while (p) {
+ String *tm = Getattr(p, "tmap:freearg");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(ret, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:freearg:next");
+ }
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------
+ * cleanupFunction()
+ *
+ * Final function cleanup code.
+ * ----------------------------------------------------------------------- */
+
+ void cleanupFunction(Node *n, Wrapper *f, ParmList *parms) {
+ SwigType *returntype = Getattr(n, "type");
+ String *cleanup = freearg(parms);
+ Printv(f->code, cleanup, NULL);
+
+ if (GetFlag(n, "feature:new")) {
+ String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
+ }
+ }
+
+ Replaceall(f->code, "$cleanup", cleanup);
+ Delete(cleanup);
+
+ /* See if there is any return cleanup code */
+ String *tm;
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(f->code, "$symname", Getattr(n, "sym:name"));
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableHandler()
+ *
+ * This exists just to set the making_variable_wrappers flag.
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableHandler(Node *n) {
+ assert(!making_variable_wrappers);
+ making_variable_wrappers = true;
+ int r = Language::variableHandler(n);
+ making_variable_wrappers = false;
+ return r;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ *
+ * Product a const declaration.
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ SwigType *type = Getattr(n, "type");
+
+ if (Swig_storage_isstatic(n)) {
+ return goComplexConstant(n, type);
+ }
+
+ String *value = Getattr(n, "value");
+ String *copy = NULL;
+ int typecode = SwigType_type(type);
+ if (typecode == T_STRING) {
+ String *stringval = Getattr(n, "stringval");
+ if (!stringval) {
+ return goComplexConstant(n, type);
+ }
+ // Backslash sequences are somewhat different in Go and C/C++.
+ copy = NewStringf("\"%(goescape)s\"", stringval);
+ value = copy;
+ } else if (typecode == T_CHAR) {
+ String *stringval = Getattr(n, "stringval");
+ if (!stringval || Len(stringval) != 1) {
+ return goComplexConstant(n, type);
+ }
+ // Backslash sequences are somewhat different in Go and C/C++.
+ copy = NewStringf("'%(goescape)s'", stringval);
+ value = copy;
+ } else if (!SwigType_issimple(type)) {
+ return goComplexConstant(n, type);
+ } else if (Swig_storage_isstatic(n)) {
+ return goComplexConstant(n, type);
+ } else if (Getattr(n, "numval")) {
+ value = Getattr(n, "numval");
+ if (typecode == T_BOOL) {
+ copy = NewString(*Char(value) == '0' ? "false" : "true");
+ value = copy;
+ }
+ } else {
+ // Currently numval only gets set for integer and boolean literals, so
+ // check for a floating point literal we can just use in Go here.
+ //
+ // Accept digits, decimal point, and exponentiation. Treat anything else
+ // as too complicated to handle as a Go constant.
+ char *p = Char(value);
+ for (int i = 0; p[i]; ++i) {
+ switch (p[i]) {
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ case '.': case 'e': case 'E': case '+': case '-':
+ break;
+ default:
+ return goComplexConstant(n, type);
+ }
+ }
+ }
+
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+
+ if (!checkNameConflict(go_name, n, NULL)) {
+ Delete(go_name);
+ Delete(copy);
+ return SWIG_NOWRAP;
+ }
+
+ String *tm = goType(n, type);
+
+ Printv(f_go_wrappers, "const ", go_name, " ", tm, " = ", value, "\n", NIL);
+
+ Delete(tm);
+ Delete(go_name);
+ Delete(copy);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumDeclaration()
+ *
+ * A C++ enum type turns into a Named go int type.
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *name = goEnumName(n);
+ if (Strcmp(name, "int") != 0) {
+ if (!ImportMode || !imported_package) {
+ if (!checkNameConflict(name, n, NULL)) {
+ Delete(name);
+ return SWIG_NOWRAP;
+ }
+ Printv(f_go_wrappers, "type ", name, " int\n", NULL);
+ } else {
+ String *nw = NewString("");
+ Printv(nw, getModuleName(imported_package), ".", name, NULL);
+ Setattr(n, "go:enumname", nw);
+ }
+ }
+ Delete(name);
+
+ return Language::enumDeclaration(n);
+ }
+
+ /* -----------------------------------------------------------------------
+ * enumvalueDeclaration()
+ *
+ * Declare a single value of an enum type. We fetch the value by
+ * calling a C/C++ function.
+ * ------------------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+
+ Swig_require("enumvalueDeclaration", n, "*sym:name", NIL);
+ Node *parent = parentNode(n);
+
+ if (Getattr(parent, "unnamed")) {
+ Setattr(n, "type", NewString("int"));
+ } else {
+ Setattr(n, "type", Getattr(parent, "enumtype"));
+ }
+
+ if (GetFlag(parent, "scopedenum")) {
+ String *symname = Getattr(n, "sym:name");
+ symname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ int ret = goComplexConstant(n, Getattr(n, "type"));
+ Swig_restore(n);
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------
+ * goComplexConstant()
+ *
+ * Handle a const declaration for something which is not a Go constant.
+ * ------------------------------------------------------------------------ */
+
+ int goComplexConstant(Node *n, SwigType *type) {
+ String *symname = Getattr(n, "sym:name");
+ if (!symname) {
+ symname = Getattr(n, "name");
+ }
+
+ String *varname = buildGoName(symname, true, false);
+
+ if (!checkNameConflict(varname, n, NULL)) {
+ Delete(varname);
+ return SWIG_NOWRAP;
+ }
+
+ if (!Getattr(n, "stringval") && !Getattr(n, "enumvalueDeclaration:sym:name")) {
+ // Based on Swig_VargetToFunction
+ String *nname = NewStringf("(%s)", Getattr(n, "value"));
+ String *call;
+ if (SwigType_isclass(type)) {
+ call = NewStringf("%s", nname);
+ } else {
+ call = SwigType_lcaststr(type, nname);
+ }
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(nname);
+ Delete(call);
+ Delete(cres);
+ } else {
+ String *get = NewString("");
+ Printv(get, Swig_cresult_name(), " = ", NULL);
+
+ if (SwigType_type(type) == T_STRING) {
+ Printv(get, "(char *)", NULL);
+ }
+
+ Printv(get, Getattr(n, "value"), NULL);
+
+ Printv(get, ";\n", NULL);
+
+ Setattr(n, "wrap:action", get);
+ Delete(get);
+ }
+
+ String *sname = Copy(symname);
+ if (class_name) {
+ Append(sname, "_");
+ Append(sname, class_name);
+ }
+
+ String *go_name = NewString("_swig_get");
+ if (class_name) {
+ Append(go_name, class_name);
+ Append(go_name, "_");
+ }
+ Append(go_name, sname);
+
+ String *wname = Swig_name_wrapper(sname);
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ int r = makeWrappers(n, go_name, NULL, wname, NULL, NULL, type, true);
+
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ String *t = goType(n, type);
+ Printv(f_go_wrappers, "var ", varname, " ", t, " = ", go_name, "()\n", NULL);
+
+ Delete(varname);
+ Delete(t);
+ Delete(go_name);
+ Delete(sname);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ *
+ * For a C++ class, in Go we generate both a struct and an
+ * interface. The interface will declare all the class public
+ * methods. We will define all the methods on the struct, so that
+ * the struct meets the interface. We then expect users of the
+ * class to use the interface.
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ class_node = n;
+
+ List *baselist = Getattr(n, "bases");
+ bool has_base_classes = baselist && Len(baselist) > 0;
+
+ String *name = Getattr(n, "sym:name");
+
+ String *go_name = exportedName(name);
+
+ if (!checkNameConflict(go_name, n, NULL)) {
+ Delete(go_name);
+ SetFlag(n, "go:conflict");
+ return SWIG_NOWRAP;
+ }
+
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ class_name = name;
+ class_receiver = go_type_name;
+ class_methods = NewHash();
+
+ int isdir = GetFlag(n, "feature:director");
+ int isnodir = GetFlag(n, "feature:nodirector");
+ bool is_director = isdir && !isnodir;
+
+ Printv(f_go_wrappers, "type ", go_type_name, " uintptr\n\n", NULL);
+
+ // A method to return the pointer to the C++ class. This is used
+ // by generated code to convert between the interface and the C++
+ // value.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn (uintptr)(p)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // A method used as a marker for the class, to avoid invalid
+ // interface conversions when using multiple inheritance.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (is_director) {
+ // Return the interface passed to the NewDirector function.
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") DirectorInterface() interface{} {\n", NULL);
+ Printv(f_go_wrappers, "\treturn nil\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ }
+
+ // We have seen a definition for this type.
+ Setattr(defined_types, go_name, go_name);
+ Setattr(defined_types, go_type_name, go_type_name);
+
+ interfaces = NewString("");
+
+ int r = Language::classHandler(n);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (has_base_classes) {
+ // For each method defined in a base class but not defined in
+ // this class, we need to define the method in this class. We
+ // can't use anonymous field inheritance because it works
+ // differently in Go and in C++.
+
+ Hash *local = NewHash();
+ for (Node *ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+
+ if (!is_public(ni)) {
+ continue;
+ }
+
+ String *type = Getattr(ni, "nodeType");
+ if (Cmp(type, "constructor") == 0 || Cmp(type, "destructor") == 0) {
+ continue;
+ }
+
+ String *cname = Getattr(ni, "sym:name");
+ if (!cname) {
+ cname = Getattr(ni, "name");
+ }
+ if (cname) {
+ Setattr(local, cname, NewString(""));
+ }
+ }
+
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ List *bases = NewList();
+ Append(bases, Getattr(b.item, "classtype"));
+ int r = addBase(n, b.item, bases, local);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(bases);
+ }
+
+ Delete(local);
+
+ Hash *parents = NewHash();
+ addFirstBaseInterface(n, parents, baselist);
+ int r = addExtraBaseInterfaces(n, parents, baselist);
+ Delete(parents);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Printv(f_go_wrappers, "type ", go_name, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\tSwigcptr() uintptr\n", NULL);
+ Printv(f_go_wrappers, "\tSwigIs", go_name, "()\n", NULL);
+
+ if (is_director) {
+ Printv(f_go_wrappers, "\tDirectorInterface() interface{}\n", NULL);
+ }
+
+ Append(f_go_wrappers, interfaces);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+ Delete(interfaces);
+
+ interfaces = NULL;
+ class_name = NULL;
+ class_receiver = NULL;
+ class_node = NULL;
+ Delete(class_methods);
+ class_methods = NULL;
+
+ Delete(go_type_name);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addBase()
+ *
+ * Implement methods and members defined in a parent class for a
+ * child class.
+ * ------------------------------------------------------------ */
+
+ int addBase(Node *n, Node *base, List *bases, Hash *local) {
+ if (GetFlag(base, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ for (Node *ni = Getattr(base, "firstChild"); ni; ni = nextSibling(ni)) {
+ int r = goBaseEntry(n, bases, local, ni);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ List *baselist = Getattr(base, "bases");
+ if (baselist && Len(baselist) > 0) {
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ List *nb = Copy(bases);
+ Append(nb, Getattr(b.item, "classtype"));
+ int r = addBase(n, b.item, nb, local);
+ Delete(nb);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * goBaseEntry()
+ *
+ * Implement one entry defined in a parent class for a child class.
+ * n is the child class.
+ * ------------------------------------------------------------ */
+
+ int goBaseEntry(Node* n, List* bases, Hash *local, Node* entry) {
+ if (GetFlag(entry, "feature:ignore")) {
+ return SWIG_OK;
+ }
+
+ if (!is_public(entry)) {
+ return SWIG_OK;
+ }
+
+ String *type = Getattr(entry, "nodeType");
+ if (Strcmp(type, "constructor") == 0 || Strcmp(type, "destructor") == 0 || Strcmp(type, "enum") == 0 || Strcmp(type, "using") == 0 || Strcmp(type, "classforward") == 0 || Strcmp(type, "template") == 0) {
+ return SWIG_OK;
+ }
+
+ if (Strcmp(type, "extend") == 0) {
+ for (Node* extend = firstChild(entry); extend; extend = nextSibling(extend)) {
+ if (isStatic(extend)) {
+ // If we don't do this, the extend_default test case fails.
+ continue;
+ }
+
+ int r = goBaseEntry(n, bases, local, extend);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ return SWIG_OK;
+ }
+
+ String *storage = Getattr(entry, "storage");
+ if (storage && (Strcmp(storage, "typedef") == 0 || Strstr(storage, "friend"))) {
+ return SWIG_OK;
+ }
+
+ String *mname = Getattr(entry, "sym:name");
+ if (!mname) {
+ return SWIG_OK;
+ }
+
+ String *lname = Getattr(entry, "name");
+ if (Getattr(class_methods, lname)) {
+ return SWIG_OK;
+ }
+ if (Getattr(local, lname)) {
+ return SWIG_OK;
+ }
+ Setattr(local, lname, NewString(""));
+
+ String *ty = NewString(Getattr(entry, "type"));
+ SwigType_push(ty, Getattr(entry, "decl"));
+ String *fullty = SwigType_typedef_resolve_all(ty);
+ bool is_function = SwigType_isfunction(fullty) ? true : false;
+ Delete(ty);
+ Delete(fullty);
+
+ if (is_function) {
+ int r = goBaseMethod(n, bases, entry);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (Getattr(entry, "sym:overloaded")) {
+ for (Node *on = Getattr(entry, "sym:nextSibling"); on; on = Getattr(on, "sym:nextSibling")) {
+ r = goBaseMethod(n, bases, on);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ String *receiver = class_receiver;
+ bool is_static = isStatic(entry);
+ if (is_static) {
+ receiver = NULL;
+ }
+ String *go_name = buildGoName(Getattr(entry, "sym:name"), is_static, false);
+ r = makeDispatchFunction(entry, go_name, receiver, is_static, NULL, false);
+ Delete(go_name);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+ } else {
+ int r = goBaseVariable(n, bases, entry);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * goBaseMethod()
+ *
+ * Implement a method defined in a parent class for a child class.
+ * ------------------------------------------------------------ */
+
+ int goBaseMethod(Node *method_class, List *bases, Node *method) {
+ String *symname = Getattr(method, "sym:name");
+ if (!validIdentifier(symname)) {
+ return SWIG_OK;
+ }
+
+ String *name = NewString("");
+ Printv(name, Getattr(method_class, "sym:name"), "_", symname, NULL);
+
+ bool is_static = isStatic(method);
+
+ String *go_name = buildGoName(name, is_static, false);
+
+ String *overname = NULL;
+ if (Getattr(method, "sym:overloaded")) {
+ overname = Getattr(method, "sym:overname");
+ }
+ String *wname = Swig_name_wrapper(name);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Append(wname, unique_id);
+
+ String *result = NewString(Getattr(method, "type"));
+ SwigType_push(result, Getattr(method, "decl"));
+ if (SwigType_isqualifier(result)) {
+ Delete(SwigType_pop(result));
+ }
+ Delete(SwigType_pop_function(result));
+
+ // If the base method is imported, wrap:action may not be set.
+ Swig_save("goBaseMethod", method, "wrap:name", "wrap:action", "parms", NULL);
+ Setattr(method, "wrap:name", wname);
+ if (!Getattr(method, "wrap:action")) {
+ if (!is_static) {
+ Swig_MethodToFunction(method, getNSpace(), getClassType(), (Getattr(method, "template") ? SmartPointer : Extend | SmartPointer), NULL, false);
+ // Remove any self parameter that was just added.
+ ParmList *parms = Getattr(method, "parms");
+ if (parms && Getattr(parms, "self")) {
+ parms = CopyParmList(nextSibling(parms));
+ Setattr(method, "parms", parms);
+ }
+ } else {
+ String *call = Swig_cfunction_call(Getattr(method, "name"), Getattr(method, "parms"));
+ Setattr(method, "wrap:action", Swig_cresult(Getattr(method, "type"), Swig_cresult_name(), call));
+ }
+ }
+
+ // A method added by %extend in a base class may have void parms.
+ ParmList* parms = Getattr(method, "parms");
+ if (parms != NULL && SwigType_type(Getattr(parms, "type")) == T_VOID) {
+ parms = NULL;
+ }
+
+ int r = makeWrappers(method, go_name, overname, wname, bases, parms, result, is_static);
+
+ Swig_restore(method);
+
+ Delete(result);
+ Delete(go_name);
+ Delete(name);
+
+ return r;
+ }
+
+ /* ------------------------------------------------------------
+ * goBaseVariable()
+ *
+ * Add accessors for a member variable defined in a parent class for
+ * a child class.
+ * ------------------------------------------------------------ */
+
+ int goBaseVariable(Node *var_class, List *bases, Node *var) {
+ if (isStatic(var)) {
+ return SWIG_OK;
+ }
+
+ String *var_name = buildGoName(Getattr(var, "sym:name"), false, false);
+
+ Swig_save("goBaseVariable", var, "type", "wrap:action", NULL);
+
+ // For a pointer type we apparently have to wrap in the decl.
+ SwigType *var_type = NewString(Getattr(var, "type"));
+ SwigType_push(var_type, Getattr(var, "decl"));
+ Setattr(var, "type", var_type);
+
+ SwigType *vt = Copy(var_type);
+
+ int flags = Extend | SmartPointer | use_naturalvar_mode(var);
+ if (isNonVirtualProtectedAccess(var)) {
+ flags |= CWRAP_ALL_PROTECTED_ACCESS;
+ }
+
+ // Copied from Swig_wrapped_member_var_type.
+ if (SwigType_isclass(vt)) {
+ if (flags & CWRAP_NATURAL_VAR) {
+ if (CPlusPlus) {
+ if (!SwigType_isconst(vt)) {
+ SwigType_add_qualifier(vt, "const");
+ }
+ SwigType_add_reference(vt);
+ }
+ } else {
+ SwigType_add_pointer(vt);
+ }
+ }
+
+ String *mname = Swig_name_member(getNSpace(), Getattr(var_class, "sym:name"), var_name);
+
+ if (!is_immutable(var)) {
+ for (Iterator ki = First(var); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0) {
+ Delattr(var, ki.key);
+ }
+ }
+ Swig_save("goBaseVariableSet", var, "name", "sym:name", "type", NULL);
+
+ String *mname_set = NewString("Set");
+ Append(mname_set, mname);
+
+ String *go_name = NewString("Set");
+ Append(go_name, var_name);
+
+ Swig_MembersetToFunction(var, class_name, flags);
+
+ String *wname = Swig_name_wrapper(mname_set);
+ Append(wname, unique_id);
+ ParmList *parms = NewParm(vt, var_name, var);
+ String *result = NewString("void");
+ int r = makeWrappers(var, go_name, NULL, wname, bases, parms, result, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(wname);
+ Delete(parms);
+ Delete(result);
+ Delete(go_name);
+ Delete(mname_set);
+
+ Swig_restore(var);
+ for (Iterator ki = First(var); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0) {
+ Delattr(var, ki.key);
+ }
+ }
+ }
+
+ Swig_MembergetToFunction(var, class_name, flags);
+
+ String *mname_get = NewString("Get");
+ Append(mname_get, mname);
+
+ String *go_name = NewString("Get");
+ Append(go_name, var_name);
+
+ String *wname = Swig_name_wrapper(mname_get);
+ Append(wname, unique_id);
+
+ int r = makeWrappers(var, go_name, NULL, wname, bases, NULL, vt, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(wname);
+ Delete(mname_get);
+ Delete(go_name);
+ Delete(mname);
+ Delete(var_name);
+ Delete(var_type);
+ Delete(vt);
+
+ Swig_restore(var);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addFirstBaseInterface()
+ *
+ * When a C++ class uses multiple inheritance, we can use the C++
+ * pointer for the first base class but not for any subsequent base
+ * classes. However, the Go interface will match the interface for
+ * all the base classes. To avoid accidentally treating a class as
+ * a pointer to a base class other than the first one, we use an
+ * isClassname method. This function adds those methods as
+ * required.
+ *
+ * For convenience when using multiple inheritance, we also add
+ * functions to retrieve the base class pointers.
+ * ------------------------------------------------------------ */
+
+ void addFirstBaseInterface(Node *n, Hash *parents, List *bases) {
+ if (!bases || Len(bases) == 0) {
+ return;
+ }
+ Iterator b = First(bases);
+ if (!GetFlag(b.item, "feature:ignore")) {
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+ String *go_base_type = goType(n, Getattr(b.item, "classtypeobj"));
+ String *go_base_type_name = goCPointerType(Getattr(b.item, "classtypeobj"), true);
+
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_base_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigIs", go_base_name, "()\n", NULL);
+
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_type, " {\n", NULL);
+ Printv(f_go_wrappers, "\treturn ", go_base_type_name, "(getSwigcptr(p))\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_type, "\n", NULL);
+
+ Setattr(parents, go_base_name, NewString(""));
+
+ Delete(go_name);
+ Delete(go_type_name);
+ Delete(go_base_type);
+ Delete(go_base_type_name);
+ }
+
+ addFirstBaseInterface(n, parents, Getattr(b.item, "bases"));
+ }
+
+ /* ------------------------------------------------------------
+ * addExtraBaseInterfaces()
+ *
+ * Add functions to retrieve the base class pointers for all base
+ * classes other than the first.
+ * ------------------------------------------------------------ */
+
+ int addExtraBaseInterfaces(Node *n, Hash *parents, List *bases) {
+ Iterator b = First(bases);
+
+ Node *fb = b.item;
+
+ for (b = Next(b); b.item; b = Next(b)) {
+ if (GetFlag(b.item, "feature:ignore")) {
+ continue;
+ }
+
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+
+ Swig_save("addExtraBaseInterface", n, "wrap:action", "wrap:name", "wrap:parms", NULL);
+
+ SwigType *type = Copy(Getattr(n, "classtypeobj"));
+ SwigType_add_pointer(type);
+ Parm *parm = NewParm(type, "self", n);
+ Setattr(n, "wrap:parms", parm);
+
+ String *pn = Swig_cparm_name(parm, 0);
+ String *action = NewString("");
+ Printv(action, Swig_cresult_name(), " = (", Getattr(b.item, "classtype"), "*)", pn, ";", NULL);
+ Delete(pn);
+
+ Setattr(n, "wrap:action", action);
+
+ String *name = Copy(class_name);
+ Append(name, "_SwigGet");
+ Append(name, go_base_name);
+
+ String *go_name = NewString("SwigGet");
+ String *c1 = exportedName(go_base_name);
+ Append(go_name, c1);
+ Delete(c1);
+
+ String *wname = Swig_name_wrapper(name);
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ SwigType *result = Copy(Getattr(b.item, "classtypeobj"));
+ SwigType_add_pointer(result);
+
+ int r = makeWrappers(n, go_name, NULL, wname, NULL, parm, result, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Swig_restore(n);
+
+ Setattr(parents, go_base_name, NewString(""));
+
+ Delete(go_name);
+ Delete(type);
+ Delete(parm);
+ Delete(action);
+ Delete(result);
+
+ String *ns = NewString("");
+ addParentExtraBaseInterfaces(n, parents, b.item, false, ns);
+ Delete(ns);
+ }
+
+ if (!GetFlag(fb, "feature:ignore")) {
+ String *ns = NewString("");
+ addParentExtraBaseInterfaces(n, parents, fb, true, ns);
+ Delete(ns);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * addParentExtraBaseInterfaces()
+ *
+ * Add functions to retrieve the base class pointers for all base
+ * classes of parents other than the first base class at each level.
+ * ------------------------------------------------------------ */
+
+ void addParentExtraBaseInterfaces(Node *n, Hash *parents, Node *base, bool is_base_first, String *sofar) {
+ List *baselist = Getattr(base, "bases");
+ if (!baselist || Len(baselist) == 0) {
+ return;
+ }
+
+ String *go_this_base_name = exportedName(Getattr(base, "sym:name"));
+
+ String *sf = NewString("");
+ Printv(sf, sofar, ".SwigGet", go_this_base_name, "()", NULL);
+
+ Iterator b = First(baselist);
+
+ if (is_base_first) {
+ if (!b.item) {
+ return;
+ }
+ if (!GetFlag(b.item, "feature:ignore")) {
+ addParentExtraBaseInterfaces(n, parents, b.item, true, sf);
+ }
+
+ b = Next(b);
+ }
+
+ String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ for (; b.item; b = Next(b)) {
+ if (GetFlag(b.item, "feature:ignore")) {
+ continue;
+ }
+
+ String *go_base_name = exportedName(Getattr(b.item, "sym:name"));
+
+ if (!Getattr(parents, go_base_name)) {
+ Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, "() ", go_base_name, " {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p", sf, ".SwigGet", go_base_name, "()\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_name, "\n", NULL);
+
+ addParentExtraBaseInterfaces(n, parents, b.item, false, sf);
+
+ Setattr(parents, go_base_name, NewString(""));
+ }
+ }
+
+ Delete(go_name);
+ Delete(go_type_name);
+ Delete(go_this_base_name);
+ Delete(sf);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorInit
+ *
+ * Add support for a director class.
+ *
+ * Virtual inheritance is different in Go and C++. We implement
+ * director classes by defining a new function in Go,
+ * NewDirectorClassname, which takes a empty interface value and
+ * creates an instance of a new child class. The new child class
+ * refers all methods back to Go. The Go code checks whether the
+ * value passed to NewDirectorClassname implements that method; if
+ * it does, it calls it, otherwise it calls back into C++.
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ // Because we use a different function to handle inheritance in
+ // Go, ordinary creations of the object should not create a
+ // director object.
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$nondirector_new");
+
+ class_node = n;
+
+ String *name = Getattr(n, "sym:name");
+
+ assert(!class_name);
+ class_name = name;
+
+ String *go_name = exportedName(name);
+
+ String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true);
+
+ assert(!class_receiver);
+ class_receiver = go_type_name;
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, go_name);
+
+ String *cxx_director_name = NewString("SwigDirector_");
+ Append(cxx_director_name, name);
+
+ // The Go type of the director class.
+ Printv(f_go_wrappers, "type ", director_struct_name, " struct {\n", NULL);
+ Printv(f_go_wrappers, "\t", go_type_name, "\n", NULL);
+ Printv(f_go_wrappers, "\tv interface{}\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") Swigcptr() uintptr {\n", NULL);
+ Printv(f_go_wrappers, "\treturn getSwigcptr(p.", go_type_name, ")\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") SwigIs", go_name, "() {\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_go_wrappers, "func (p *", director_struct_name, ") DirectorInterface() interface{} {\n", NULL);
+ Printv(f_go_wrappers, "\treturn p.v\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ // Start defining the director class.
+ Printv(f_c_directors_h, "class ", cxx_director_name, " : public ", Getattr(n, "classtype"), "\n", NULL);
+ Printv(f_c_directors_h, "{\n", NULL);
+ Printv(f_c_directors_h, " public:\n", NULL);
+
+ Delete(director_struct_name);
+ Delete(cxx_director_name);
+
+ class_methods = NewHash();
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor
+ *
+ * Emit a constructor for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ }
+
+ String *go_name = exportedName(name);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ String *cn = exportedName(Getattr(parentNode(n), "sym:name"));
+
+ String *go_type_name = goCPointerType(Getattr(parentNode(n), "classtypeobj"), true);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ String *fn_name = NewString("_swig_NewDirector");
+ Append(fn_name, cn);
+ Append(fn_name, go_name);
+
+ if (!overname && !is_ignored) {
+ if (!checkNameConflict(fn_name, n, NULL)) {
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *fn_with_over_name = Copy(fn_name);
+ if (overname) {
+ Append(fn_with_over_name, overname);
+ }
+
+ String *wname = Swig_name_wrapper(fn_name);
+
+ if (overname) {
+ Append(wname, overname);
+ }
+ Append(wname, unique_id);
+ Setattr(n, "wrap:name", wname);
+
+ bool is_static = isStatic(n);
+
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ DelWrapper(dummy);
+
+ Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("goin", parms, NULL);
+ Swig_typemap_attach_parms("goargout", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
+ int parm_count = emit_num_arguments(parms);
+
+ String *func_name = NewString("NewDirector");
+ Append(func_name, go_name);
+
+ String *func_with_over_name = Copy(func_name);
+ if (overname) {
+ Append(func_with_over_name, overname);
+ }
+
+ SwigType *first_type = NewString("int");
+ Parm *first_parm = NewParm(first_type, "swig_p", n);
+ set_nextSibling(first_parm, parms);
+ Setattr(first_parm, "lname", "p");
+
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
+ if (!is_ignored) {
+ Printv(f_cgo_comment, "extern uintptr_t ", wname, "(int", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type);
+ Printv(f_cgo_comment, ", ", ct, " ", Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+ Printv(f_cgo_comment, ");\n", NULL);
+
+ // Write out the Go function that calls the wrapper.
+
+ Printv(f_go_wrappers, "func ", func_with_over_name, "(v interface{}", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") ", cn, " {\n", NULL);
+
+ Printv(f_go_wrappers, "\tp := &", director_struct_name, "{0, v}\n", NULL);
+
+ String *call = NewString("");
+
+ Printv(call, "\tp.", class_receiver, " = ", NULL);
+ Printv(call, go_type_name, "(C.", wname, "(C.int(swigDirectorAdd(p))", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+
+ p = getParm(p);
+ String *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
+ if (goTypeIsInterface(p, pt)) {
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ }
+
+ Setattr(p, "emit:goinput", ivar);
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+ Delete(ct);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, "))", NULL);
+
+ Printv(f_go_wrappers, call, "\n", NULL);
+
+ goargout(parms);
+
+ Printv(f_go_wrappers, "\treturn p\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ SwigType *result = Copy(Getattr(parentNode(n), "classtypeobj"));
+ SwigType_add_pointer(result);
+
+ Swig_save("classDirectorConstructor", n, "wrap:name", "wrap:action", NULL);
+
+ String *dwname = Swig_name_wrapper(name);
+ Append(dwname, unique_id);
+ Setattr(n, "wrap:name", dwname);
+
+ String *action = NewString("");
+ Printv(action, Swig_cresult_name(), " = new SwigDirector_", class_name, "(", NULL);
+ String *pname = Swig_cparm_name(NULL, 0);
+ Printv(action, pname, NULL);
+ Delete(pname);
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *pname = Swig_cparm_name(NULL, i + 1);
+ Printv(action, ", ", NULL);
+ if (SwigType_isreference(Getattr(p, "type"))) {
+ Printv(action, "*", NULL);
+ }
+ Printv(action, pname, NULL);
+ Delete(pname);
+ p = nextParm(p);
+ }
+ Printv(action, ");", NULL);
+ Setattr(n, "wrap:action", action);
+
+ cgoWrapperInfo info;
+
+ info.n = n;
+ info.go_name = func_name;
+ info.overname = overname;
+ info.wname = wname;
+ info.base = NULL;
+ info.parms = first_parm;
+ info.result = result;
+ info.is_static = false;
+ info.receiver = NULL;
+ info.is_constructor = true;
+ info.is_destructor = false;
+
+ int r = cgoGccWrapper(&info);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Swig_restore(n);
+
+ Delete(result);
+ }
+
+ String *cxx_director_name = NewString("SwigDirector_");
+ Append(cxx_director_name, class_name);
+
+ String *decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0);
+ Printv(f_c_directors_h, " ", decl, ";\n", NULL);
+ Delete(decl);
+
+ decl = Swig_method_decl(NULL, Getattr(n, "decl"), cxx_director_name, first_parm, 0);
+ Printv(f_c_directors, cxx_director_name, "::", decl, "\n", NULL);
+ Delete(decl);
+
+ Printv(f_c_directors, " : ", Getattr(parentNode(n), "classtype"), "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_c_directors, ", ", NULL);
+ }
+ String *pn = Getattr(p, "name");
+ assert(pn);
+ Printv(f_c_directors, pn, NULL);
+ p = nextParm(p);
+ }
+ Printv(f_c_directors, "),\n", NULL);
+ Printv(f_c_directors, " go_val(swig_p), swig_mem(0)\n", NULL);
+ Printv(f_c_directors, "{ }\n\n", NULL);
+
+ if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) {
+ int r = makeDispatchFunction(n, func_name, cn, is_static, Getattr(parentNode(n), "classtypeobj"), false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ }
+
+ Delete(cxx_director_name);
+ Delete(go_name);
+ Delete(cn);
+ Delete(go_type_name);
+ Delete(director_struct_name);
+ Delete(fn_name);
+ Delete(fn_with_over_name);
+ Delete(func_name);
+ Delete(func_with_over_name);
+ Delete(wname);
+ Delete(first_type);
+ Delete(first_parm);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDestructor
+ *
+ * Emit a destructor for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorDestructor(Node *n) {
+ if (!is_public(n)) {
+ return SWIG_OK;
+ }
+
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (!is_ignored) {
+ String *fnname = NewString("DeleteDirector");
+ String *c1 = exportedName(class_name);
+ Append(fnname, c1);
+ Delete(c1);
+
+ String *wname = Swig_name_wrapper(fnname);
+ Append(wname, unique_id);
+
+ Setattr(n, "wrap:name", fnname);
+
+ Swig_DestructorToFunction(n, getNSpace(), getClassType(), CPlusPlus, Extend);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ String *result = NewString("void");
+ int r = makeWrappers(n, fnname, NULL, wname, NULL, parms, result, isStatic(n));
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(result);
+ Delete(fnname);
+ Delete(wname);
+ }
+
+ // Generate the destructor for the C++ director class. Since the
+ // Go code is keeping a pointer to the C++ object, we need to call
+ // back to the Go code to let it know that the C++ object is gone.
+
+ String *go_name = NewString("Swiggo_DeleteDirector_");
+ Append(go_name, class_name);
+
+ String *cn = exportedName(class_name);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ Printv(f_c_directors_h, " virtual ~SwigDirector_", class_name, "()", NULL);
+
+ String *throws = buildThrow(n);
+ if (throws) {
+ Printv(f_c_directors_h, " ", throws, NULL);
+ }
+
+ Printv(f_c_directors_h, ";\n", NULL);
+
+ String *director_sig = NewString("");
+
+ Printv(director_sig, "SwigDirector_", class_name, "::~SwigDirector_", class_name, "()", NULL);
+
+ if (throws) {
+ Printv(director_sig, " ", throws, NULL);
+ Delete(throws);
+ }
+
+ Printv(director_sig, "\n", NULL);
+ Printv(director_sig, "{\n", NULL);
+
+ if (is_ignored) {
+ Printv(f_c_directors, director_sig, NULL);
+ } else {
+ makeDirectorDestructorWrapper(go_name, director_struct_name, director_sig);
+ }
+
+ Printv(f_c_directors, " delete swig_mem;\n", NULL);
+
+ Printv(f_c_directors, "}\n\n", NULL);
+
+ Delete(director_sig);
+ Delete(go_name);
+ Delete(cn);
+ Delete(director_struct_name);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * makeDirectorDestructorWrapper
+ *
+ * Emit the function wrapper for the destructor of a director class.
+ * ------------------------------------------------------------ */
+
+ void makeDirectorDestructorWrapper(String *go_name, String *director_struct_name, String *director_sig) {
+ String *wname = Copy(go_name);
+ Append(wname, unique_id);
+
+ Printv(f_go_wrappers, "//export ", wname, "\n", NULL);
+ Printv(f_go_wrappers, "func ", wname, "(c int) {\n", NULL);
+ Printv(f_go_wrappers, "\tswigDirectorLookup(c).(*", director_struct_name, ").", class_receiver, " = 0\n", NULL);
+ Printv(f_go_wrappers, "\tswigDirectorDelete(c)\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Printv(f_c_directors, "extern \"C\" void ", wname, "(intgo);\n", NULL);
+ Printv(f_c_directors, director_sig, NULL);
+ Printv(f_c_directors, " ", wname, "(go_val);\n", NULL);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorMethod
+ *
+ * Emit a method for a director class, plus its overloads.
+ * ------------------------------------------------------------ */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+
+ // We don't need explicit calls.
+ if (GetFlag(n, "explicitcall")) {
+ return SWIG_OK;
+ }
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ (void)is_ignored;
+ name = Getattr(n, "name");
+ }
+
+ bool overloaded = Getattr(n, "sym:overloaded") && !Getattr(n, "explicitcallnode");
+ if (!overloaded) {
+ int r = oneClassDirectorMethod(n, parent, super);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ } else {
+ // Handle overloaded methods here, because otherwise we will
+ // reject them in the class_methods hash table. We need to use
+ // class_methods so that we correctly handle cases where a
+ // function in one class hides a function of the same name in a
+ // parent class.
+ if (!Getattr(class_methods, name)) {
+ for (Node *on = Getattr(n, "sym:overloaded"); on; on = Getattr(on, "sym:nextSibling")) {
+ // Swig_overload_rank expects wrap:name and wrap:parms to be
+ // set.
+ String *wn = Swig_name_wrapper(Getattr(on, "sym:name"));
+ Append(wn, Getattr(on, "sym:overname"));
+ Append(wn, unique_id);
+ Setattr(on, "wrap:name", wn);
+ Delete(wn);
+ Setattr(on, "wrap:parms", Getattr(on, "parms"));
+ }
+ }
+
+ int r = oneClassDirectorMethod(n, parent, super);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!Getattr(n, "sym:nextSibling"))
+ {
+ // Last overloaded function
+ Node *on = Getattr(n, "sym:overloaded");
+ bool is_static = isStatic(on);
+
+ String *cn = exportedName(Getattr(parent, "sym:name"));
+ String *go_name = buildGoName(name, is_static, false);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ int r = makeDispatchFunction(on, go_name, director_struct_name, is_static, director_struct_name, false);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ if (!GetFlag(n, "abstract")) {
+ String *go_upcall = NewString("Director");
+ Append(go_upcall, cn);
+ Append(go_upcall, go_name);
+ r = makeDispatchFunction(on, go_upcall, director_struct_name, is_static, director_struct_name, true);
+ if (r != SWIG_OK) {
+ return r;
+ }
+ Delete(go_upcall);
+ }
+
+ Delete(director_struct_name);
+ Delete(go_name);
+ Delete(cn);
+ }
+ }
+ Setattr(class_methods, name, NewString(""));
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * oneClassDirectorMethod
+ *
+ * Emit a method for a director class.
+ * ------------------------------------------------------------ */
+
+ int oneClassDirectorMethod(Node *n, Node *parent, String *super) {
+ String *symname = Getattr(n, "sym:name");
+ if (!checkFunctionVisibility(n, parent)) {
+ return SWIG_OK;
+ }
+
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
+ bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 && Cmp(Getattr(n, "value"), "0") == 0);
+
+ String *name = Getattr(n, "sym:name");
+ if (!name) {
+ assert(is_ignored);
+ name = Getattr(n, "name");
+ }
+
+ String *overname = NULL;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ }
+
+ String *cn = exportedName(Getattr(parent, "sym:name"));
+
+ String *go_type_name = goCPointerType(Getattr(parent, "classtypeobj"), true);
+
+ String *director_struct_name = NewString("_swig_Director");
+ Append(director_struct_name, cn);
+
+ bool is_static = isStatic(n);
+
+ String *go_name = buildGoName(name, is_static, false);
+
+ ParmList *parms = Getattr(n, "parms");
+ Setattr(n, "wrap:parms", parms);
+
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+
+ Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
+ int parm_count = emit_num_arguments(parms);
+
+ SwigType *returntype = Getattr(n, "type");
+ bool is_void = !(Cmp(returntype, "void"));
+
+ // Save the type for overload processing.
+ Setattr(n, "go:type", returntype);
+
+ String *interface_name = NewString("_swig_DirectorInterface");
+ Append(interface_name, cn);
+ Append(interface_name, go_name);
+ if (overname) {
+ Append(interface_name, overname);
+ }
+
+ String *callback_name = Copy(director_struct_name);
+ Append(callback_name, "_callback_");
+ Append(callback_name, name);
+ Replace(callback_name, "_swig", "Swig", DOH_REPLACE_FIRST);
+ if (overname) {
+ Append(callback_name, overname);
+ }
+ Append(callback_name, unique_id);
+
+ String *upcall_name = Copy(director_struct_name);
+ Append(upcall_name, "_upcall_");
+ Append(upcall_name, go_name);
+
+ String *upcall_wname = Swig_name_wrapper(upcall_name);
+ if (overname) {
+ Append(upcall_wname, overname);
+ }
+ Append(upcall_wname, unique_id);
+
+ String *upcall_gc_name = buildGoWrapperName(upcall_name, overname);
+
+ String *go_with_over_name = Copy(go_name);
+ if (overname) {
+ Append(go_with_over_name, overname);
+ }
+
+ Parm *p = 0;
+ Wrapper *w = NewWrapper();
+
+ Swig_director_parms_fixup(parms);
+
+ Swig_typemap_attach_parms("directorin", parms, w);
+ Swig_typemap_attach_parms("directorargout", parms, w);
+ Swig_typemap_attach_parms("godirectorin", parms, w);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+
+ DelWrapper(dummy);
+
+ if (!is_ignored) {
+ // We use an interface to see if this method is defined in Go.
+ Printv(f_go_wrappers, "type ", interface_name, " interface {\n", NULL);
+ Printv(f_go_wrappers, "\t", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (!is_void) {
+ String *tm = goType(n, returntype);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, "\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (!GetFlag(n, "abstract")) {
+ Printv(f_cgo_comment, "extern ", NULL);
+
+ if (is_void) {
+ Printv(f_cgo_comment, "void", NULL);
+ } else {
+ bool c_struct_type;
+ String *ret_type = cgoTypeForGoValue(n, returntype, &c_struct_type);
+ Printv(f_cgo_comment, ret_type, NULL);
+ Delete(ret_type);
+ }
+
+ Printv(f_cgo_comment, " ", upcall_wname, "(uintptr_t", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, Getattr(p, "type"), &c_struct_type);
+ Printv(f_cgo_comment, ", ", ct, " ", Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+ Printv(f_cgo_comment, ");\n", NULL);
+ }
+
+ // Define the method on the director class in Go.
+
+ Printv(f_go_wrappers, "func (swig_p *", director_struct_name, ") ", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (!is_void) {
+ String *tm = goType(n, returntype);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ Printv(f_go_wrappers, "\tif swig_g, swig_ok := swig_p.v.(", interface_name, "); swig_ok {\n", NULL);
+ Printv(f_go_wrappers, "\t\t", NULL);
+ if (!is_void) {
+ Printv(f_go_wrappers, "return ", NULL);
+ }
+ Printv(f_go_wrappers, "swig_g.", go_with_over_name, "(", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")\n", NULL);
+ if (is_void) {
+ Printv(f_go_wrappers, "\t\treturn\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t}\n", NULL);
+
+ if (GetFlag(n, "abstract")) {
+ Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
+ } else {
+ String *ret_type = NULL;
+ bool memcpy_ret = false;
+ String *wt = NULL;
+ String *goout = NULL;
+ if (!is_void) {
+ ret_type = goImType(n, returntype);
+ Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+ goout = goTypemapLookup("goout", n, "swig_r");
+
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(n, returntype, &c_struct_type));
+ if (c_struct_type) {
+ memcpy_ret = true;
+ }
+ }
+
+ String *call = NewString("");
+
+ Printv(call, "\t", NULL);
+ if (!is_void) {
+ if (memcpy_ret) {
+ Printv(call, "swig_r_p := ", NULL);
+ } else {
+ Printv(call, "swig_r = (", ret_type, ")(", NULL);
+ }
+ if (goTypeIsInterface(n, returntype)) {
+ wt = goWrapperType(n, returntype, true);
+ Printv(call, "(", wt, ")(", NULL);
+ }
+ }
+
+ Printv(call, "C.", upcall_wname, "(C.uintptr_t(swig_p.",
+ go_type_name, ")", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+ p = getParm(p);
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = Getattr(p, "lname");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ // This is an ordinary call from Go to C++, so adjust using
+ // the goin typemap.
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
+ if (goTypeIsInterface(p, pt)) {
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ }
+
+ Setattr(p, "emit:goinput", ivar);
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (wt) {
+ // Close the type conversion to the wrapper type.
+ Printv(call, ")", NULL);
+ }
+ if (!is_void && !memcpy_ret) {
+ // Close the type conversion of the return value.
+ Printv(call, ")", NULL);
+ }
+
+ Printv(call, "\n", NULL);
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (memcpy_ret) {
+ Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+ }
+
+ goargout(parms);
+
+ if (!is_void) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, returntype);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ if (ret_type) {
+ Delete(ret_type);
+ }
+ if (wt) {
+ Delete(wt);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (!GetFlag(n, "abstract")) {
+ // Define a function that uses the Go director type that other
+ // methods in the Go type can call to get parent methods.
+
+ Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(swig_p ", cn, NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL);
+ String *tm = goType(p, Getattr(p, "type"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ")", NULL);
+
+ if (!is_void) {
+ String *tm = goType(n, returntype);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ Delete(tm);
+ }
+
+ Printv(f_go_wrappers, " {\n", NULL);
+
+ String *ret_type = NULL;
+ bool memcpy_ret = false;
+ String *wt = NULL;
+ String *goout = NULL;
+ if (!is_void) {
+ ret_type = goImType(n, returntype);
+ Printv(f_go_wrappers, "\tvar swig_r ", ret_type, "\n", NULL);
+ goout = goTypemapLookup("goout", n, "swig_r");
+
+ bool c_struct_type;
+ Delete(cgoTypeForGoValue(n, returntype, &c_struct_type));
+ if (c_struct_type) {
+ memcpy_ret = true;
+ }
+ }
+
+ String *call = NewString("");
+
+ Printv(call, "\t", NULL);
+ if (!is_void) {
+ if (memcpy_ret) {
+ Printv(call, "swig_r_p := ", NULL);
+ } else {
+ Printv(call, "swig_r = (", ret_type, ")(", NULL);
+ }
+ if (goTypeIsInterface(n, returntype)) {
+ wt = goWrapperType(n, returntype, true);
+ Printv(call, "(", wt, ")(", NULL);
+ }
+ }
+
+ Printv(call, "C.", upcall_wname, "(C.uintptr_t(swig_p.(*",
+ director_struct_name, ").", go_type_name, ")", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
+ p = getParm(p);
+ SwigType *pt = Getattr(p, "type");
+
+ String *ivar = NewStringf("_swig_i_%d", i);
+
+ String *ln = Copy(Getattr(p, "lname"));
+
+ String *goin = goGetattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(f_go_wrappers, "\t", ivar, " := ", NULL);
+ bool need_close = false;
+ if (goTypeIsInterface(p, pt)) {
+ Printv(f_go_wrappers, "getSwigcptr(", NULL);
+ need_close = true;
+ }
+ Printv(f_go_wrappers, ln, NULL);
+ if (need_close) {
+ Printv(f_go_wrappers, ")", NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ } else {
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, "\n", NULL);
+ Delete(goin);
+ }
+
+ Setattr(p, "emit:goinput", ivar);
+
+ bool c_struct_type;
+ String *ct = cgoTypeForGoValue(p, pt, &c_struct_type);
+ if (c_struct_type) {
+ Printv(call, "*(*C.", ct, ")(unsafe.Pointer(&", ivar, "))", NULL);
+ } else {
+ Printv(call, "C.", ct, "(", ivar, ")", NULL);
+ }
+
+ Delete(ln);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (wt) {
+ // Close the type conversion to the wrapper type.
+ Printv(call, ")", NULL);
+ }
+ if (!is_void && !memcpy_ret) {
+ // Close the type conversion of the return value.
+ Printv(call, ")", NULL);
+ }
+
+ Printv(call, "\n", NULL);
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (memcpy_ret) {
+ Printv(f_go_wrappers, "\tswig_r = *(*", ret_type, ")(unsafe.Pointer(&swig_r_p))\n", NULL);
+ }
+
+ goargout(parms);
+
+ if (!is_void) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, returntype);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ if (ret_type) {
+ Delete(ret_type);
+ }
+ if (wt) {
+ Delete(wt);
+ }
+
+ // Define a method in the C++ director class that the C++
+ // upcall function can call. This permits an upcall to a
+ // protected method.
+
+ String *upcall_method_name = NewString("_swig_upcall_");
+ Append(upcall_method_name, name);
+ if (overname) {
+ Append(upcall_method_name, overname);
+ }
+ SwigType *rtype = Getattr(n, "classDirectorMethods:type");
+ String *upcall_decl = Swig_method_decl(rtype, Getattr(n, "decl"), upcall_method_name, parms, 0);
+ Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL);
+ Delete(upcall_decl);
+
+ Printv(f_c_directors_h, " ", NULL);
+ if (!is_void) {
+ Printv(f_c_directors_h, "return ", NULL);
+ }
+
+ String *super_call = Swig_method_call(super, parms);
+ Printv(f_c_directors_h, super_call, ";\n", NULL);
+ Delete(super_call);
+
+ Printv(f_c_directors_h, " }\n", NULL);
+
+ // Define the C++ function that the Go function calls.
+
+ SwigType *first_type = NULL;
+ Parm *first_parm = parms;
+ if (!is_static) {
+ first_type = NewString("SwigDirector_");
+ Append(first_type, class_name);
+ SwigType_add_pointer(first_type);
+ first_parm = NewParm(first_type, "p", n);
+ set_nextSibling(first_parm, parms);
+ }
+
+ Swig_save("classDirectorMethod", n, "wrap:name", "wrap:action", NULL);
+
+ Setattr(n, "wrap:name", upcall_wname);
+
+ String *action = NewString("");
+ if (!is_void) {
+ Printv(action, Swig_cresult_name(), " = (", SwigType_lstr(returntype, 0), ")", NULL);
+ if (SwigType_isreference(returntype)) {
+ Printv(action, "&", NULL);
+ }
+ }
+ Printv(action, Swig_cparm_name(NULL, 0), "->", upcall_method_name, "(", NULL);
+
+ p = parms;
+ int i = 0;
+ while (p != NULL) {
+ if (SwigType_type(Getattr(p, "type")) != T_VOID) {
+ String *pname = Swig_cparm_name(NULL, i + 1);
+ if (i > 0) {
+ Printv(action, ", ", NULL);
+ }
+
+ // A parameter whose type is a reference is converted into a
+ // pointer type by gcCTypeForGoValue. We are calling a
+ // function which expects a reference so we need to convert
+ // back.
+ if (SwigType_isreference(Getattr(p, "type"))) {
+ Printv(action, "*", NULL);
+ }
+
+ Printv(action, pname, NULL);
+ Delete(pname);
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Printv(action, ");", NULL);
+ Setattr(n, "wrap:action", action);
+
+ cgoWrapperInfo info;
+
+ info.n = n;
+ info.go_name = go_name;
+ info.overname = overname;
+ info.wname = upcall_wname;
+ info.base = NULL;
+ info.parms = first_parm;
+ info.result = returntype;
+ info.is_static = is_static;
+ info.receiver = NULL;
+ info.is_constructor = false;
+ info.is_destructor = false;
+
+ int r = cgoGccWrapper(&info);
+ if (r != SWIG_OK) {
+ return r;
+ }
+
+ Delete(first_type);
+ if (first_parm != parms) {
+ Delete(first_parm);
+ }
+
+ Swig_restore(n);
+ Delete(upcall_method_name);
+ }
+
+ // The Go function which invokes the method. This is called by
+ // the C++ method on the director class.
+
+ Printv(f_go_wrappers, "//export ", callback_name, "\n",
+ "func ", callback_name, "(swig_c int", NULL);
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = goWrapperType(p, Getattr(p, "type"), false);
+ Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", tm, NULL);
+ Delete(tm);
+ p = nextParm(p);
+ }
+
+ Printv(f_go_wrappers, ") ", NULL);
+ String *result_wrapper = NULL;
+ if (!is_void) {
+ result_wrapper = goWrapperType(n, returntype, true);
+ Printv(f_go_wrappers, "(swig_result ", result_wrapper, ") ", NULL);
+ }
+ Printv(f_go_wrappers, "{\n", NULL);
+
+ if (is_ignored) {
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ } else {
+ bool result_is_interface = false;
+ String *goout = NULL;
+ if (!is_void) {
+ result_is_interface = goTypeIsInterface(NULL, returntype);
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (!result_is_interface) {
+ Printv(f_go_wrappers, goType(n, returntype), NULL);
+ } else {
+ Printv(f_go_wrappers, result_wrapper, NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ goout = goTypemapLookup("godirectorout", n, "swig_r");
+ }
+
+ String *call = NewString("");
+ Printv(call, "\t", NULL);
+
+ if (!is_void) {
+ Printv(call, "swig_r = ", NULL);
+ if (result_is_interface) {
+ Printv(call, result_wrapper, "(getSwigcptr(", NULL);
+ }
+ }
+ Printv(call, "swig_p.", go_with_over_name, "(", NULL);
+
+ String *goincode = NewString("");
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (i > 0) {
+ Printv(call, ", ", NULL);
+ }
+ SwigType *pt = Getattr(p, "type");
+
+ String *ln = NewString("");
+
+ // If the Go representation is an interface type class, then
+ // we are receiving a uintptr, and must convert to the
+ // interface.
+ bool is_interface = goTypeIsInterface(p, pt);
+ if (is_interface) {
+ // Passing is_result as true to goWrapperType gives us the
+ // name of the Go type we need to convert to an interface.
+ String *wt = goWrapperType(p, pt, true);
+ Printv(ln, wt, "(", NULL);
+ Delete(wt);
+ }
+
+ Printv(ln, Getattr(p, "lname"), NULL);
+
+ if (is_interface) {
+ Printv(ln, ")", NULL);
+ }
+
+ String *goin = goGetattr(p, "tmap:godirectorin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, "\n", NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(goincode, goin, "\n", NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Delete(ivar);
+ }
+
+ Delete(ln);
+
+ p = nextParm(p);
+ }
+
+ Printv(call, ")", NULL);
+
+ if (result_is_interface) {
+ Printv(call, "))", NULL);
+ }
+ Printv(call, "\n", NULL);
+
+ Printv(f_go_wrappers, "\tswig_p := swigDirectorLookup(swig_c).(*", director_struct_name, ")\n", NULL);
+ Printv(f_go_wrappers, goincode, NULL);
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (!is_void) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goImType(n, returntype);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, "\n", NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+ }
+
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Delete(result_wrapper);
+
+ Delete(upcall_wname);
+ Delete(upcall_gc_name);
+ Delete(go_with_over_name);
+ }
+
+ if (!is_ignored || is_pure_virtual) {
+ // Declare the method for the director class.
+
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), Getattr(n, "name"), parms, 0);
+ Printv(f_c_directors_h, " virtual ", decl, NULL);
+ Delete(decl);
+
+ String *qname = NewString("");
+ Printv(qname, "SwigDirector_", class_name, "::", Getattr(n, "name"), NULL);
+ decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0);
+ Printv(w->def, decl, NULL);
+ Delete(decl);
+ Delete(qname);
+
+ String *throws = buildThrow(n);
+ if (throws) {
+ Printv(f_c_directors_h, " ", throws, NULL);
+ Printv(w->def, " ", throws, NULL);
+ Delete(throws);
+ }
+
+ Printv(f_c_directors_h, ";\n", NULL);
+
+ Printv(w->def, " {\n", NULL);
+
+ if (!is_void) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (!is_ignored) {
+ makeDirectorMethodWrapper(n, w, callback_name);
+ } else {
+ assert(is_pure_virtual);
+ Printv(w->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL);
+ if (!is_void) {
+ String *retstr = SwigType_rcaststr(returntype, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ }
+ }
+
+ Printv(w->code, "}", NULL);
+
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_c_directors);
+ }
+
+ Delete(cn);
+ Delete(go_type_name);
+ Delete(director_struct_name);
+ Delete(interface_name);
+ Delete(callback_name);
+ Delete(upcall_name);
+ Delete(go_name);
+ DelWrapper(w);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * makeDirectorMethodWrapper
+ *
+ * Emit the function wrapper for a director method.
+ * ------------------------------------------------------------ */
+ void makeDirectorMethodWrapper(Node *n, Wrapper *w, String *callback_name) {
+ ParmList *parms = Getattr(n, "wrap:parms");
+ SwigType *returntype = Getattr(n, "type");
+ bool is_void = !(Cmp(returntype, "void"));
+
+ Printv(f_c_directors, "extern \"C\" ", NULL);
+
+ String *fnname = Copy(callback_name);
+ Append(fnname, "(int");
+
+ Parm *p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+ String *cg = gcCTypeForGoValue(p, Getattr(p, "type"), Getattr(p, "lname"));
+ Printv(fnname, ", ", cg, NULL);
+ Delete(cg);
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(fnname, ")", NULL);
+
+ if (is_void) {
+ Printv(f_c_directors, "void ", fnname, NULL);
+ } else {
+ String *tm = gcCTypeForGoValue(n, returntype, fnname);
+ Printv(f_c_directors, tm, NULL);
+ Delete(tm);
+ }
+
+ Delete(fnname);
+
+ Printv(f_c_directors, ";\n", NULL);
+
+ if (!is_void) {
+ String *r = NewString(Swig_cresult_name());
+ String *tm = gcCTypeForGoValue(n, returntype, r);
+ Wrapper_add_local(w, r, tm);
+ Delete(tm);
+ Delete(r);
+ }
+
+ String *args = NewString("");
+
+ p = parms;
+ while (p) {
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ String *pn = NewString("swig_");
+ Append(pn, Getattr(p, "lname"));
+ Setattr(p, "emit:directorinput", pn);
+
+ String *tm = gcCTypeForGoValue(p, Getattr(p, "type"), pn);
+ Wrapper_add_local(w, pn, tm);
+ Delete(tm);
+
+ tm = Getattr(p, "tmap:directorin");
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
+ line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", pn);
+ Replaceall(tm, "$owner", 0);
+ Printv(w->code, " ", tm, "\n", NULL);
+ Delete(tm);
+
+ Printv(args, ", ", pn, NULL);
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ Printv(w->code, " ", NULL);
+ if (!is_void) {
+ Printv(w->code, Swig_cresult_name(), " = ", NULL);
+ }
+ Printv(w->code, callback_name, "(go_val", args, ");\n", NULL);
+
+ /* Marshal outputs */
+ for (p = parms; p; ) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (!is_void) {
+ String *result_str = NewString("c_result");
+ String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
+ if (!tm) {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use type %s as director method returntype\n", SwigType_str(returntype, 0));
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, " ", tm, "\n", NULL);
+ String *retstr = SwigType_rcaststr(returntype, "c_result");
+ Printv(w->code, " return ", retstr, ";\n", NULL);
+ Delete(retstr);
+ Delete(tm);
+ }
+ Delete(result_str);
+ }
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd
+ *
+ * Complete support for a director class.
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ (void) n;
+
+ Printv(f_c_directors_h, " private:\n", NULL);
+ Printv(f_c_directors_h, " intgo go_val;\n", NULL);
+ Printv(f_c_directors_h, " Swig_memory *swig_mem;\n", NULL);
+ Printv(f_c_directors_h, "};\n\n", NULL);
+
+ class_name = NULL;
+ class_node = NULL;
+
+ Delete(class_receiver);
+ class_receiver = NULL;
+
+ Delete(class_methods);
+ class_methods = NULL;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDisown
+ *
+ * I think Go does not require a disown method.
+ * ------------------------------------------------------------ */
+
+ int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * buildThrow()
+ *
+ * Build and return a throw clause if needed.
+ *--------------------------------------------------------------------*/
+
+ String *buildThrow(Node *n) {
+ if (Getattr(n, "noexcept"))
+ return NewString("noexcept");
+ ParmList *throw_parm_list = Getattr(n, "throws");
+ if (!throw_parm_list && !Getattr(n, "throw"))
+ return NULL;
+ String *ret = NewString("throw(");
+ if (throw_parm_list) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, NULL);
+ }
+ bool first = true;
+ for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (first) {
+ first = false;
+ } else {
+ Printv(ret, ", ", NULL);
+ }
+ String *s = SwigType_str(Getattr(p, "type"), 0);
+ Printv(ret, s, NULL);
+ Delete(s);
+ }
+ }
+ Printv(ret, ")", NULL);
+ return ret;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *
+ * We don't need to check upcall when calling methods.
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * makeDispatchFunction
+ *
+ * Make a dispatch function for an overloaded C++ function. The
+ * receiver parameter is the receiver for a method, unless is_upcall
+ * is true. If is_upcall is true, then the receiver parameter is
+ * the type of the first argument to the function.
+ *--------------------------------------------------------------------*/
+
+ int makeDispatchFunction(Node *n, String *go_name, String *receiver, bool is_static, SwigType *director_struct, bool is_upcall) {
+ bool is_director = director_struct ? true : false;
+
+ String *nodetype = Getattr(n, "nodeType");
+ bool is_constructor = Cmp(nodetype, "constructor") == 0;
+ bool is_destructor = Cmp(nodetype, "destructor") == 0;
+
+ bool can_use_receiver = (!is_constructor && !is_destructor && !is_upcall);
+
+ bool use_receiver = (!is_static && can_use_receiver);
+
+ bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !is_upcall);
+
+ List *dispatch = Swig_overload_rank(n, false);
+ int nfunc = Len(dispatch);
+
+ SwigType *all_result;
+ bool mismatch;
+ if (is_constructor) {
+ assert(!is_upcall);
+ if (!is_director) {
+ all_result = Copy(Getattr(class_node, "classtypeobj"));
+ } else {
+ all_result = Copy(director_struct);
+ }
+ mismatch = false;
+ } else {
+ all_result = NULL;
+ mismatch = false;
+ bool any_void = false;
+ for (int i = 0; i < nfunc; ++i) {
+ Node *nn = Getitem(dispatch, i);
+ Node *ni = Getattr(nn, "directorNode") ? Getattr(nn, "directorNode") : nn;
+ SwigType *result = Getattr(ni, "go:type");
+ assert(result);
+
+ if (SwigType_type(result) == T_VOID) {
+ if (all_result) {
+ mismatch = true;
+ }
+ any_void = true;
+ } else {
+ if (any_void) {
+ mismatch = true;
+ } else if (!all_result) {
+ all_result = Copy(result);
+ } else if (Cmp(result, all_result) != 0) {
+ mismatch = true;
+ }
+ }
+ }
+ if (mismatch) {
+ Delete(all_result);
+ all_result = NULL;
+ } else if (all_result) {
+ ;
+ } else {
+ all_result = NewString("void");
+ }
+ }
+
+ Printv(f_go_wrappers, "func ", NULL);
+
+ if (receiver && use_receiver) {
+ Printv(f_go_wrappers, "(p ", receiver, ") ", NULL);
+ }
+
+ Printv(f_go_wrappers, go_name, "(", NULL);
+ if (is_director && is_constructor) {
+ Printv(f_go_wrappers, "abi interface{}, ", NULL);
+ assert(!add_to_interface);
+ }
+ if (is_upcall) {
+ Printv(f_go_wrappers, "p *", receiver, ", ", NULL);
+ assert(!add_to_interface);
+ }
+ Printv(f_go_wrappers, "a ...interface{})", NULL);
+
+ if (add_to_interface) {
+ Printv(interfaces, "\t", go_name, "(a ...interface{})", NULL);
+ }
+
+ if (mismatch) {
+ Printv(f_go_wrappers, " interface{}", NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " interface{}", NULL);
+ }
+ } else if (all_result && SwigType_type(all_result) != T_VOID) {
+ if (is_director && is_constructor) {
+ Printv(f_go_wrappers, " ", receiver, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " ", receiver, NULL);
+ }
+ } else {
+ String *tm = goType(n, all_result);
+ Printv(f_go_wrappers, " ", tm, NULL);
+ if (add_to_interface) {
+ Printv(interfaces, " ", tm, NULL);
+ }
+ Delete(tm);
+ }
+ }
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (add_to_interface) {
+ Printv(interfaces, "\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\targc := len(a)\n", NULL);
+
+ for (int i = 0; i < nfunc; ++i) {
+ int fn = 0;
+ Node *nn = Getitem(dispatch, i);
+ Node *ni = Getattr(nn, "directorNode") ? Getattr(nn, "directorNode") : nn;
+ Parm *pi = Getattr(ni, "wrap:parms");
+
+ // If we are using a receiver, we want to ignore a leading self
+ // parameter. Because of the way this is called, there may or
+ // may not be a self parameter at this point.
+ if (use_receiver && pi && Getattr(pi, "self")) {
+ pi = getParm(pi);
+ if (pi) {
+ pi = nextParm(pi);
+ }
+ }
+
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ bool varargs = emit_isvarargs(pi) ? true : false;
+
+ if (varargs) {
+ Printf(f_go_wrappers, "\tif argc >= %d {\n", num_required);
+ } else {
+ if (num_required == num_arguments) {
+ Printf(f_go_wrappers, "\tif argc == %d {\n", num_required);
+ } else {
+ Printf(f_go_wrappers, "\tif argc >= %d && argc <= %d {\n", num_required, num_arguments);
+ }
+ }
+
+ // Build list of collisions with the same number of arguments.
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; ++k) {
+ Node *nnk = Getitem(dispatch, k);
+ Node *nk = Getattr(nnk, "directorNode") ? Getattr(nnk, "directorNode") : nnk;
+ Parm *pk = Getattr(nk, "wrap:parms");
+ if (use_receiver && pk && Getattr(pk, "self")) {
+ pk = getParm(pk);
+ if (pk) {
+ pk = nextParm(pk);
+ }
+ }
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments)
+ || (nak >= num_required && nak <= num_arguments)
+ || (nrk <= num_required && nak >= num_arguments)
+ || (varargs && nrk >= num_required)) {
+ Append(coll, nk);
+ }
+ }
+
+ int num_braces = 0;
+ if (Len(coll) > 0 && num_arguments > 0) {
+ int j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ pj = getParm(pj);
+ if (!pj) {
+ break;
+ }
+
+ // If all the overloads have the same type in this position,
+ // we can omit the check.
+ SwigType *tm = goOverloadType(pj, Getattr(pj, "type"));
+ bool emitcheck = false;
+ for (int k = 0; k < Len(coll) && !emitcheck; ++k) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ if (use_receiver && pk && Getattr(pk, "self")) {
+ pk = getParm(pk);
+ if (pk) {
+ pk = nextParm(pk);
+ }
+ }
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ while (pl && l <= j) {
+ pl = getParm(pl);
+ if (!pl) {
+ break;
+ }
+ if (l == j) {
+ SwigType *tml = goOverloadType(pl, Getattr(pl, "type"));
+ if (Cmp(tm, tml) != 0) {
+ emitcheck = true;
+ }
+ Delete(tml);
+ }
+ pl = nextParm(pl);
+ ++l;
+ }
+ }
+
+ if (emitcheck) {
+ if (j >= num_required) {
+ Printf(f_go_wrappers, "\t\tif argc > %d {\n", j);
+ ++num_braces;
+ }
+
+ fn = i + 1;
+ Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, tm);
+ Printf(f_go_wrappers, "\t\t\tgoto check_%d\n", fn);
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ Delete(tm);
+
+ pj = nextParm(pj);
+
+ ++j;
+ }
+ }
+
+ for (; num_braces > 0; --num_braces) {
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ // We may need to generate multiple calls if there are variable
+ // argument lists involved. Build the start of the call.
+
+ String *start = NewString("");
+
+ SwigType *result = Getattr(ni, "go:type");
+
+ if (is_constructor) {
+ result = all_result;
+ } else if (is_destructor) {
+ result = NULL;
+ }
+
+ if (result && SwigType_type(result) != T_VOID && (!all_result || SwigType_type(all_result) != T_VOID)) {
+ Printv(start, "return ", NULL);
+ }
+
+ bool advance_parm = false;
+
+ if (receiver && use_receiver) {
+ Printv(start, "p.", go_name, NULL);
+ } else if (can_use_receiver && !isStatic(ni) && pi && Getattr(pi, "self")) {
+ // This is an overload of a static function and a non-static
+ // function.
+ assert(num_required > 0);
+ SwigType *tm = goWrapperType(pi, Getattr(pi, "type"), true);
+ String *nm = buildGoName(Getattr(ni, "sym:name"), false, isFriend(ni));
+ Printv(start, "a[0].(", tm, ").", nm, NULL);
+ Delete(nm);
+ Delete(tm);
+ advance_parm = true;
+ } else {
+ Printv(start, go_name, NULL);
+ }
+
+ Printv(start, Getattr(ni, "sym:overname"), "(", NULL);
+
+ bool need_comma = false;
+
+ if (is_director && is_constructor) {
+ Printv(start, "abi", NULL);
+ need_comma = true;
+ }
+ if (is_upcall) {
+ Printv(start, "p", NULL);
+ need_comma = true;
+ }
+ Parm *p = pi;
+ int pn = 0;
+ if (advance_parm) {
+ p = getParm(p);
+ if (p) {
+ p = nextParm(p);
+ }
+ ++pn;
+ }
+ while (pn < num_required) {
+ p = getParm(p);
+
+ if (need_comma) {
+ Printv(start, ", ", NULL);
+ }
+
+ SwigType *tm = goType(p, Getattr(p, "type"));
+ Printf(start, "a[%d].(%s)", pn, tm);
+ Delete(tm);
+
+ need_comma = true;
+ ++pn;
+ p = nextParm(p);
+ }
+
+ String *end = NULL;
+ if (!result || SwigType_type(result) == T_VOID || (all_result && SwigType_type(all_result) == T_VOID)) {
+ end = NewString("");
+ Printv(end, "return", NULL);
+ if (!all_result || SwigType_type(all_result) != T_VOID) {
+ Printv(end, " 0", NULL);
+ }
+ }
+
+ if (num_required == num_arguments) {
+ Printv(f_go_wrappers, "\t\t", start, ")\n", NULL);
+ if (end) {
+ Printv(f_go_wrappers, "\t\t", end, "\n", NULL);
+ }
+ } else {
+ Printv(f_go_wrappers, "\t\tswitch argc {\n", NULL);
+ for (int j = num_required; j <= num_arguments; ++j) {
+ Printf(f_go_wrappers, "\t\tcase %d:\n", j);
+ Printv(f_go_wrappers, "\t\t\t", start, NULL);
+ bool nc = need_comma;
+ for (int k = num_required; k < j; ++k) {
+ if (nc) {
+ Printv(f_go_wrappers, ", ", NULL);
+ }
+ Printf(f_go_wrappers, "a[%d]", k);
+ nc = true;
+ }
+ Printv(f_go_wrappers, ")\n", NULL);
+ if (end) {
+ Printv(f_go_wrappers, "\t\t\t", end, "\n", NULL);
+ }
+ }
+ Printv(f_go_wrappers, "\t\t}\n", NULL);
+ }
+
+ Printv(f_go_wrappers, "\t}\n", NULL);
+
+ if (fn != 0) {
+ Printf(f_go_wrappers, "check_%d:\n", fn);
+ }
+
+ Delete(coll);
+ }
+
+ Printv(f_go_wrappers, "\tpanic(\"No match for overloaded function call\")\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
+
+ Delete(all_result);
+ Delete(dispatch);
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkFunctionVisibility()
+ *
+ * Return true if we should write out a function based on its
+ * visibility, false otherwise.
+ * ---------------------------------------------------------------------- */
+
+ bool checkFunctionVisibility(Node *n, Node *parent) {
+ // Write out a public function.
+ if (is_public(n))
+ return true;
+ // Don't write out a private function.
+ if (is_private(n))
+ return false;
+ // Write a protected function for a director class in
+ // dirprot_mode.
+ if (parent == NULL) {
+ return false;
+ }
+ if (dirprot_mode() && Swig_directorclass(parent))
+ return true;
+ // Otherwise don't write out a protected function.
+ return false;
+ }
+
+
+ /* ----------------------------------------------------------------------
+ * exportedName()
+ *
+ * Given a C/C++ name, return a name in Go which will be exported.
+ * If the first character is an upper case letter, this returns a
+ * copy of its argument. If the first character is a lower case
+ * letter, this forces it to upper case. Otherwise, this prepends
+ * 'X'.
+ * ---------------------------------------------------------------------- */
+
+ String *exportedName(SwigType *name) {
+ SwigType *copy = Copy(name);
+ char c = *Char(copy);
+ if (islower(c)) {
+ char l[2];
+ char u[2];
+ l[0] = c;
+ l[1] = '\0';
+ u[0] = toupper(c);
+ u[1] = '\0';
+ Replace(copy, l, u, DOH_REPLACE_FIRST);
+ } else if (!isalpha(c)) {
+ char l[2];
+ char u[3];
+ l[0] = c;
+ l[1] = '\0';
+ u[0] = 'X';
+ u[1] = c;
+ u[2] = '\0';
+ Replace(copy, l, u, DOH_REPLACE_FIRST);
+ }
+ String *ret = Swig_name_mangle_type(copy);
+ Delete(copy);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * removeClassname()
+ *
+ * If the name starts with the current class name, followed by an
+ * underscore, remove it. If there is no current class name, this
+ * simply returns a copy of the name. This undoes Swig's way of
+ * recording the class name in a member name.
+ * ---------------------------------------------------------------------- */
+
+ String *removeClassname(String *name) {
+ String *copy = Copy(name);
+ if (class_name) {
+ char *p = Char(name);
+ if (Strncmp(name, class_name, Len(class_name)) == 0 && p[Len(class_name)] == '_') {
+ Replace(copy, class_name, "", DOH_REPLACE_FIRST);
+ Replace(copy, "_", "", DOH_REPLACE_FIRST);
+ }
+ }
+ return copy;
+ }
+
+ /* ----------------------------------------------------------------------
+ * buildGoName()
+ *
+ * Build the name to use for an ordinary function, variable, or
+ * whatever in Go. The name argument is something like the sym:name
+ * attribute of the node. If is_static is false, this could be a
+ * method, and the returned name will be the name of the
+ * method--i.e., it will not include the class name.
+ * ---------------------------------------------------------------------- */
+
+ String *buildGoName(String *name, bool is_static, bool is_friend) {
+ String *nw = NewString("");
+ if (is_static && !is_friend && class_name) {
+ String *c1 = exportedName(class_name);
+ Append(nw, c1);
+ Delete(c1);
+ }
+ String *c2 = removeClassname(name);
+ String *c3 = exportedName(c2);
+ Append(nw, c3);
+ Delete(c2);
+ Delete(c3);
+ String *ret = Swig_name_mangle_string(nw);
+ Delete(nw);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * buildGoWrapperName()
+ *
+ * Build the name to use for a Go wrapper function. This is a
+ * function called by the real Go function in order to convert C++
+ * classes from interfaces to pointers, and other such conversions
+ * between the Go type and the C++ type.
+ * ---------------------------------------------------------------------- */
+
+ String *buildGoWrapperName(String *name, String *overname) {
+ String *s1 = NewString("_swig_wrap_");
+ Append(s1, name);
+ String *s2 = Swig_name_mangle_string(s1);
+ Delete(s1);
+ if (overname) {
+ Append(s2, overname);
+ }
+ return s2;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkNameConflict()
+ *
+ * Check for a name conflict on the name we are going to use in Go.
+ * These conflicts are likely because of the enforced
+ * capitalization. When we find one, issue a warning and return
+ * false. If the name is OK, return true.
+ * ---------------------------------------------------------------------- */
+
+ bool checkNameConflict(String* name, Node* n, const_String_or_char_ptr scope) {
+ Node *lk = symbolLookup(name, scope);
+ if (lk) {
+ String *n1 = Getattr(n, "sym:name");
+ if (!n1) {
+ n1 = Getattr(n, "name");
+ }
+ String *n2 = Getattr(lk, "sym:name");
+ if (!n2) {
+ n2 = Getattr(lk, "name");
+ }
+ Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
+ "Ignoring '%s' due to Go name ('%s') conflict with '%s'\n",
+ n1, name, n2);
+ return false;
+ }
+ bool r = addSymbol(name, n, scope) ? true : false;
+ assert(r);
+ (void)r;
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkIgnoredParameters()
+ *
+ * If any of the parameters of this function, or the return type,
+ * are ignored due to a name conflict, give a warning and return
+ * false.
+ * ---------------------------------------------------------------------- */
+
+ bool checkIgnoredParameters(Node *n, String *go_name) {
+ ParmList *parms = Getattr(n, "parms");
+ if (parms) {
+ Wrapper *dummy = NewWrapper();
+ emit_attach_parmmaps(parms, dummy);
+ int parm_count = emit_num_arguments(parms);
+ Parm *p = parms;
+
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (!checkIgnoredType(n, go_name, Getattr(p, "type"))) {
+ DelWrapper(dummy);
+ return false;
+ }
+ p = nextParm(p);
+ }
+
+ DelWrapper(dummy);
+ }
+
+ if (!checkIgnoredType(n, go_name, Getattr(n, "type"))) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /* ----------------------------------------------------------------------
+ * checkIgnoredType()
+ *
+ * If this type is being ignored due to a name conflict, give a
+ * warning and return false.
+ * ---------------------------------------------------------------------- */
+
+ bool checkIgnoredType(Node *n, String *go_name, SwigType *type) {
+ if (hasGoTypemap(n, type)) {
+ return true;
+ }
+
+ SwigType *t = SwigType_typedef_resolve_all(type);
+
+ bool ret = true;
+ bool is_conflict = false;
+ Node *e = Language::enumLookup(t);
+ if (e) {
+ if (GetFlag(e, "go:conflict")) {
+ is_conflict = true;
+ }
+ } else if (SwigType_issimple(t)) {
+ Node *cn = classLookup(t);
+ if (cn) {
+ if (GetFlag(cn, "go:conflict")) {
+ is_conflict = true;
+ }
+ }
+ } else if (SwigType_ispointer(t) || SwigType_isarray(t) || SwigType_isqualifier(t) || SwigType_isreference(t)) {
+ SwigType *r = Copy(t);
+ if (SwigType_ispointer(r)) {
+ SwigType_del_pointer(r);
+ } else if (SwigType_isarray(r)) {
+ SwigType_del_array(r);
+ } else if (SwigType_isqualifier(r)) {
+ SwigType_del_qualifier(r);
+ } else {
+ SwigType_del_reference(r);
+ }
+
+ if (!checkIgnoredType(n, go_name, r)) {
+ ret = false;
+ }
+
+ Delete(r);
+ }
+
+ if (is_conflict) {
+ String *s = SwigType_str(t, NULL);
+ Swig_warning(WARN_GO_NAME_CONFLICT, input_file, line_number,
+ "Ignoring '%s' (Go name '%s') due to Go name conflict for parameter or result type '%s'\n",
+ Getattr(n, "name"), go_name, s);
+ Delete(s);
+ ret = false;
+ }
+
+ Delete(t);
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goType()
+ *
+ * Given a SWIG type, return a string for the type in Go.
+ * ---------------------------------------------------------------------- */
+
+ String *goType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, false, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goImType()
+ *
+ * Given a SWIG type, return a string for the intermediate Go type
+ * to pass to C/C++. This is like goType except that it looks for
+ * an imtype typemap entry first.
+ * ---------------------------------------------------------------------- */
+
+ String *goImType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, true, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypeWithInfo()
+ *
+ * Like goType, but return some more information.
+ *
+ * If use_imtype is true, this look for a imtype typemap entry.
+ *
+ * If the p_is_interface parameter is not NULL, this sets
+ * *p_is_interface to indicate whether this type is going to be
+ * represented by a Go interface type. These are cases where the Go
+ * code needs to make some adjustments when passing values back and
+ * forth with C/C++.
+ * ---------------------------------------------------------------------- */
+
+ String *goTypeWithInfo(Node *n, SwigType *type, bool use_imtype, bool *p_is_interface) {
+ if (p_is_interface) {
+ *p_is_interface = false;
+ }
+
+ String *ret = NULL;
+ if (use_imtype) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:imtype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("imtype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goImType", n);
+ ret = Swig_typemap_lookup("imtype", p, "", NULL);
+ Delete(p);
+ }
+ }
+ if (!ret) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:gotype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("gotype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goType", n);
+ ret = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
+ }
+ }
+
+ if (ret && Strstr(ret, "$gotypename") != 0) {
+ ret = NULL;
+ }
+
+ if (ret) {
+ return Copy(ret);
+ }
+
+ SwigType *t = SwigType_typedef_resolve_all(type);
+
+ if (SwigType_isenum(t)) {
+ Node *e = Language::enumLookup(t);
+ if (e) {
+ ret = goEnumName(e);
+ } else if (Strcmp(t, "enum ") == 0) {
+ ret = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ String *tt = Copy(t);
+ Replace(tt, "enum ", "", DOH_REPLACE_ANY);
+ ret = exportedName(tt);
+ Setattr(undefined_enum_types, t, ret);
+ Delete(tt);
+ }
+ } else if (SwigType_isfunctionpointer(t) || SwigType_isfunction(t)) {
+ ret = NewString("_swig_fnptr");
+ } else if (SwigType_ismemberpointer(t)) {
+ ret = NewString("_swig_memberptr");
+ } else if (SwigType_issimple(t)) {
+ Node *cn = classLookup(t);
+ if (cn) {
+ ret = Getattr(cn, "sym:name");
+ if (!ret) {
+ ret = Getattr(cn, "name");
+ }
+ ret = exportedName(ret);
+
+ Node *cnmod = Getattr(cn, "module");
+ if (!cnmod || Strcmp(Getattr(cnmod, "name"), module) == 0) {
+ Setattr(undefined_types, t, t);
+ } else {
+ String *nw = NewString("");
+ Printv(nw, getModuleName(Getattr(cnmod, "name")), ".", ret, NULL);
+ Delete(ret);
+ ret = nw;
+ }
+ } else {
+ // SWIG does not know about this type.
+ ret = exportedName(t);
+ Setattr(undefined_types, t, t);
+ }
+ if (p_is_interface) {
+ *p_is_interface = true;
+ }
+ } else if (SwigType_ispointer(t) || SwigType_isarray(t)) {
+ SwigType *r = Copy(t);
+ if (SwigType_ispointer(r)) {
+ SwigType_del_pointer(r);
+ } else {
+ SwigType_del_array(r);
+ }
+
+ if (SwigType_type(r) == T_VOID) {
+ ret = NewString("uintptr");
+ } else {
+ bool is_interface;
+ String *base = goTypeWithInfo(n, r, false, &is_interface);
+
+ // At the Go level, an unknown or class type is handled as an
+ // interface wrapping a pointer. This means that if a
+ // function returns the C type X, we will be wrapping the C
+ // type X*. In Go we will call that type X. That means that
+ // if a C function expects X*, we can pass the Go type X. And
+ // that means that when we see the C type X*, we should use
+ // the Go type X.
+
+ // The is_interface variable tells us this. However, it will
+ // be true both for the case of X and for the case of X*. If
+ // r is a pointer here, then we are looking at X**. There is
+ // really no good way for us to handle that.
+ bool is_pointer_to_pointer = false;
+ if (is_interface) {
+ SwigType *c = Copy(r);
+ if (SwigType_isqualifier(c)) {
+ SwigType_del_qualifier(c);
+ if (SwigType_ispointer(c) || SwigType_isarray(c)) {
+ is_pointer_to_pointer = true;
+ }
+ }
+ Delete(c);
+ }
+
+ if (is_interface) {
+ if (!is_pointer_to_pointer) {
+ ret = base;
+ if (p_is_interface) {
+ *p_is_interface = true;
+ }
+ } else {
+ ret = NewString("uintptr");
+ }
+ } else {
+ ret = NewString("*");
+ Append(ret, base);
+ Delete(base);
+ }
+ }
+
+ Delete(r);
+ } else if (SwigType_isreference(t)) {
+ SwigType *r = Copy(t);
+ SwigType_del_reference(r);
+
+ // If this is a const reference, and we are looking at a pointer
+ // to it, then we just use the pointer we already have.
+ bool add_pointer = true;
+ if (SwigType_isqualifier(r)) {
+ String *q = SwigType_parm(r);
+ if (Strcmp(q, "const") == 0) {
+ SwigType *c = Copy(r);
+ SwigType_del_qualifier(c);
+ if (SwigType_ispointer(c)) {
+ add_pointer = false;
+ }
+ Delete(c);
+ }
+ }
+ if (add_pointer) {
+ SwigType_add_pointer(r);
+ }
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
+ Delete(r);
+ } else if (SwigType_isqualifier(t)) {
+ SwigType *r = Copy(t);
+ SwigType_del_qualifier(r);
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
+ Delete(r);
+ } else if (SwigType_isvarargs(t)) {
+ ret = NewString("[]interface{}");
+ }
+
+ Delete(t);
+
+ if (!ret) {
+ Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "No Go typemap defined for %s\n", SwigType_str(type, 0));
+ ret = NewString("uintptr");
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * cgoTypeForGoValue()
+ *
+ * Given a SWIG type, return a string for the C type to use for the
+ * cgo wrapper code. This always returns a simple identifier, since
+ * it is used in Go code as C.name.
+ *
+ * This sets *c_struct_type if the C type uses a struct where the Go
+ * type uses a simple type. This is true for strings and slices.
+ * When this is true the Go code has to jump through unsafe hoops to
+ * pass the type checker.
+ * ---------------------------------------------------------------------- */
+
+ String *cgoTypeForGoValue(Node *n, SwigType *type, bool *c_struct_type) {
+ *c_struct_type = false;
+
+ bool is_interface;
+ String *go_type = goTypeWithInfo(n, type, true, &is_interface);
+ if (is_interface) {
+ Delete(go_type);
+ return NewString("uintptr_t");
+ }
+ if (Strcmp(go_type, "uintptr") == 0) {
+ Delete(go_type);
+ return NewString("uintptr_t");
+ }
+ if (((char*)Char(go_type))[0] == '*') {
+ // Treat all pointers as void*. There is no meaningful type
+ // checking going on here anyhow, and that lets us avoid
+ // worrying about defining the base type of the pointer.
+ Delete(go_type);
+ return NewString("swig_voidp");
+ }
+
+ // Check for some Go types that are really pointers under the covers.
+ bool is_hidden_pointer = Strncmp(go_type, "func(", 5) == 0 || Strncmp(go_type, "map[", 4) == 0 || Strncmp(go_type, "chan ", 5) == 0;
+
+ Delete(go_type);
+
+ String *ct = Getattr(n, "emit:cgotype");
+ if (ct) {
+ *c_struct_type = Getattr(n, "emit:cgotypestruct") ? true : false;
+ return Copy(ct);
+ }
+
+ String *t = Copy(type);
+ if (SwigType_isarray(t) && Getattr(n, "tmap:gotype") == NULL) {
+ SwigType_del_array(t);
+ SwigType_add_pointer(t);
+ }
+
+ bool add_typedef = true;
+
+ static int count;
+ ++count;
+ ct = NewStringf("swig_type_%d", count);
+
+ String *gct = gcCTypeForGoValue(n, t, ct);
+ Delete(t);
+
+ if (Strncmp(gct, "_gostring_", 10) == 0 || Strncmp(gct, "_goslice_", 9) == 0) {
+ *c_struct_type = true;
+ Setattr(n, "emit:cgotypestruct", type);
+ } else {
+ char *p = Strstr(gct, ct);
+ if (p != NULL && p > (char*)Char(gct) && p[-1] == '*' && p[Len(ct)] == '\0') {
+ // Treat all pointers as void*. See above.
+ Delete(ct);
+ --count;
+ ct = NewString("swig_voidp");
+ add_typedef = false;
+ if (is_hidden_pointer) {
+ // A Go type that is really a pointer, like func, map, chan,
+ // is being represented in C by a pointer. This is fine,
+ // but we have to memcpy the type rather than simply
+ // converting it.
+ *c_struct_type = true;
+ Setattr(n, "emit:cgotypestruct", type);
+ }
+ }
+
+ if (Strncmp(gct, "bool ", 5) == 0) {
+ // Change the C++ type bool to the C type _Bool.
+ Replace(gct, "bool", "_Bool", DOH_REPLACE_FIRST);
+ }
+ if (Strncmp(gct, "intgo ", 6) == 0) {
+ // We #define intgo to swig_intgo for the cgo comment.
+ Replace(gct, "intgo", "swig_intgo", DOH_REPLACE_FIRST);
+ }
+ p = Strstr(gct, ct);
+ if (p != NULL && p > (char*)Char(gct) && p[-1] == ' ' && p[Len(ct)] == '\0') {
+ String *q = NewStringWithSize(gct, Len(gct) - Len(ct) - 1);
+ if (validIdentifier(q)) {
+ // This is a simple type name, and we can use it directly.
+ Delete(ct);
+ --count;
+ ct = q;
+ add_typedef = false;
+ }
+ }
+ }
+ if (add_typedef) {
+ Printv(f_cgo_comment_typedefs, "typedef ", gct, ";\n", NULL);
+ }
+
+ Setattr(n, "emit:cgotype", ct);
+
+ Delete(gct);
+
+ return Copy(ct);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goWrapperType()
+ *
+ * Given a type, return a string for the type to use for the wrapped
+ * Go function. This function exists because for a C++ class we
+ * need to convert interface and reference types.
+ * ---------------------------------------------------------------------- */
+
+ String *goWrapperType(Node *n, SwigType *type, bool is_result) {
+ bool is_interface;
+ String *ret = goTypeWithInfo(n, type, true, &is_interface);
+
+ // If this is an interface, we want to pass the real type.
+ if (is_interface) {
+ Delete(ret);
+ if (!is_result) {
+ ret = NewString("uintptr");
+ } else {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ while (true) {
+ if (SwigType_ispointer(ty)) {
+ SwigType_del_pointer(ty);
+ } else if (SwigType_isarray(ty)) {
+ SwigType_del_array(ty);
+ } else if (SwigType_isreference(ty)) {
+ SwigType_del_reference(ty);
+ } else if (SwigType_isqualifier(ty)) {
+ SwigType_del_qualifier(ty);
+ } else {
+ break;
+ }
+ }
+ assert(SwigType_issimple(ty));
+ String *p = goCPointerType(ty, true);
+ Delete(ty);
+ ret = p;
+ }
+ }
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goOverloadType()
+ *
+ * Given a type, return the Go type to use when dispatching of
+ * overloaded functions. This is normally just the usual Go type.
+ * However, for a C++ class, the usual Go type is an interface type.
+ * And if that interface type represents a C++ type that SWIG does
+ * not know about, then the interface type generated for any C++
+ * class will match that interface. So for that case, we match on
+ * the underlying integer type.
+ *
+ * It has to work this way so that we can handle a derived type of a
+ * %ignore'd type. It's unlikely that anybody will have a value of
+ * an undefined type, but we support it because it worked in the
+ * past.
+ * ---------------------------------------------------------------------- */
+
+ String *goOverloadType(Node *n, SwigType *type) {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ while (true) {
+ if (SwigType_ispointer(ty)) {
+ SwigType_del_pointer(ty);
+ } else if (SwigType_isarray(ty)) {
+ SwigType_del_array(ty);
+ } else if (SwigType_isreference(ty)) {
+ SwigType_del_reference(ty);
+ } else if (SwigType_isqualifier(ty)) {
+ SwigType_del_qualifier(ty);
+ } else {
+ break;
+ }
+ }
+
+ String* go_type = goType(n, ty);
+
+ if (Getattr(undefined_types, ty) && !Getattr(defined_types, go_type)) {
+ Delete(go_type);
+ return goWrapperType(n, type, true);
+ }
+
+ Delete(go_type);
+ return goType(n, type);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goCPointerType()
+ *
+ * Return the name of the Go type to use for the C pointer value.
+ * The regular C type is the name of an interface type which wraps a
+ * pointer whose name is returned by this function.
+ * ---------------------------------------------------------------------- */
+
+ String *goCPointerType(SwigType *type, bool add_to_hash) {
+ SwigType *ty = SwigType_typedef_resolve_all(type);
+ Node *cn = classLookup(ty);
+ String *ex;
+ String *ret;
+ if (!cn) {
+ if (add_to_hash) {
+ Setattr(undefined_types, ty, ty);
+ }
+ ret = NewString("Swigcptr");
+ ex = exportedName(ty);
+ Append(ret, ex);
+ } else {
+ String *cname = Getattr(cn, "sym:name");
+ if (!cname) {
+ cname = Getattr(cn, "name");
+ }
+ ex = exportedName(cname);
+ Node *cnmod = Getattr(cn, "module");
+ if (!cnmod || Strcmp(Getattr(cnmod, "name"), module) == 0) {
+ if (add_to_hash) {
+ Setattr(undefined_types, ty, ty);
+ }
+ ret = NewString("Swigcptr");
+ Append(ret, ex);
+ } else {
+ ret = NewString("");
+ Printv(ret, getModuleName(Getattr(cnmod, "name")), ".Swigcptr", ex, NULL);
+ }
+ }
+ Delete(ty);
+ Delete(ex);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * gcCTypeForGoValue()
+ *
+ * Given a type, return the C/C++ type which will be used to catch
+ * the value in Go. This is the gc version.
+ * ---------------------------------------------------------------------- */
+
+ String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) {
+ bool is_interface;
+ String *gt = goTypeWithInfo(n, type, true, &is_interface);
+
+ String *tail = NewString("");
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ bool is_const_ref = false;
+ if (SwigType_isreference(t)) {
+ SwigType* tt = Copy(t);
+ SwigType_del_reference(tt);
+ if (SwigType_isqualifier(tt)) {
+ String* q = SwigType_parm(tt);
+ if (Strcmp(q, "const") == 0) {
+ is_const_ref = true;
+ }
+ }
+ Delete(tt);
+ }
+ if (!is_const_ref) {
+ while (Strncmp(gt, "*", 1) == 0) {
+ Replace(gt, "*", "", DOH_REPLACE_FIRST);
+ Printv(tail, "*", NULL);
+ }
+ }
+ Delete(t);
+
+ bool is_string = Strcmp(gt, "string") == 0;
+ bool is_slice = Strncmp(gt, "[]", 2) == 0;
+ bool is_function = Strcmp(gt, "_swig_fnptr") == 0;
+ bool is_member = Strcmp(gt, "_swig_memberptr") == 0;
+ bool is_complex64 = Strcmp(gt, "complex64") == 0;
+ bool is_complex128 = Strcmp(gt, "complex128") == 0;
+ bool is_bool = false;
+ bool is_int8 = false;
+ bool is_int16 = false;
+ bool is_int = Strcmp(gt, "int") == 0 || Strcmp(gt, "uint") == 0;
+ bool is_int32 = false;
+ bool is_int64 = false;
+ bool is_float32 = false;
+ bool is_float64 = false;
+
+ bool has_typemap = (n != NULL && Getattr(n, "tmap:gotype") != NULL) || hasGoTypemap(n, type);
+ if (has_typemap) {
+ is_bool = Strcmp(gt, "bool") == 0;
+ is_int8 = Strcmp(gt, "int8") == 0 || Strcmp(gt, "uint8") == 0 || Strcmp(gt, "byte") == 0;
+ is_int16 = Strcmp(gt, "int16") == 0 || Strcmp(gt, "uint16") == 0;
+ is_int32 = Strcmp(gt, "int32") == 0 || Strcmp(gt, "uint32") == 0;
+ is_int64 = Strcmp(gt, "int64") == 0 || Strcmp(gt, "uint64") == 0;
+ is_float32 = Strcmp(gt, "float32") == 0;
+ is_float64 = Strcmp(gt, "float64") == 0;
+ }
+ Delete(gt);
+
+ String *ret;
+ if (is_string) {
+ // Note that we don't turn a reference to a string into a
+ // pointer to a string. Strings are immutable anyhow.
+ ret = NewString("");
+ Printv(ret, "_gostring_", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_slice) {
+ // Slices are always passed as a _goslice_, whether or not references
+ // are involved.
+ ret = NewString("");
+ Printv(ret, "_goslice_", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_function || is_member) {
+ ret = NewString("");
+ Printv(ret, "void*", tail, " ", name, NULL);
+ Delete(tail);
+ return ret;
+ } else if (is_complex64) {
+ ret = NewString("_Complex float ");
+ } else if (is_complex128) {
+ ret = NewString("_Complex double ");
+ } else if (is_interface) {
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (SwigType_ispointer(t)) {
+ SwigType_del_pointer(t);
+ }
+ if (SwigType_isreference(t)) {
+ SwigType_del_reference(t);
+ }
+ SwigType_add_pointer(t);
+ ret = SwigType_lstr(t, name);
+ Delete(t);
+ Delete(tail);
+ return ret;
+ } else {
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (!has_typemap && SwigType_isreference(t)) {
+ // A const reference to a known type, or to a pointer, is not
+ // mapped to a pointer.
+ SwigType_del_reference(t);
+ if (SwigType_isqualifier(t)) {
+ String *q = SwigType_parm(t);
+ if (Strcmp(q, "const") == 0) {
+ SwigType_del_qualifier(t);
+ if (hasGoTypemap(n, t) || SwigType_ispointer(t)) {
+ if (is_int) {
+ ret = NewString("intgo ");
+ Append(ret, name);
+ } else if (is_int64) {
+ ret = NewString("long long ");
+ Append(ret, name);
+ } else {
+ ret = SwigType_lstr(t, name);
+ }
+ Delete(q);
+ Delete(t);
+ Delete(tail);
+ return ret;
+ }
+ }
+ Delete(q);
+ }
+ }
+
+ if (Language::enumLookup(t) != NULL) {
+ is_int = true;
+ } else {
+ SwigType *tstripped = SwigType_strip_qualifiers(t);
+ if (SwigType_isenum(tstripped))
+ is_int = true;
+ Delete(tstripped);
+ }
+
+ Delete(t);
+ if (is_bool) {
+ ret = NewString("bool ");
+ } else if (is_int8) {
+ ret = NewString("char ");
+ } else if (is_int16) {
+ ret = NewString("short ");
+ } else if (is_int) {
+ ret = NewString("intgo ");
+ } else if (is_int32) {
+ ret = NewString("int ");
+ } else if (is_int64) {
+ ret = NewString("long long ");
+ } else if (is_float32) {
+ ret = NewString("float ");
+ } else if (is_float64) {
+ ret = NewString("double ");
+ } else {
+ Delete(tail);
+ return SwigType_lstr(type, name);
+ }
+ }
+
+ Append(ret, tail);
+ if (!has_typemap && SwigType_isreference(type)) {
+ Append(ret, "* ");
+ }
+ Append(ret, name);
+ Delete(tail);
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypeIsInterface
+ *
+ * Return whether this C++ type is represented as an interface type
+ * in Go. These types require adjustments in the Go code when
+ * passing them back and forth between Go and C++.
+ * ---------------------------------------------------------------------- */
+
+ bool goTypeIsInterface(Node *n, SwigType *type) {
+ bool is_interface;
+ Delete(goTypeWithInfo(n, type, false, &is_interface));
+ return is_interface;
+ }
+
+ /* ----------------------------------------------------------------------
+ * hasGoTypemap
+ *
+ * Return whether a type has a "gotype" typemap entry.
+ * ---------------------------------------------------------------------- */
+
+ bool hasGoTypemap(Node *n, SwigType *type) {
+ Parm *p = NewParm(type, "test", n);
+ SwigType *tm = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
+ if (tm && Strstr(tm, "$gotypename") == 0) {
+ Delete(tm);
+ return true;
+ }
+ Delete(tm);
+ return false;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goEnumName()
+ *
+ * Given an enum node, return a string to use for the enum type in Go.
+ * ---------------------------------------------------------------------- */
+
+ String *goEnumName(Node *n) {
+ String *ret = Getattr(n, "go:enumname");
+ if (ret) {
+ return Copy(ret);
+ }
+
+ if (Equal(Getattr(n, "type"), "enum ")) {
+ return NewString("int");
+ }
+
+ SwigType *type = Getattr(n, "enumtype");
+ assert(type);
+ char *p = Char(type);
+ int len = Len(type);
+ SwigType *s = NewString("");
+ bool capitalize = true;
+ for (int i = 0; i < len; ++i, ++p) {
+ if (*p == ':') {
+ ++i;
+ ++p;
+ assert(*p == ':');
+ capitalize = true;
+ } else if (capitalize) {
+ Putc(toupper(*p), s);
+ capitalize = false;
+ } else {
+ Putc(*p, s);
+ }
+ }
+
+ ret = Swig_name_mangle_type(s);
+ Delete(s);
+ return ret;
+ }
+
+
+ /* ----------------------------------------------------------------------
+ * getParm()
+ *
+ * Get the real parameter to use.
+ * ---------------------------------------------------------------------- */
+
+ Parm *getParm(Parm *p) {
+ while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ return p;
+ }
+
+ /* ----------------------------------------------------------------------
+ * nextParm()
+ *
+ * Return the next parameter.
+ * ---------------------------------------------------------------------- */
+
+ Parm *nextParm(Parm *p) {
+ if (!p) {
+ return NULL;
+ } else if (Getattr(p, "tmap:in")) {
+ return Getattr(p, "tmap:in:next");
+ } else {
+ return nextSibling(p);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * isStatic
+ *
+ * Return whether a node should be considered as static rather than
+ * as a member.
+ * ---------------------------------------------------------------------- */
+
+ bool isStatic(Node *n) {
+ String *storage = Getattr(n, "storage");
+ return (storage && (Swig_storage_isstatic(n) || Strstr(storage, "friend")) && (!SmartPointer || !Getattr(n, "allocate:smartpointeraccess")));
+ }
+
+ /* ----------------------------------------------------------------------
+ * isFriend
+ *
+ * Return whether a node is a friend.
+ * ---------------------------------------------------------------------- */
+
+ bool isFriend(Node *n) {
+ String *storage = Getattr(n, "storage");
+ return storage && Strstr(storage, "friend");
+ }
+
+ /* ----------------------------------------------------------------------
+ * goGetattr
+ *
+ * Fetch an attribute from a node but return NULL if it is the empty string.
+ * ---------------------------------------------------------------------- */
+ Node *goGetattr(Node *n, const char *name) {
+ Node *ret = Getattr(n, name);
+ if (ret != NULL && Len(ret) == 0) {
+ ret = NULL;
+ }
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * goTypemapLookup
+ *
+ * Look up a typemap but return NULL if it is the empty string.
+ * ---------------------------------------------------------------------- */
+ String *goTypemapLookup(const char *name, Node *node, const char *lname) {
+ String *ret = Swig_typemap_lookup(name, node, lname, NULL);
+ if (ret != NULL && Len(ret) == 0) {
+ ret = NULL;
+ }
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+ * getModuleName
+ *
+ * Return the name of a module. This is different from module path:
+ * "some/path/to/module" -> "module".
+ * ---------------------------------------------------------------------- */
+
+ String *getModuleName(String *module_path) {
+ char *suffix = strrchr(Char(module_path), '/');
+ if (suffix == NULL) {
+ return module_path;
+ }
+ return Str(suffix + 1);
+ }
+
+}; /* class GO */
+
+/* -----------------------------------------------------------------------------
+ * swig_go() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_go() {
+ return new GO();
+}
+extern "C" Language *swig_go(void) {
+ return new_swig_go();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+// Usage message.
+const char * const GO::usage = "\
+Go Options (available with -go)\n\
+ -cgo - Generate cgo input files\n\
+ -no-cgo - Do not generate cgo input files\n\
+ -gccgo - Generate code for gccgo rather than gc\n\
+ -go-pkgpath <p> - Like gccgo -fgo-pkgpath option\n\
+ -go-prefix <p> - Like gccgo -fgo-prefix option\n\
+ -import-prefix <p> - Prefix to add to %import directives\n\
+ -intgosize <s> - Set size of Go int type--32 or 64 bits\n\
+ -package <name> - Set name of the Go package to <name>\n\
+ -use-shlib - Force use of a shared library\n\
+ -soname <name> - Set shared library holding C/C++ code to <name>\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/guile.cxx b/contrib/tools/swig/Source/Modules/guile.cxx
new file mode 100644
index 00000000000..403949df133
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/guile.cxx
@@ -0,0 +1,1642 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * guile.cxx
+ *
+ * Guile language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <ctype.h>
+
+// Note string broken in half for compilers that can't handle long strings
+static const char *usage = "\
+Guile Options (available with -guile)\n\
+ -emitsetters - Emit procedures-with-setters for variables\n\
+ and structure slots.\n\
+ -emitslotaccessors - Emit accessor methods for all GOOPS slots\n" "\
+ -exportprimitive - Add the (export ...) code from scmstub into the\n\
+ GOOPS file.\n\
+ -goopsprefix <prefix> - Prepend <prefix> to all goops identifiers\n\
+ -Linkage <lstyle> - Use linkage protocol <lstyle> (default `simple')\n\
+ Use `module' for native Guile module linking\n\
+ (requires Guile >= 1.5.0). Use `passive' for\n\
+ passive linking (no C-level module-handling code),\n\
+ or `hobbit' for hobbit modules.\n\
+ -onlysetters - Don't emit traditional getter and setter\n\
+ procedures for structure slots,\n\
+ only emit procedures-with-setters.\n\
+ -package <name> - Set the path of the module to <name>\n\
+ (default NULL)\n\
+ -prefix <name> - Use <name> as prefix [default \"gswig_\"]\n\
+ -procdoc <file> - Output procedure documentation to <file>\n\
+ -procdocformat <format> - Output procedure documentation in <format>;\n\
+ one of `guile-1.4', `plain', `texinfo'\n\
+ -proxy - Export GOOPS class definitions\n\
+ -primsuffix <suffix> - Name appended to primitive module when exporting\n\
+ GOOPS classes. (default = \"primitive\")\n\
+ -scmstub - Output Scheme file with module declaration and\n\
+ exports; only with `passive' and `simple' linkage\n\
+ -useclassprefix - Prepend the class name to all goops identifiers\n\
+\n";
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_init = 0;
+
+
+static String *prefix = NewString("gswig_");
+static char *module = 0;
+static String *package = 0;
+static enum {
+ GUILE_LSTYLE_SIMPLE, // call `SWIG_init()'
+ GUILE_LSTYLE_PASSIVE, // passive linking (no module code)
+ GUILE_LSTYLE_MODULE, // native guile module linking (Guile >= 1.4.1)
+ GUILE_LSTYLE_HOBBIT // use (hobbit4d link)
+} linkage = GUILE_LSTYLE_SIMPLE;
+
+static File *procdoc = 0;
+static bool scmstub = false;
+static String *scmtext;
+static bool goops = false;
+static String *goopstext;
+static String *goopscode;
+static String *goopsexport;
+
+static enum {
+ GUILE_1_4,
+ PLAIN,
+ TEXINFO
+} docformat = GUILE_1_4;
+
+static int emit_setters = 0;
+static int only_setters = 0;
+static int emit_slot_accessors = 0;
+static int struct_member = 0;
+
+static String *beforereturn = 0;
+static String *return_nothing_doc = 0;
+static String *return_one_doc = 0;
+static String *return_multi_doc = 0;
+
+static String *exported_symbols = 0;
+
+static int exporting_destructor = 0;
+static String *swigtype_ptr = 0;
+
+/* GOOPS stuff */
+static String *primsuffix = 0;
+static String *class_name = 0;
+static String *short_class_name = 0;
+static String *goops_class_methods;
+static int in_class = 0;
+static int have_constructor = 0;
+static int useclassprefix = 0; // -useclassprefix argument
+static String *goopsprefix = 0; // -goopsprefix argument
+static int primRenamer = 0; // if (use-modules ((...) :renamer ...) is exported to GOOPS file
+static int exportprimitive = 0; // -exportprimitive argument
+static String *memberfunction_name = 0;
+
+extern "C" {
+ static Node *has_classname(Node *class_node) {
+ return Getattr(class_node, "guile:goopsclassname") ? class_node : 0;
+ }
+}
+
+class GUILE:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i;
+
+ SWIG_library_directory("guile");
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-Linkage") == 0 || strcmp(argv[i], "-linkage") == 0) {
+ if (argv[i + 1]) {
+ if (0 == strcmp(argv[i + 1], "hobbit"))
+ linkage = GUILE_LSTYLE_HOBBIT;
+ else if (0 == strcmp(argv[i + 1], "simple"))
+ linkage = GUILE_LSTYLE_SIMPLE;
+ else if (0 == strcmp(argv[i + 1], "passive"))
+ linkage = GUILE_LSTYLE_PASSIVE;
+ else if (0 == strcmp(argv[i + 1], "module"))
+ linkage = GUILE_LSTYLE_MODULE;
+ else
+ Swig_arg_error();
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-procdoc") == 0) {
+ if (argv[i + 1]) {
+ procdoc = NewFile(argv[i + 1], "w", SWIG_output_files());
+ if (!procdoc) {
+ FileErrorDisplay(argv[i + 1]);
+ Exit(EXIT_FAILURE);
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-procdocformat") == 0) {
+ if (strcmp(argv[i + 1], "guile-1.4") == 0)
+ docformat = GUILE_1_4;
+ else if (strcmp(argv[i + 1], "plain") == 0)
+ docformat = PLAIN;
+ else if (strcmp(argv[i + 1], "texinfo") == 0)
+ docformat = TEXINFO;
+ else
+ Swig_arg_error();
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else if (strcmp(argv[i], "-emit-setters") == 0 || strcmp(argv[i], "-emitsetters") == 0) {
+ emit_setters = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-only-setters") == 0 || strcmp(argv[i], "-onlysetters") == 0) {
+ emit_setters = 1;
+ only_setters = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-emit-slot-accessors") == 0 || strcmp(argv[i], "-emitslotaccessors") == 0) {
+ emit_slot_accessors = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-scmstub") == 0) {
+ scmstub = true;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ goops = true;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-primsuffix") == 0) {
+ if (argv[i + 1]) {
+ primsuffix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-goopsprefix") == 0) {
+ if (argv[i + 1]) {
+ goopsprefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-useclassprefix") == 0) {
+ useclassprefix = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-exportprimitive") == 0) {
+ exportprimitive = 1;
+ // should use Swig_warning() here?
+ Swig_mark_arg(i);
+ }
+ }
+ }
+
+ // set default value for primsuffix
+ if (!primsuffix)
+ primsuffix = NewString("primitive");
+
+ //goops support can only be enabled if passive or module linkage is used
+ if (goops) {
+ if (linkage != GUILE_LSTYLE_PASSIVE && linkage != GUILE_LSTYLE_MODULE) {
+ Printf(stderr, "guile: GOOPS support requires passive or module linkage\n");
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ if (goops) {
+ // -proxy implies -emit-setters
+ emit_setters = 1;
+ }
+
+ if ((linkage == GUILE_LSTYLE_PASSIVE && scmstub) || linkage == GUILE_LSTYLE_MODULE)
+ primRenamer = 1;
+
+ if (exportprimitive && primRenamer) {
+ // should use Swig_warning() ?
+ Printf(stderr, "guile: Warning: -exportprimitive only makes sense with passive linkage without a scmstub.\n");
+ }
+
+ // Make sure `prefix' ends in an underscore
+ if (prefix) {
+ const char *px = Char(prefix);
+ if (px[Len(prefix) - 1] != '_')
+ Printf(prefix, "_");
+ }
+
+ /* Add a symbol for this module */
+ Preprocessor_define("SWIGGUILE 1", 0);
+ /* Read in default typemaps */
+ SWIG_config_file("guile_scm.swg");
+ allow_overloading();
+
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+
+ scmtext = NewString("");
+ Swig_register_filebyname("scheme", scmtext);
+ exported_symbols = NewString("");
+ goopstext = NewString("");
+ Swig_register_filebyname("goops", goopstext);
+ goopscode = NewString("");
+ goopsexport = NewString("");
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "GUILE");
+
+ /* Write out directives and declarations */
+
+ module = Swig_copy_string(Char(Getattr(n, "name")));
+
+ switch (linkage) {
+ case GUILE_LSTYLE_SIMPLE:
+ /* Simple linkage; we have to export the SWIG_init function. The user can
+ rename the function by a #define. */
+ Printf(f_runtime, "#define SWIG_GUILE_INIT_STATIC extern\n");
+ break;
+ default:
+ /* Other linkage; we make the SWIG_init function static */
+ Printf(f_runtime, "#define SWIG_GUILE_INIT_STATIC static\n");
+ break;
+ }
+
+ if (CPlusPlus) {
+ Printf(f_runtime, "extern \"C\" {\n\n");
+ }
+ Printf(f_runtime, "SWIG_GUILE_INIT_STATIC void\nSWIG_init (void);\n");
+ if (CPlusPlus) {
+ Printf(f_runtime, "\n}\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ Language::top(n);
+
+ /* Close module */
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printf(f_init, "}\n\n");
+ Printf(f_init, "#ifdef __cplusplus\n}\n#endif\n");
+
+ String *module_name = NewString("");
+
+ if (!module)
+ Printv(module_name, "swig", NIL);
+ else {
+ if (package)
+ Printf(module_name, "%s/%s", package, module);
+ else
+ Printv(module_name, module, NIL);
+ }
+ emit_linkage(module_name);
+
+ Delete(module_name);
+
+ if (procdoc) {
+ Delete(procdoc);
+ procdoc = NULL;
+ }
+ Delete(goopscode);
+ Delete(goopsexport);
+ Delete(goopstext);
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ void emit_linkage(String *module_name) {
+ String *module_func = NewString("");
+
+ if (CPlusPlus) {
+ Printf(f_init, "extern \"C\" {\n\n");
+ }
+
+ Printv(module_func, module_name, NIL);
+ Replaceall(module_func, "-", "_");
+
+ switch (linkage) {
+ case GUILE_LSTYLE_SIMPLE:
+ Printf(f_init, "\n/* Linkage: simple */\n");
+ break;
+ case GUILE_LSTYLE_PASSIVE:
+ Printf(f_init, "\n/* Linkage: passive */\n");
+ Replaceall(module_func, "/", "_");
+ Insert(module_func, 0, "scm_init_");
+ Append(module_func, "_module");
+
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ Printf(f_init, " SWIG_init();\n");
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Printf(f_init, "}\n");
+ break;
+ case GUILE_LSTYLE_MODULE:
+ Printf(f_init, "\n/* Linkage: module */\n");
+ Replaceall(module_func, "/", "_");
+ Insert(module_func, 0, "scm_init_");
+ Append(module_func, "_module");
+
+ Printf(f_init, "static void SWIG_init_helper(void *data)\n");
+ Printf(f_init, "{\n SWIG_init();\n");
+ if (Len(exported_symbols) > 0)
+ Printf(f_init, " scm_c_export(%sNULL);", exported_symbols);
+ Printf(f_init, "\n}\n\n");
+
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ {
+ String *mod = NewString(module_name);
+ if (goops)
+ Printv(mod, "-", primsuffix, NIL);
+ Replaceall(mod, "/", " ");
+ Printf(f_init, " scm_c_define_module(\"%s\",\n", mod);
+ Printf(f_init, " SWIG_init_helper, NULL);\n");
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Delete(mod);
+ }
+ Printf(f_init, "}\n");
+ break;
+ case GUILE_LSTYLE_HOBBIT:
+ Printf(f_init, "\n/* Linkage: hobbit */\n");
+ Replaceall(module_func, "/", "_slash_");
+ Insert(module_func, 0, "scm_init_");
+ Printf(f_init, "SCM\n%s (void)\n{\n", module_func);
+ {
+ String *mod = NewString(module_name);
+ Replaceall(mod, "/", " ");
+ Printf(f_init, " scm_register_module_xxx (\"%s\", (void *) SWIG_init);\n", mod);
+ Printf(f_init, " return SCM_UNSPECIFIED;\n");
+ Delete(mod);
+ }
+ Printf(f_init, "}\n");
+ break;
+ default:
+ fputs("Fatal internal error: Invalid Guile linkage setting.\n", stderr);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (scmstub) {
+ /* Emit Scheme stub if requested */
+ String *primitive_name = NewString(module_name);
+ if (goops)
+ Printv(primitive_name, "-", primsuffix, NIL);
+
+ String *mod = NewString(primitive_name);
+ Replaceall(mod, "/", " ");
+
+ String *fname = NewStringf("%s%s.scm",
+ SWIG_output_directory(),
+ primitive_name);
+ Delete(primitive_name);
+ File *scmstubfile = NewFile(fname, "w", SWIG_output_files());
+ if (!scmstubfile) {
+ FileErrorDisplay(fname);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(fname);
+
+ Swig_banner_target_lang(scmstubfile, ";;;");
+ Printf(scmstubfile, "\n");
+ if (linkage == GUILE_LSTYLE_SIMPLE || linkage == GUILE_LSTYLE_PASSIVE)
+ Printf(scmstubfile, "(define-module (%s))\n\n", mod);
+ Delete(mod);
+ Printf(scmstubfile, "%s", scmtext);
+ if ((linkage == GUILE_LSTYLE_SIMPLE || linkage == GUILE_LSTYLE_PASSIVE)
+ && Len(exported_symbols) > 0) {
+ String *ex = NewString(exported_symbols);
+ Replaceall(ex, ", ", "\n ");
+ Replaceall(ex, "\"", "");
+ Chop(ex);
+ Printf(scmstubfile, "\n(export %s)\n", ex);
+ Delete(ex);
+ }
+ Delete(scmstubfile);
+ }
+
+ if (goops) {
+ String *mod = NewString(module_name);
+ Replaceall(mod, "/", " ");
+
+ String *fname = NewStringf("%s%s.scm", SWIG_output_directory(),
+ module_name);
+ File *goopsfile = NewFile(fname, "w", SWIG_output_files());
+ if (!goopsfile) {
+ FileErrorDisplay(fname);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(fname);
+ Swig_banner_target_lang(goopsfile, ";;;");
+ Printf(goopsfile, "\n");
+ Printf(goopsfile, "(define-module (%s))\n", mod);
+ Printf(goopsfile, "%s\n", goopstext);
+ Printf(goopsfile, "(use-modules (oop goops) (Swig common))\n");
+ if (primRenamer) {
+ Printf(goopsfile, "(use-modules ((%s-%s) :renamer (symbol-prefix-proc 'primitive:)))\n", mod, primsuffix);
+ }
+ Printf(goopsfile, "%s\n(export %s)", goopscode, goopsexport);
+ if (exportprimitive) {
+ String *ex = NewString(exported_symbols);
+ Replaceall(ex, ", ", "\n ");
+ Replaceall(ex, "\"", "");
+ Chop(ex);
+ Printf(goopsfile, "\n(export %s)", ex);
+ Delete(ex);
+ }
+ Delete(mod);
+ Delete(goopsfile);
+ }
+
+ Delete(module_func);
+ if (CPlusPlus) {
+ Printf(f_init, "\n}\n");
+ }
+ }
+
+ /* Return true iff T is a pointer type */
+
+ int is_a_pointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+ }
+
+ /* Report an error handling the given type. */
+
+ void throw_unhandled_guile_type_error(SwigType *d) {
+ Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, "Unable to handle type %s.\n", SwigType_str(d, 0));
+ }
+
+ /* Write out procedure documentation */
+
+ void write_doc(const String *proc_name, const String *signature, const String *doc, const String *signature2 = NULL) {
+ switch (docformat) {
+ case GUILE_1_4:
+ Printv(procdoc, "\f\n", NIL);
+ Printv(procdoc, "(", signature, ")\n", NIL);
+ if (signature2)
+ Printv(procdoc, "(", signature2, ")\n", NIL);
+ Printv(procdoc, doc, "\n", NIL);
+ break;
+ case PLAIN:
+ Printv(procdoc, "\f", proc_name, "\n\n", NIL);
+ Printv(procdoc, "(", signature, ")\n", NIL);
+ if (signature2)
+ Printv(procdoc, "(", signature2, ")\n", NIL);
+ Printv(procdoc, doc, "\n\n", NIL);
+ break;
+ case TEXINFO:
+ Printv(procdoc, "\f", proc_name, "\n", NIL);
+ Printv(procdoc, "@deffn primitive ", signature, "\n", NIL);
+ if (signature2)
+ Printv(procdoc, "@deffnx primitive ", signature2, "\n", NIL);
+ Printv(procdoc, doc, "\n", NIL);
+ Printv(procdoc, "@end deffn\n\n", NIL);
+ break;
+ }
+ }
+
+ /* returns false if the typemap is an empty string */
+ bool handle_documentation_typemap(String *output,
+ const String *maybe_delimiter, Parm *p, const String *typemap, const String *default_doc, const String *name = NULL) {
+ String *tmp = NewString("");
+ String *tm;
+ if (!(tm = Getattr(p, typemap))) {
+ Printf(tmp, "%s", default_doc);
+ tm = tmp;
+ }
+ bool result = (Len(tm) > 0);
+ if (maybe_delimiter && Len(output) > 0 && Len(tm) > 0) {
+ Printv(output, maybe_delimiter, NIL);
+ }
+ const String *pn = !name ? (const String *) Getattr(p, "name") : name;
+ String *pt = Getattr(p, "type");
+ Replaceall(tm, "$name", pn); // legacy for $parmname
+ Replaceall(tm, "$type", SwigType_str(pt, 0));
+ /* $NAME is like $name, but marked-up as a variable. */
+ String *ARGNAME = NewString("");
+ if (docformat == TEXINFO)
+ Printf(ARGNAME, "@var{%s}", pn);
+ else
+ Printf(ARGNAME, "%(upper)s", pn);
+ Replaceall(tm, "$NAME", ARGNAME);
+ Replaceall(tm, "$PARMNAME", ARGNAME);
+ Printv(output, tm, NIL);
+ Delete(tmp);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * Create a function declaration and register it with the interpreter.
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+ String *proc_name = 0;
+ char source[256];
+ Wrapper *f = NewWrapper();
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *signature = NewString("");
+ String *doc_body = NewString("");
+ String *returns = NewString("");
+ String *method_signature = NewString("");
+ String *primitive_args = NewString("");
+ Hash *scheme_arg_names = NewHash();
+ int num_results = 1;
+ String *tmp = NewString("");
+ String *tm;
+ int i;
+ int numargs = 0;
+ int numreq = 0;
+ String *overname = 0;
+ int args_passed_as_array = 0;
+ int scheme_argnum = 0;
+ bool any_specialized_arg = false;
+
+ // Make a wrapper name for this
+ String *wname = Swig_name_wrapper(iname);
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ args_passed_as_array = 1;
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ // Build the name for scheme.
+ proc_name = NewString(iname);
+ Replaceall(proc_name, "_", "-");
+
+ /* Emit locals etc. into f->code; figure out which args to ignore */
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of required and total arguments */
+ numargs = emit_num_arguments(l);
+ numreq = emit_num_required(l);
+
+ /* Declare return variable */
+
+ Wrapper_add_local(f, "gswig_result", "SCM gswig_result");
+ Wrapper_add_local(f, "gswig_list_p", "SWIGUNUSED int gswig_list_p = 0");
+
+ /* Open prototype and signature */
+
+ Printv(f->def, "static SCM\n", wname, " (", NIL);
+ if (args_passed_as_array) {
+ Printv(f->def, "int argc, SCM *argv", NIL);
+ }
+ Printv(signature, proc_name, NIL);
+
+ /* Now write code to extract the parameters */
+
+ for (i = 0, p = l; i < numargs; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ int opt_p = (i >= numreq);
+
+ // Produce names of source and target
+ if (args_passed_as_array)
+ sprintf(source, "argv[%d]", i);
+ else
+ sprintf(source, "s_%d", i);
+
+ if (!args_passed_as_array) {
+ if (i != 0)
+ Printf(f->def, ", ");
+ Printf(f->def, "SCM s_%d", i);
+ }
+ if (opt_p) {
+ Printf(f->code, " if (%s != SCM_UNDEFINED) {\n", source);
+ }
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printv(f->code, tm, "\n", NIL);
+
+ SwigType *pb = SwigType_typedef_resolve_all(SwigType_base(pt));
+ SwigType *pn = Getattr(p, "name");
+ String *argname;
+ scheme_argnum++;
+ if (pn && !Getattr(scheme_arg_names, pn))
+ argname = pn;
+ else {
+ /* Anonymous arg or re-used argument name -- choose a name that cannot clash */
+ argname = NewStringf("%%arg%d", scheme_argnum);
+ }
+
+ if (procdoc) {
+ if (i == numreq) {
+ /* First optional argument */
+ Printf(signature, " #:optional");
+ }
+ /* Add to signature (arglist) */
+ handle_documentation_typemap(signature, " ", p, "tmap:in:arglist", "$name", argname);
+ /* Document the type of the arg in the documentation body */
+ handle_documentation_typemap(doc_body, ", ", p, "tmap:in:doc", "$NAME is of type <$type>", argname);
+ }
+
+ if (goops) {
+ if (i < numreq) {
+ if (strcmp("void", Char(pt)) != 0) {
+ Node *class_node = Swig_symbol_clookup_check(pb, Getattr(n, "sym:symtab"), has_classname);
+ String *goopsclassname = !class_node ? NULL : Getattr(class_node, "guile:goopsclassname");
+ /* do input conversion */
+ if (goopsclassname) {
+ Printv(method_signature, " (", argname, " ", goopsclassname, ")", NIL);
+ any_specialized_arg = true;
+ } else {
+ Printv(method_signature, " ", argname, NIL);
+ }
+ Printv(primitive_args, " ", argname, NIL);
+ Setattr(scheme_arg_names, argname, p);
+ }
+ }
+ }
+
+ if (!pn) {
+ Delete(argname);
+ }
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ throw_unhandled_guile_type_error(pt);
+ p = nextSibling(p);
+ }
+ if (opt_p)
+ Printf(f->code, " }\n");
+ }
+ if (Len(doc_body) > 0)
+ Printf(doc_body, ".\n");
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ /* Pass output arguments back to the caller. */
+
+ /* Insert argument output code */
+ String *returns_argout = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ if (procdoc) {
+ if (handle_documentation_typemap(returns_argout, ", ", p, "tmap:argout:doc", "$NAME (of type $type)")) {
+ /* A documentation typemap that is not the empty string
+ indicates that a value is returned to Scheme. */
+ num_results++;
+ }
+ }
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (exporting_destructor) {
+ /* Mark the destructor's argument as destroyed. */
+ String *tm = NewString("SWIG_Guile_MarkPointerDestroyed($input);");
+ Replaceall(tm, "$input", Getattr(l, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ Delete(tm);
+ }
+
+ /* Close prototype */
+
+ Printf(f->def, ")\n{\n");
+
+ /* Define the scheme name in C. This define is used by several Guile
+ macros. */
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ // Now write code to make the function call
+ String *actioncode = emit_action(n);
+
+ // Now have return value, figure out what to do with it.
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$result", "gswig_result");
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+ Printv(f->code, tm, "\n", NIL);
+ } else {
+ throw_unhandled_guile_type_error(returntype);
+ }
+ emit_return_variable(n, returntype, f);
+
+ // Documentation
+ if ((tm = Getattr(n, "tmap:out:doc"))) {
+ Printv(returns, tm, NIL);
+ if (Len(tm) > 0)
+ num_results = 1;
+ else
+ num_results = 0;
+ } else {
+ String *s = SwigType_str(returntype, 0);
+ Chop(s);
+ Printf(returns, "<%s>", s);
+ Delete(s);
+ num_results = 1;
+ }
+ Append(returns, returns_argout);
+
+
+ // Dump the argument output code
+ Printv(f->code, outarg, NIL);
+
+ // Dump the argument cleanup code
+ Printv(f->code, cleanup, NIL);
+
+ // Look for any remaining cleanup
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ // Wrap things up (in a manner of speaking)
+
+ if (beforereturn)
+ Printv(f->code, beforereturn, "\n", NIL);
+ Printv(f->code, "return gswig_result;\n", NIL);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+
+ // Undefine the scheme name
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (numargs > 10) {
+ /* "The total number of these arguments should match the actual number
+ * of arguments to fcn, but may not exceed 10" says:
+ * https://www.gnu.org/software/guile/manual/html_node/Primitive-Procedures.html
+ * We handle this case by passing all the arguments as "rest".
+ */
+ int i;
+ /* Build a wrapper wrapper */
+ Printv(f_wrappers, "static SCM\n", wname, "_rest (SCM rest)\n", NIL);
+ Printv(f_wrappers, "{\n", NIL);
+ Printf(f_wrappers, "SCM arg[%d];\n", numargs);
+ Printf(f_wrappers, "SWIG_Guile_GetArgs (arg, rest, %d, %d, \"%s\");\n", numreq, numargs - numreq, proc_name);
+ Printv(f_wrappers, "return ", wname, "(", NIL);
+ Printv(f_wrappers, "arg[0]", NIL);
+ for (i = 1; i < numargs; i++)
+ Printf(f_wrappers, ", arg[%d]", i);
+ Printv(f_wrappers, ");\n", NIL);
+ Printv(f_wrappers, "}\n", NIL);
+ /* Register it */
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, 0, 1, (swig_guile_proc) %s_rest);\n", proc_name, wname);
+ } else if (emit_setters && struct_member && strlen(Char(proc_name)) > 3) {
+ int len = Len(proc_name);
+ const char *pc = Char(proc_name);
+ /* MEMBER-set and MEMBER-get functions. */
+ int is_setter = (pc[len - 3] == 's');
+ if (is_setter) {
+ Printf(f_init, "SCM setter = ");
+ struct_member = 2; /* have a setter */
+ } else
+ Printf(f_init, "SCM getter = ");
+ /* GOOPS support uses the MEMBER-set and MEMBER-get functions,
+ so ignore only_setters in this case. */
+ if (only_setters && !goops)
+ Printf(f_init, "scm_c_make_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+ else
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+
+ if (!is_setter) {
+ /* Strip off "-get" */
+ if (struct_member == 2) {
+ /* There was a setter, so create a procedure with setter */
+ Printf(f_init, "scm_c_define");
+ Printf(f_init, "(\"%.*s\", " "scm_make_procedure_with_setter(getter, setter));\n", pc, len - 4);
+ } else {
+ /* There was no setter, so make an alias to the getter */
+ Printf(f_init, "scm_c_define");
+ Printf(f_init, "(\"%.*s\", getter);\n", pc, len - 4);
+ }
+ Printf(exported_symbols, "\"%.*s\", ", pc, len - 4);
+ }
+ } else {
+ /* Register the function */
+ if (exporting_destructor) {
+ Printf(f_init, "((swig_guile_clientdata *)(SWIGTYPE%s->clientdata))->destroy = (guile_destructor) %s;\n", swigtype_ptr, wname);
+ //Printf(f_init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) %s);\n", swigtype_ptr, wname);
+ }
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", %d, %d, 0, (swig_guile_proc) %s);\n", proc_name, numreq, numargs - numreq, wname);
+ }
+ } else { /* overloaded function; don't export the single methods */
+ if (!Getattr(n, "sym:nextSibling")) {
+ /* Emit overloading dispatch function */
+
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(argc,argv);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "static SCM\n", dname, "(SCM rest)\n{\n", NIL);
+ Printf(df->code, "#define FUNC_NAME \"%s\"\n", proc_name);
+ Printf(df->code, "SCM argv[%d];\n", maxargs);
+ Printf(df->code, "int argc = SWIG_Guile_GetArgs (argv, rest, %d, %d, \"%s\");\n", 0, maxargs, proc_name);
+ Printv(df->code, dispatch, "\n", NIL);
+ Printf(df->code, "scm_misc_error(\"%s\", \"No matching method for generic function `%s'\", SCM_EOL);\n", proc_name, iname);
+ Printf(df->code, "#undef FUNC_NAME\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, 0, 1, (swig_guile_proc) %s);\n", proc_name, dname);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ }
+ Printf(exported_symbols, "\"%s\", ", proc_name);
+
+ if (!in_class || memberfunction_name) {
+ // export wrapper into goops file
+ String *method_def = NewString("");
+ String *goops_name;
+ if (in_class)
+ goops_name = NewString(memberfunction_name);
+ else
+ goops_name = goopsNameMapping(proc_name, "");
+ String *primitive_name = NewString("");
+ if (primRenamer)
+ Printv(primitive_name, "primitive:", proc_name, NIL);
+ else
+ Printv(primitive_name, proc_name, NIL);
+ Replaceall(method_signature, "_", "-");
+ Replaceall(primitive_args, "_", "-");
+ if (!any_specialized_arg) {
+ /* If there would not be any specialized argument in
+ the method declaration, we simply re-export the
+ function. This is a performance optimization. */
+ Printv(method_def, "(define ", goops_name, " ", primitive_name, ")\n", NIL);
+ } else if (numreq == numargs) {
+ Printv(method_def, "(define-method (", goops_name, method_signature, ")\n", NIL);
+ Printv(method_def, " (", primitive_name, primitive_args, "))\n", NIL);
+ } else {
+ /* Handle optional args. For the rest argument, use a name
+ that cannot clash. */
+ Printv(method_def, "(define-method (", goops_name, method_signature, " . %args)\n", NIL);
+ Printv(method_def, " (apply ", primitive_name, primitive_args, " %args))\n", NIL);
+ }
+ if (in_class) {
+ /* Defer method definition till end of class definition. */
+ Printv(goops_class_methods, method_def, NIL);
+ } else {
+ Printv(goopscode, method_def, NIL);
+ }
+ Printf(goopsexport, "%s ", goops_name);
+ Delete(primitive_name);
+ Delete(goops_name);
+ Delete(method_def);
+ }
+
+ if (procdoc) {
+ String *returns_text = NewString("");
+ if (num_results == 0)
+ Printv(returns_text, return_nothing_doc, NIL);
+ else if (num_results == 1)
+ Printv(returns_text, return_one_doc, NIL);
+ else
+ Printv(returns_text, return_multi_doc, NIL);
+ /* Substitute documentation variables */
+ static const char *numbers[] = { "zero", "one", "two", "three",
+ "four", "five", "six", "seven",
+ "eight", "nine", "ten", "eleven",
+ "twelve"
+ };
+ if (num_results <= 12)
+ Replaceall(returns_text, "$num_values", numbers[num_results]);
+ else {
+ String *num_results_str = NewStringf("%d", num_results);
+ Replaceall(returns_text, "$num_values", num_results_str);
+ Delete(num_results_str);
+ }
+ Replaceall(returns_text, "$values", returns);
+ Printf(doc_body, "\n%s", returns_text);
+ write_doc(proc_name, signature, doc_body);
+ Delete(returns_text);
+ }
+
+ Delete(proc_name);
+ Delete(outarg);
+ Delete(cleanup);
+ Delete(signature);
+ Delete(method_signature);
+ Delete(primitive_args);
+ Delete(doc_body);
+ Delete(returns_argout);
+ Delete(returns);
+ Delete(tmp);
+ Delete(scheme_arg_names);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ *
+ * Create a link to a C variable.
+ * This creates a single function PREFIX_var_VARNAME().
+ * This function takes a single optional argument. If supplied, it means
+ * we are setting this variable to some value. If omitted, it means we are
+ * simply evaluating this variable. Either way, we return the variables
+ * value.
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ String *proc_name;
+ Wrapper *f;
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ f = NewWrapper();
+ // evaluation function names
+
+ String *var_name = Swig_name_wrapper(iname);
+
+ // Build the name for scheme.
+ proc_name = NewString(iname);
+ Replaceall(proc_name, "_", "-");
+ Setattr(n, "wrap:name", proc_name);
+
+ int assignable = !is_immutable(n);
+
+ if (1 || (SwigType_type(t) != T_USER) || (is_a_pointer(t))) {
+
+ Printf(f->def, "static SCM\n%s(SCM s_0)\n{\n", var_name);
+
+ /* Define the scheme name in C. This define is used by several Guile
+ macros. */
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ Wrapper_add_local(f, "gswig_result", "SCM gswig_result");
+
+ if (assignable) {
+ /* Check for a setting of the variable value */
+ Printf(f->code, "if (s_0 != SCM_UNDEFINED) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$input", "s_0");
+ /* Printv(f->code,tm,"\n",NIL); */
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_guile_type_error(t);
+ }
+ Printf(f->code, "}\n");
+ }
+ // Now return the value of the variable (regardless
+ // of evaluating or setting)
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "gswig_result");
+ /* Printv(f->code,tm,"\n",NIL); */
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_guile_type_error(t);
+ }
+ Printf(f->code, "\nreturn gswig_result;\n");
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ // Now add symbol to the Guile interpreter
+
+ if (!emit_setters || !assignable) {
+ /* Read-only variables become a simple procedure returning the
+ value; read-write variables become a simple procedure with
+ an optional argument. */
+
+ if (!goops && GetFlag(n, "feature:constasvar")) {
+ /* need to export this function as a variable instead of a procedure */
+ if (scmstub) {
+ /* export the function in the wrapper, and (set!) it in scmstub */
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, %d, 0, (swig_guile_proc) %s);\n", proc_name, assignable, var_name);
+ Printf(scmtext, "(set! %s (%s))\n", proc_name, proc_name);
+ } else {
+ /* export the variable directly */
+ Printf(f_init, "scm_c_define(\"%s\", %s(SCM_UNDEFINED));\n", proc_name, var_name);
+ }
+
+ } else {
+ /* Export the function as normal */
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 0, %d, 0, (swig_guile_proc) %s);\n", proc_name, assignable, var_name);
+ }
+
+ } else {
+ /* Read/write variables become a procedure with setter. */
+ Printf(f_init, "{ SCM p = scm_c_define_gsubr(\"%s\", 0, 1, 0, (swig_guile_proc) %s);\n", proc_name, var_name);
+ Printf(f_init, "scm_c_define");
+ Printf(f_init, "(\"%s\", " "scm_make_procedure_with_setter(p, p)); }\n", proc_name);
+ }
+ Printf(exported_symbols, "\"%s\", ", proc_name);
+
+ // export wrapper into goops file
+ if (!in_class) { // only if the variable is not part of a class
+ String *class_name = SwigType_typedef_resolve_all(SwigType_base(t));
+ String *goops_name = goopsNameMapping(proc_name, "");
+ String *primitive_name = NewString("");
+ if (primRenamer)
+ Printv(primitive_name, "primitive:", NIL);
+ Printv(primitive_name, proc_name, NIL);
+ /* Simply re-export the procedure */
+ if ((!emit_setters || !assignable)
+ && GetFlag(n, "feature:constasvar")) {
+ Printv(goopscode, "(define ", goops_name, " (", primitive_name, "))\n", NIL);
+ } else {
+ Printv(goopscode, "(define ", goops_name, " ", primitive_name, ")\n", NIL);
+ }
+ Printf(goopsexport, "%s ", goops_name);
+ Delete(primitive_name);
+ Delete(class_name);
+ Delete(goops_name);
+ }
+
+ if (procdoc) {
+ /* Compute documentation */
+ String *signature = NewString("");
+ String *signature2 = NULL;
+ String *doc = NewString("");
+
+ if (!assignable) {
+ Printv(signature, proc_name, NIL);
+ if (GetFlag(n, "feature:constasvar")) {
+ Printv(doc, "Is constant ", NIL);
+ } else {
+ Printv(doc, "Returns constant ", NIL);
+ }
+ if ((tm = Getattr(n, "tmap:varout:doc"))) {
+ Printv(doc, tm, NIL);
+ } else {
+ String *s = SwigType_str(t, 0);
+ Chop(s);
+ Printf(doc, "<%s>", s);
+ Delete(s);
+ }
+ } else if (emit_setters) {
+ Printv(signature, proc_name, NIL);
+ signature2 = NewString("");
+ Printv(signature2, "set! (", proc_name, ") ", NIL);
+ handle_documentation_typemap(signature2, NIL, n, "tmap:varin:arglist", "new-value");
+ Printv(doc, "Get or set the value of the C variable, \n", NIL);
+ Printv(doc, "which is of type ", NIL);
+ handle_documentation_typemap(doc, NIL, n, "tmap:varout:doc", "$1_type");
+ Printv(doc, ".");
+ } else {
+ Printv(signature, proc_name, " #:optional ", NIL);
+ if ((tm = Getattr(n, "tmap:varin:doc"))) {
+ Printv(signature, tm, NIL);
+ } else {
+ String *s = SwigType_str(t, 0);
+ Chop(s);
+ Printf(signature, "new-value <%s>", s);
+ Delete(s);
+ }
+
+ Printv(doc, "If NEW-VALUE is provided, " "set C variable to this value.\n", NIL);
+ Printv(doc, "Returns variable value ", NIL);
+ if ((tm = Getattr(n, "tmap:varout:doc"))) {
+ Printv(doc, tm, NIL);
+ } else {
+ String *s = SwigType_str(t, 0);
+ Chop(s);
+ Printf(doc, "<%s>", s);
+ Delete(s);
+ }
+ }
+ write_doc(proc_name, signature, doc, signature2);
+ Delete(signature);
+ if (signature2)
+ Delete(signature2);
+ Delete(doc);
+ }
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
+ }
+ Delete(var_name);
+ Delete(proc_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ *
+ * We create a read-only variable.
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ int constasvar = GetFlag(n, "feature:constasvar");
+
+
+ String *proc_name;
+ String *var_name;
+ Wrapper *f;
+ SwigType *nctype;
+ String *tm;
+
+ f = NewWrapper();
+
+ // Make a static variable;
+ var_name = NewStringf("%sconst_%s", prefix, iname);
+
+ // Strip const qualifier from type if present
+
+ nctype = NewString(type);
+ if (SwigType_isconst(nctype)) {
+ Delete(SwigType_pop(nctype));
+ }
+ // Build the name for scheme.
+ proc_name = NewString(iname);
+ Replaceall(proc_name, "_", "-");
+
+ if ((SwigType_type(nctype) == T_USER) && (!is_a_pointer(nctype))) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ Delete(var_name);
+ DelWrapper(f);
+ return SWIG_NOWRAP;
+ }
+ // See if there's a typemap
+
+ if ((tm = Swig_typemap_lookup("constant", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Printv(f_header, tm, "\n", NIL);
+ } else {
+ // Create variable and assign it a value
+ Printf(f_header, "static %s = (%s)(%s);\n", SwigType_str(type, var_name), SwigType_str(type, 0), value);
+ }
+ {
+ /* Hack alert: will cleanup later -- Dave */
+ Node *nn = NewHash();
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ Setattr(nn, "name", var_name);
+ Setattr(nn, "sym:name", iname);
+ Setattr(nn, "type", nctype);
+ SetFlag(nn, "feature:immutable");
+ if (constasvar) {
+ SetFlag(nn, "feature:constasvar");
+ }
+ variableWrapper(nn);
+ Delete(nn);
+ }
+ Delete(var_name);
+ Delete(nctype);
+ Delete(proc_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+ virtual int classDeclaration(Node *n) {
+ String *class_name = NewStringf("<%s>", Getattr(n, "sym:name"));
+ Setattr(n, "guile:goopsclassname", class_name);
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+ virtual int classHandler(Node *n) {
+ /* Create new strings for building up a wrapper function */
+ have_constructor = 0;
+
+ class_name = NewString("");
+ short_class_name = NewString("");
+ Printv(class_name, "<", Getattr(n, "sym:name"), ">", NIL);
+ Printv(short_class_name, Getattr(n, "sym:name"), NIL);
+ Replaceall(class_name, "_", "-");
+ Replaceall(short_class_name, "_", "-");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ /* Handle inheritance */
+ String *base_class = NewString("<");
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator i = First(baselist);
+ while (i.item) {
+ Printv(base_class, Getattr(i.item, "sym:name"), NIL);
+ i = Next(i);
+ if (i.item) {
+ Printf(base_class, "> <");
+ }
+ }
+ }
+ Printf(base_class, ">");
+ Replaceall(base_class, "_", "-");
+
+ Printv(goopscode, "(define-class ", class_name, " ", NIL);
+ Printf(goopsexport, "%s ", class_name);
+
+ if (Len(base_class) > 2) {
+ Printv(goopscode, "(", base_class, ")\n", NIL);
+ } else {
+ Printv(goopscode, "(<swig>)\n", NIL);
+ }
+ SwigType *ct = NewStringf("p.%s", Getattr(n, "name"));
+ swigtype_ptr = SwigType_manglestr(ct);
+
+ String *mangled_classname = Swig_name_mangle_string(Getattr(n, "sym:name"));
+ /* Export clientdata structure */
+ Printf(f_runtime, "static swig_guile_clientdata _swig_guile_clientdata%s = { NULL, SCM_EOL };\n", mangled_classname);
+
+ Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", swigtype_ptr, ", (void *) &_swig_guile_clientdata", mangled_classname, ");\n", NIL);
+ SwigType_remember(ct);
+ Delete(ct);
+
+ /* Emit all of the members */
+ goops_class_methods = NewString("");
+
+ in_class = 1;
+ Language::classHandler(n);
+ in_class = 0;
+
+ Printv(goopscode, " #:metaclass <swig-metaclass>\n", NIL);
+
+ if (have_constructor)
+ Printv(goopscode, " #:new-function ", primRenamer ? "primitive:" : "", "new-", short_class_name, "\n", NIL);
+
+ Printf(goopscode, ")\n%s\n", goops_class_methods);
+ Delete(goops_class_methods);
+ goops_class_methods = 0;
+
+
+ /* export class initialization function */
+ if (goops) {
+ /* export the wrapper function */
+ String *funcName = NewString(mangled_classname);
+ Printf(funcName, "_swig_guile_setgoopsclass");
+ String *guileFuncName = NewString(funcName);
+ Replaceall(guileFuncName, "_", "-");
+
+ Printv(f_wrappers, "static SCM ", funcName, "(SCM cl) \n", NIL);
+ Printf(f_wrappers, "#define FUNC_NAME %s\n{\n", guileFuncName);
+ Printv(f_wrappers, " ((swig_guile_clientdata *)(SWIGTYPE", swigtype_ptr, "->clientdata))->goops_class = cl;\n", NIL);
+ Printf(f_wrappers, " return SCM_UNSPECIFIED;\n");
+ Printf(f_wrappers, "}\n#undef FUNC_NAME\n\n");
+
+ Printf(f_init, "scm_c_define_gsubr(\"%s\", 1, 0, 0, (swig_guile_proc) %s);\n", guileFuncName, funcName);
+ Printf(exported_symbols, "\"%s\", ", guileFuncName);
+
+ /* export the call to the wrapper function */
+ Printf(goopscode, "(%s%s %s)\n\n", primRenamer ? "primitive:" : "", guileFuncName, class_name);
+
+ Delete(guileFuncName);
+ Delete(funcName);
+ }
+
+ Delete(mangled_classname);
+
+ Delete(swigtype_ptr);
+ swigtype_ptr = 0;
+
+ Delete(class_name);
+ Delete(short_class_name);
+ class_name = 0;
+ short_class_name = 0;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+ int memberfunctionHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+
+ memberfunction_name = goopsNameMapping(proc, short_class_name);
+ Language::memberfunctionHandler(n);
+ Delete(memberfunction_name);
+ memberfunction_name = NULL;
+ Delete(proc);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+ int membervariableHandler(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+
+ if (emit_setters) {
+ struct_member = 1;
+ Printf(f_init, "{\n");
+ }
+
+ Language::membervariableHandler(n);
+
+ if (emit_setters) {
+ Printf(f_init, "}\n");
+ struct_member = 0;
+ }
+
+ String *proc = NewString(iname);
+ Replaceall(proc, "_", "-");
+ String *goops_name = goopsNameMapping(proc, short_class_name);
+
+ /* The slot name is never qualified with the class,
+ even if useclassprefix is true. */
+ Printv(goopscode, " (", proc, " #:allocation #:virtual", NIL);
+ /* GOOPS (at least in Guile 1.6.3) only accepts closures, not
+ primitive procedures for slot-ref and slot-set. */
+ Printv(goopscode, "\n #:slot-ref (lambda (obj) (", primRenamer ? "primitive:" : "", short_class_name, "-", proc, "-get", " obj))", NIL);
+ if (!GetFlag(n, "feature:immutable")) {
+ Printv(goopscode, "\n #:slot-set! (lambda (obj value) (", primRenamer ? "primitive:" : "", short_class_name, "-", proc, "-set", " obj value))", NIL);
+ } else {
+ Printf(goopscode, "\n #:slot-set! (lambda (obj value) (error \"Immutable slot\"))");
+ }
+ if (emit_slot_accessors) {
+ if (GetFlag(n, "feature:immutable")) {
+ Printv(goopscode, "\n #:getter ", goops_name, NIL);
+ } else {
+ Printv(goopscode, "\n #:accessor ", goops_name, NIL);
+ }
+ Printf(goopsexport, "%s ", goops_name);
+ }
+ Printv(goopscode, ")\n", NIL);
+ Delete(proc);
+ Delete(goops_name);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ * ------------------------------------------------------------ */
+ int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+ virtual int destructorHandler(Node *n) {
+ exporting_destructor = true;
+ Language::destructorHandler(n);
+ exporting_destructor = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * pragmaDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *cmd = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+# define store_pragma(PRAGMANAME) \
+ if (Strcmp(cmd, #PRAGMANAME) == 0) { \
+ if (PRAGMANAME) Delete(PRAGMANAME); \
+ PRAGMANAME = value ? NewString(value) : NULL; \
+ }
+
+ if (Strcmp(lang, "guile") == 0) {
+ store_pragma(beforereturn)
+ store_pragma(return_nothing_doc)
+ store_pragma(return_one_doc)
+ store_pragma(return_multi_doc);
+# undef store_pragma
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * goopsNameMapping()
+ * Maps the identifier from C++ to the GOOPS based * on command
+ * line parameters and such.
+ * If class_name = "" that means the mapping is for a function or
+ * variable not attached to any class.
+ * ------------------------------------------------------------ */
+ String *goopsNameMapping(String *name, const_String_or_char_ptr class_name) {
+ String *n = NewString("");
+
+ if (Strcmp(class_name, "") == 0) {
+ // not part of a class, so no class name to prefix
+ if (goopsprefix) {
+ Printf(n, "%s%s", goopsprefix, name);
+ } else {
+ Printf(n, "%s", name);
+ }
+ } else {
+ if (useclassprefix) {
+ Printf(n, "%s-%s", class_name, name);
+ } else {
+ if (goopsprefix) {
+ Printf(n, "%s%s", goopsprefix, name);
+ } else {
+ Printf(n, "%s", name);
+ }
+ }
+ }
+ return n;
+ }
+
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ /* Check whether we have an R5RS identifier. Guile supports a
+ superset of R5RS identifiers, but it's probably a bad idea to use
+ those. */
+ /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */
+ /* <initial> --> <letter> | <special initial> */
+ if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~'))) {
+ /* <peculiar identifier> --> + | - | ... */
+ if ((strcmp(c, "+") == 0)
+ || strcmp(c, "-") == 0 || strcmp(c, "...") == 0)
+ return 1;
+ else
+ return 0;
+ }
+ /* <subsequent> --> <initial> | <digit> | <special subsequent> */
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+')
+ || (*c == '-') || (*c == '.') || (*c == '@')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ String *runtimeCode() {
+ String *s;
+ s = Swig_include_sys("guile_scm_run.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'guile_scm_run.swg");
+ s = NewString("");
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigguilerun.h");
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_guile() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_guile() {
+ return new GUILE();
+}
+extern "C" Language *swig_guile(void) {
+ return new_swig_guile();
+}
diff --git a/contrib/tools/swig/Source/Modules/interface.cxx b/contrib/tools/swig/Source/Modules/interface.cxx
new file mode 100644
index 00000000000..3916c4085b0
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/interface.cxx
@@ -0,0 +1,210 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * interface.cxx
+ *
+ * This module contains support for the interface feature.
+ * This feature is used in language modules where the target language does not
+ * naturally support C++ style multiple inheritance, but does support inheritance
+ * from multiple interfaces.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static bool interface_feature_enabled = false;
+
+/* -----------------------------------------------------------------------------
+ * collect_interface_methods()
+ *
+ * Create a list of all the methods from the base classes of class n that are
+ * marked as an interface. The resulting list is thus the list of methods that
+ * need to be implemented in order for n to be non-abstract.
+ * ----------------------------------------------------------------------------- */
+
+static List *collect_interface_methods(Node *n) {
+ List *methods = NewList();
+ if (List *bases = Getattr(n, "interface:bases")) {
+ for (Iterator base = First(bases); base.item; base = Next(base)) {
+ Node *cls = base.item;
+ if (cls == n)
+ continue;
+ for (Node *child = firstChild(cls); child; child = nextSibling(child)) {
+ if (Cmp(nodeType(child), "cdecl") == 0) {
+ if (GetFlag(child, "feature:ignore") || Getattr(child, "interface:owner"))
+ continue; // skip methods propagated to bases
+ if (!checkAttribute(child, "kind", "function"))
+ continue;
+ if (checkAttribute(child, "storage", "static"))
+ continue; // accept virtual methods, non-virtual methods too... mmm??. Warn that the interface class has something that is not a virtual method?
+ Node *nn = copyNode(child);
+ Setattr(nn, "interface:owner", cls);
+ ParmList *parms = CopyParmList(Getattr(child, "parms"));
+ Setattr(nn, "parms", parms);
+ Delete(parms);
+ ParmList *throw_parm_list = Getattr(child, "throws");
+ if (throw_parm_list)
+ Setattr(nn, "throws", CopyParmList(throw_parm_list));
+ Append(methods, nn);
+ }
+ }
+ }
+ }
+ return methods;
+}
+
+/* -----------------------------------------------------------------------------
+ * collect_interface_bases
+ * ----------------------------------------------------------------------------- */
+
+static void collect_interface_bases(List *bases, Node *n) {
+ if (GetFlag(n, "feature:interface")) {
+ if (!Swig_item_in_list(bases, n))
+ Append(bases, n);
+ }
+
+ if (List *baselist = Getattr(n, "bases")) {
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ if (GetFlag(base.item, "feature:interface"))
+ collect_interface_bases(bases, base.item);
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * collect_interface_base_classes()
+ *
+ * Create a list containing all the classes up the inheritance hierarchy
+ * marked with feature:interface (including this class n).
+ * Stops going up the inheritance chain as soon as a class is found without
+ * feature:interface.
+ * Remove duplicate bases (in the event of multiple inheritance).
+ * The idea is to find all the base interfaces that a class must implement.
+ * ----------------------------------------------------------------------------- */
+
+static void collect_interface_base_classes(Node *n) {
+ if (GetFlag(n, "feature:interface")) {
+ // check all bases are also interfaces
+ if (List *baselist = Getattr(n, "bases")) {
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ if (!GetFlag(base.item, "feature:interface")) {
+ Swig_error(Getfile(n), Getline(n), "Base class '%s' of '%s' is not similarly marked as an interface.\n", SwigType_namestr(Getattr(base.item, "name")), SwigType_namestr(Getattr(n, "name")));
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+ }
+ }
+
+ List *interface_bases = NewList();
+ collect_interface_bases(interface_bases, n);
+ if (Len(interface_bases) == 0)
+ Delete(interface_bases);
+ else
+ Setattr(n, "interface:bases", interface_bases);
+}
+
+/* -----------------------------------------------------------------------------
+ * process_interface_name()
+ * ----------------------------------------------------------------------------- */
+
+static void process_interface_name(Node *n) {
+ if (GetFlag(n, "feature:interface")) {
+ String *interface_name = Getattr(n, "feature:interface:name");
+ if (!Len(interface_name)) {
+ Swig_error(Getfile(n), Getline(n), "The interface feature for '%s' is missing the name attribute.\n", SwigType_namestr(Getattr(n, "name")));
+ Exit(EXIT_FAILURE);
+ }
+ if (Strchr(interface_name, '%')) {
+ String *name = NewStringf(interface_name, Getattr(n, "sym:name"));
+ Setattr(n, "interface:name", name);
+ } else {
+ Setattr(n, "interface:name", interface_name);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_interface_propagate_methods()
+ *
+ * Find all the base classes marked as an interface (with feature:interface) for
+ * class node n. For each of these, add all of its methods as methods of n so that
+ * n is not abstract. If class n is also marked as an interface, it will remain
+ * abstract and not have any methods added.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_interface_propagate_methods(Node *n) {
+ if (interface_feature_enabled) {
+ process_interface_name(n);
+ collect_interface_base_classes(n);
+ List *methods = collect_interface_methods(n);
+ bool is_interface = GetFlag(n, "feature:interface") ? true : false;
+ for (Iterator mi = First(methods); mi.item; mi = Next(mi)) {
+ if (!is_interface && GetFlag(mi.item, "abstract"))
+ continue;
+ String *this_decl = Getattr(mi.item, "decl");
+ String *this_decl_resolved = SwigType_typedef_resolve_all(this_decl);
+ bool identically_overloaded_method = false; // true when a base class' method is implemented in n
+ if (SwigType_isfunction(this_decl_resolved)) {
+ String *name = Getattr(mi.item, "name");
+ for (Node *child = firstChild(n); child; child = nextSibling(child)) {
+ if (Getattr(child, "interface:owner"))
+ break; // at the end of the list are newly appended methods
+ if (Cmp(nodeType(child), "cdecl") == 0) {
+ if (checkAttribute(child, "name", name)) {
+ String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
+ identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0;
+ Delete(decl);
+ if (identically_overloaded_method)
+ break;
+ }
+ }
+ }
+ }
+ Delete(this_decl_resolved);
+ if (!identically_overloaded_method) {
+ // Add method copied from base class to this derived class
+ Node *cn = mi.item;
+ Delattr(cn, "sym:overname");
+ String *prefix = Getattr(n, "name");
+ String *name = Getattr(cn, "name");
+ String *decl = Getattr(cn, "decl");
+ String *oldname = Getattr(cn, "sym:name");
+
+ String *symname = Swig_name_make(cn, prefix, name, decl, oldname);
+ if (Strcmp(symname, "$ignore") != 0) {
+ Symtab *oldscope = Swig_symbol_setscope(Getattr(n, "symtab"));
+ Node *on = Swig_symbol_add(symname, cn);
+ (void)on;
+ assert(on == cn);
+
+ // Features from the copied base class method are already present, now add in features specific to the added method in the derived class
+ Swig_features_get(Swig_cparse_features(), Swig_symbol_qualifiedscopename(0), name, decl, cn);
+ Swig_symbol_setscope(oldscope);
+ appendChild(n, cn);
+ }
+ } else {
+ Delete(mi.item);
+ }
+ }
+ Delete(methods);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_interface_feature_enable()
+ *
+ * Turn on interface feature support
+ * ----------------------------------------------------------------------------- */
+
+void Swig_interface_feature_enable() {
+ interface_feature_enabled = true;
+}
diff --git a/contrib/tools/swig/Source/Modules/java.cxx b/contrib/tools/swig/Source/Modules/java.cxx
new file mode 100644
index 00000000000..2efc89bec2e
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/java.cxx
@@ -0,0 +1,4969 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * java.cxx
+ *
+ * Java language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <errno.h>
+#include <limits.h> // for INT_MAX
+#include <ctype.h>
+#include "javadoc.h"
+
+/* Hash type used for upcalls from C/C++ */
+typedef DOH UpcallData;
+
+class JAVA:public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *protected_string;
+
+ Hash *swig_types_hash;
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ List *filenames_list;
+
+ bool proxy_flag; // Flag for generating proxy classes
+ bool nopgcpp_flag; // Flag for suppressing the premature garbage collection prevention parameter
+ bool native_function_flag; // Flag for when wrapping a native function
+ bool enum_constant_flag; // Flag for when wrapping an enum or constant
+ bool static_flag; // Flag for when wrapping a static functions or member variables
+ bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
+ bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
+ bool global_variable_flag; // Flag for when wrapping a global variable
+ bool old_variable_names; // Flag for old style variable names in the intermediary class
+ bool member_func_flag; // flag set when wrapping a member function
+ bool doxygen; //flag for converting found doxygen to javadoc
+ bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx
+
+ String *imclass_name; // intermediary class name
+ String *module_class_name; // module class name
+ String *constants_interface_name; // constants interface name
+ String *imclass_class_code; // intermediary class code
+ String *proxy_class_def;
+ String *proxy_class_code;
+ String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
+ 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;
+ String *module_class_constants_code;
+ String *common_begin_code;
+ String *enum_code;
+ String *package; // Optional package name
+ String *jnipackage; // Package name used in the JNI code
+ String *package_path; // Package name used internally by JNI (slashes)
+ String *imclass_imports; //intermediary class imports from %pragma
+ String *module_imports; //module imports from %pragma
+ String *imclass_baseclass; //inheritance for intermediary class class from %pragma
+ String *imclass_package; //package in which to generate the intermediary class
+ String *module_baseclass; //inheritance for module class from %pragma
+ String *imclass_interfaces; //interfaces for intermediary class class from %pragma
+ String *module_interfaces; //interfaces for module class from %pragma
+ String *imclass_class_modifiers; //class modifiers for intermediary class overridden by %pragma
+ String *module_class_modifiers; //class modifiers for module class overridden by %pragma
+ String *constants_modifiers; //access modifiers for constants interface overridden by %pragma
+ String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
+ String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
+ String *imclass_directors; // Intermediate class director code
+ String *destructor_call; //C++ destructor call if any
+ String *destructor_throws_clause; //C++ destructor throws clause if any
+
+ // Director method stuff:
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int n_directors;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+ int nesting_depth;
+
+ enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
+
+public:
+
+ /* -----------------------------------------------------------------------------
+ * JAVA()
+ * ----------------------------------------------------------------------------- */
+
+ JAVA():empty_string(NewString("")),
+ public_string(NewString("public")),
+ protected_string(NewString("protected")),
+ swig_types_hash(NULL),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ filenames_list(NULL),
+ proxy_flag(true),
+ nopgcpp_flag(false),
+ native_function_flag(false),
+ enum_constant_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ old_variable_names(false),
+ member_func_flag(false),
+ doxygen(false),
+ comment_creation_chatter(false),
+ imclass_name(NULL),
+ module_class_name(NULL),
+ constants_interface_name(NULL),
+ imclass_class_code(NULL),
+ proxy_class_def(NULL),
+ proxy_class_code(NULL),
+ interface_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),
+ module_class_constants_code(NULL),
+ common_begin_code(NULL),
+ enum_code(NULL),
+ package(NULL),
+ jnipackage(NULL),
+ package_path(NULL),
+ imclass_imports(NULL),
+ module_imports(NULL),
+ imclass_baseclass(NULL),
+ imclass_package(NULL),
+ module_baseclass(NULL),
+ imclass_interfaces(NULL),
+ module_interfaces(NULL),
+ imclass_class_modifiers(NULL),
+ module_class_modifiers(NULL),
+ constants_modifiers(NULL),
+ upcasts_code(NULL),
+ imclass_cppcasts_code(NULL),
+ imclass_directors(NULL),
+ destructor_call(NULL),
+ destructor_throws_clause(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ n_directors(0),
+ first_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;
+ directorLanguage();
+ }
+
+ ~JAVA() {
+ delete doxygenTranslator;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * constructIntermediateClassName()
+ *
+ * Construct the fully qualified name of the intermediate class and set
+ * the full_imclass_name attribute accordingly.
+ * ----------------------------------------------------------------------------- */
+ void constructIntermediateClassName(Node *n) {
+ String *nspace = Getattr(n, "sym:nspace");
+
+ if (imclass_package && package)
+ full_imclass_name = NewStringf("%s.%s.%s", package, imclass_package, imclass_name);
+ else if (package && nspace)
+ full_imclass_name = NewStringf("%s.%s", package, imclass_name);
+ else if (imclass_package)
+ full_imclass_name = NewStringf("%s.%s", imclass_package, imclass_name);
+ else
+ full_imclass_name = NewStringf("%s", imclass_name);
+
+ if (nspace && !package) {
+ String *name = Getattr(n, "name") ? Getattr(n, "name") : NewString("<unnamed>");
+ Swig_warning(WARN_JAVA_NSPACE_WITHOUT_PACKAGE, Getfile(n), Getline(n),
+ "The nspace feature is used on '%s' without -package. "
+ "The generated code may not compile as Java does not support types declared in a named package accessing types declared in an unnamed package.\n", SwigType_namestr(name));
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getProxyName()
+ *
+ * Test to see if a type corresponds to something wrapped with a proxy class.
+ * Return NULL if not otherwise the proxy class name, fully qualified with
+ * package name if the nspace feature is used, unless jnidescriptor is true as
+ * the package name is handled differently (unfortunately for legacy reasons).
+ * ----------------------------------------------------------------------------- */
+
+ String *getProxyName(SwigType *t, bool jnidescriptor = false) {
+ String *proxyname = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n) {
+ proxyname = Getattr(n, "proxyname");
+ if (!proxyname || jnidescriptor) {
+ String *nspace = Getattr(n, "sym:nspace");
+ 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")) {
+ if (String* name = Getattr(outer_class, "sym:name")) {
+ Push(symname, jnidescriptor ? "$" : ".");
+ Push(symname, name);
+ }
+ else
+ return NULL;
+ }
+ }
+ if (nspace) {
+ if (package && !jnidescriptor)
+ proxyname = NewStringf("%s.%s.%s", package, nspace, symname);
+ else
+ proxyname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ proxyname = Copy(symname);
+ }
+ if (!jnidescriptor) {
+ Setattr(n, "proxyname", proxyname); // Cache it
+ Delete(proxyname);
+ }
+ Delete(symname);
+ }
+ }
+ }
+ return proxyname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * makeValidJniName()
+ * ----------------------------------------------------------------------------- */
+
+ String *makeValidJniName(const String *name) {
+ String *valid_jni_name = NewString(name);
+ Replaceall(valid_jni_name, "_", "_1");
+ return valid_jni_name;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("java");
+
+ int doxygen_translator_flags = 0;
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString("");
+ Printf(package, argv[i + 1]);
+ if (Len(package) == 0) {
+ Delete(package);
+ package = 0;
+ }
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-doxygen") == 0)) {
+ Swig_mark_arg(i);
+ doxygen = true;
+ scan_doxygen_comments = true;
+ } else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) {
+ Swig_mark_arg(i);
+ doxygen_translator_flags |= DoxygenTranslator::debug_translator;
+ } else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) {
+ Swig_mark_arg(i);
+ doxygen_translator_flags |= DoxygenTranslator::debug_parser;
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ Swig_mark_arg(i);
+ proxy_flag = false;
+ } else if (strcmp(argv[i], "-nopgcpp") == 0) {
+ Swig_mark_arg(i);
+ nopgcpp_flag = true;
+ } else if (strcmp(argv[i], "-oldvarnames") == 0) {
+ Swig_mark_arg(i);
+ old_variable_names = true;
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ if (doxygen)
+ doxygenTranslator = new JavaDocConverter(doxygen_translator_flags);
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGJAVA 1", 0);
+
+ SWIG_config_file("java.swg");
+
+ allow_overloading();
+ Swig_interface_feature_enable();
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+
+ // Get any options set in the module directive
+ Node *module = Getattr(n, "module");
+ Node *optionsnode = Getattr(module, "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "jniclassname"))
+ imclass_name = Copy(Getattr(optionsnode, "jniclassname"));
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ if (Getattr(optionsnode, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ common_begin_code = Getattr(optionsnode, "javabegin");
+ if (common_begin_code)
+ Printf(common_begin_code, "\n");
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (Swig_directors_enabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ swig_types_hash = NewHash();
+ filenames_list = NewList();
+
+ // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
+ if (!imclass_name) {
+ imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
+ module_class_name = Copy(Getattr(n, "name"));
+ } else {
+ // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
+ if (Cmp(imclass_name, Getattr(n, "name")) == 0)
+ module_class_name = NewStringf("%sModule", Getattr(n, "name"));
+ else
+ module_class_name = Copy(Getattr(n, "name"));
+ }
+ constants_interface_name = NewStringf("%sConstants", module_class_name);
+
+ // module class and intermediary classes are always created
+ if (!addSymbol(imclass_name, module))
+ return SWIG_ERROR;
+ if (!addSymbol(module_class_name, module))
+ return SWIG_ERROR;
+
+ imclass_class_code = NewString("");
+ proxy_class_def = NewString("");
+ proxy_class_code = NewString("");
+ module_class_constants_code = NewString("");
+ imclass_baseclass = NewString("");
+ imclass_package = NULL;
+ imclass_interfaces = NewString("");
+ imclass_class_modifiers = NewString("");
+ module_class_code = NewString("");
+ module_baseclass = NewString("");
+ module_interfaces = NewString("");
+ module_imports = NewString("");
+ module_class_modifiers = NewString("");
+ constants_modifiers = NewString("");
+ imclass_imports = NewString("");
+ imclass_cppcasts_code = NewString("");
+ imclass_directors = NewString("");
+ upcasts_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+ n_directors = 0;
+ jnipackage = NewString("");
+ package_path = NewString("");
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "JAVA");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ Printf(f_runtime, "\n");
+
+ String *wrapper_name = NewString("");
+
+ if (package) {
+ String *jniname = makeValidJniName(package);
+ Printv(jnipackage, jniname, NIL);
+ Delete(jniname);
+ Replaceall(jnipackage, ".", "_");
+ Append(jnipackage, "_");
+ Printv(package_path, package, NIL);
+ Replaceall(package_path, ".", "/");
+ }
+ String *jniname = makeValidJniName(imclass_name);
+ Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, jniname);
+ Delete(jniname);
+
+ Swig_name_register("wrapper", Char(wrapper_name));
+ if (old_variable_names) {
+ Swig_name_register("set", "set_%n%v");
+ Swig_name_register("get", "get_%n%v");
+ }
+
+ Delete(wrapper_name);
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ /* Emit code */
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+ // Generate the intermediary class
+ {
+ String *filen = NewStringf("%s%s.java", outputDirectory(imclass_package), imclass_name);
+ File *f_im = NewFile(filen, "w", SWIG_output_files());
+ if (!f_im) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the intermediary class file
+ emitBanner(f_im);
+
+ if (imclass_package && package)
+ Printf(f_im, "package %s.%s;", package, imclass_package);
+ else if (imclass_package)
+ Printf(f_im, "package %s;", imclass_package);
+ else if (package)
+ Printf(f_im, "package %s;\n", package);
+
+ if (imclass_imports)
+ Printf(f_im, "%s\n", imclass_imports);
+
+ if (Len(imclass_class_modifiers) > 0)
+ Printf(f_im, "%s ", imclass_class_modifiers);
+ Printf(f_im, "%s ", imclass_name);
+
+ if (imclass_baseclass && *Char(imclass_baseclass))
+ Printf(f_im, "extends %s ", imclass_baseclass);
+ if (Len(imclass_interfaces) > 0)
+ Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
+ Printf(f_im, "{\n");
+
+ // Add the intermediary class methods
+ Replaceall(imclass_class_code, "$module", module_class_name);
+ Replaceall(imclass_class_code, "$imclassname", imclass_name);
+ Printv(f_im, imclass_class_code, NIL);
+ Printv(f_im, imclass_cppcasts_code, NIL);
+ if (Len(imclass_directors) > 0)
+ Printv(f_im, "\n", imclass_directors, NIL);
+
+ if (n_dmethods > 0) {
+ Putc('\n', f_im);
+ Printf(f_im, " private final static native void swig_module_init();\n");
+ Printf(f_im, " static {\n");
+ Printf(f_im, " swig_module_init();\n");
+ Printf(f_im, " }\n");
+ }
+ // Finish off the class
+ Printf(f_im, "}\n");
+ Delete(f_im);
+ }
+
+ // Generate the Java module class
+ {
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name);
+ File *f_module = NewFile(filen, "w", SWIG_output_files());
+ if (!f_module) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the module class file
+ emitBanner(f_module);
+
+ if (package)
+ Printf(f_module, "package %s;\n", package);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
+ if (comment_creation_chatter)
+ Printf(f_module, "/* This was generated from top() */\n");
+ Printv(f_module, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+ if (Len(module_class_modifiers) > 0)
+ Printf(f_module, "%s ", module_class_modifiers);
+ Printf(f_module, "%s ", module_class_name);
+
+ if (module_baseclass && *Char(module_baseclass))
+ Printf(f_module, "extends %s ", module_baseclass);
+ if (Len(module_interfaces) > 0) {
+ if (Len(module_class_constants_code) != 0)
+ Printv(f_module, "implements ", constants_interface_name, ", ", module_interfaces, " ", NIL);
+ else
+ Printv(f_module, "implements ", module_interfaces, " ", NIL);
+ } else {
+ if (Len(module_class_constants_code) != 0)
+ Printv(f_module, "implements ", constants_interface_name, " ", NIL);
+ }
+ Printf(f_module, "{\n");
+
+ Replaceall(module_class_code, "$module", module_class_name);
+ Replaceall(module_class_constants_code, "$module", module_class_name);
+
+ Replaceall(module_class_code, "$imclassname", imclass_name);
+ Replaceall(module_class_constants_code, "$imclassname", imclass_name);
+
+ // Add the wrapper methods
+ Printv(f_module, module_class_code, NIL);
+
+ // Finish off the class
+ Printf(f_module, "}\n");
+ Delete(f_module);
+ }
+
+ // Generate the Java constants interface
+ if (Len(module_class_constants_code) != 0) {
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), constants_interface_name);
+ File *f_module = NewFile(filen, "w", SWIG_output_files());
+ if (!f_module) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the Java constants interface file
+ emitBanner(f_module);
+
+ if (package)
+ Printf(f_module, "package %s;\n", package);
+
+ if (module_imports)
+ Printf(f_module, "%s\n", module_imports);
+
+ if (Len(constants_modifiers) > 0)
+ Printf(f_module, "%s ", constants_modifiers);
+ Printf(f_module, "%s {\n", constants_interface_name);
+
+ // Write out all the global constants
+ Printv(f_module, module_class_constants_code, NIL);
+
+ // Finish off the Java interface
+ Printf(f_module, "}\n");
+ Delete(f_module);
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ emitDirectorUpcalls();
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Output a Java type wrapper class for each SWIG type
+ for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
+ emitTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(swig_types_hash);
+ swig_types_hash = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(imclass_name);
+ imclass_name = NULL;
+ Delete(imclass_class_code);
+ imclass_class_code = NULL;
+ Delete(proxy_class_def);
+ proxy_class_def = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(module_class_constants_code);
+ module_class_constants_code = NULL;
+ Delete(imclass_baseclass);
+ imclass_baseclass = NULL;
+ Delete(imclass_package);
+ imclass_package = NULL;
+ Delete(imclass_interfaces);
+ imclass_interfaces = NULL;
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = NULL;
+ Delete(module_class_name);
+ module_class_name = NULL;
+ Delete(constants_interface_name);
+ constants_interface_name = NULL;
+ Delete(module_class_code);
+ module_class_code = NULL;
+ Delete(module_baseclass);
+ module_baseclass = NULL;
+ Delete(module_interfaces);
+ module_interfaces = NULL;
+ Delete(module_imports);
+ module_imports = NULL;
+ Delete(module_class_modifiers);
+ module_class_modifiers = NULL;
+ Delete(constants_modifiers);
+ constants_modifiers = NULL;
+ Delete(imclass_imports);
+ imclass_imports = NULL;
+ Delete(imclass_cppcasts_code);
+ imclass_cppcasts_code = NULL;
+ Delete(imclass_directors);
+ imclass_directors = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(package);
+ package = NULL;
+ Delete(jnipackage);
+ jnipackage = NULL;
+ Delete(package_path);
+ package_path = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ n_dmethods = 0;
+
+ /* Close all of the files */
+ Dump(f_header, f_runtime);
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors, f_runtime);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ Dump(f_wrappers, f_runtime);
+ Wrapper_pretty_print(f_init, f_runtime);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Dump(f_runtime, f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitBanner()
+ * ----------------------------------------------------------------------------- */
+
+ void emitBanner(File *f) {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
+ Printv(f, common_begin_code, NIL);
+ }
+
+ /*-----------------------------------------------------------------------
+ * Add new director upcall signature
+ *----------------------------------------------------------------------*/
+
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) {
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ String *imclass_methodidx = NewStringf("%d", n_dmethods);
+ String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ Hash *new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "fdesc", Copy(class_desc));
+ Setattr(new_udata, "imclass_method", Copy(imclass_method));
+ Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc));
+ Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /*-----------------------------------------------------------------------
+ * Get director upcall signature
+ *----------------------------------------------------------------------*/
+
+ UpcallData *getUpcallMethodData(String *director_class, String *decl) {
+ String *key = NewStringf("%s|%s", director_class, decl);
+ UpcallData *udata = Getattr(dmethods_table, key);
+
+ Delete(key);
+ return udata;
+ }
+
+ /* ----------------------------------------------------------------------
+ * nativeWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n, imclass_name))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ int num_arguments = 0;
+ int gencomma = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+ String *nondir_args = NewString("");
+ bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(symname, n, imclass_name))
+ return SWIG_ERROR;
+ }
+
+ /*
+ The rest of this function deals with generating the intermediary class wrapper function (that wraps
+ a c/c++ function) and generating the JNI c code. Each Java wrapper function has a
+ matching JNI c function call.
+ */
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *jniname = makeValidJniName(overloaded_name);
+ String *wname = Swig_name_wrapper(jniname);
+
+ Delete(jniname);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("jni", l, f);
+ Swig_typemap_attach_parms("jtype", l, f);
+ Swig_typemap_attach_parms("jstype", l, f);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("jni", n, "", 0))) {
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) {
+ Printf(im_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ is_void_return = Cmp(c_return_type, "void") == 0;
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL);
+
+ Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL);
+
+ // Usually these function parameters are unused - The code below ensures
+ // that compilers do not issue such a warning if configured to do so.
+
+ Printv(f->code, " (void)jenv;\n", NIL);
+ Printv(f->code, " (void)jcls;\n", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore")) {
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+ }
+
+ Printf(imclass_class_code, " public final static native %s %s(", im_return_type, overloaded_name);
+
+ num_arguments = emit_num_arguments(l);
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the JNI C types of the parameter */
+ if ((tm = Getattr(p, "tmap:jni"))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = Getattr(p, "tmap:jtype"))) {
+ Printv(im_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(imclass_class_code, ", ");
+ Printf(imclass_class_code, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, ", ", c_param_type, " ", arg, NIL);
+
+ ++gencomma;
+
+ // Premature garbage collection prevention parameter
+ if (!is_destructor) {
+ String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p);
+ if (pgc_parameter) {
+ Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg);
+ Printf(f->def, ", jobject %s_", arg);
+ Printf(f->code, " (void)%s_;\n", arg);
+ }
+ }
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ addThrows(n, "tmap:in", p);
+ Replaceall(tm, "$arg", arg); /* deprecated? */
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+
+ Printf(nondir_args, "%s\n", tm);
+
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ }
+
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ Printv(f->code, nondir_args, NIL);
+ Delete(nondir_args);
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ addThrows(n, "tmap:check", p);
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ addThrows(n, "tmap:freearg", p);
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ addThrows(n, "tmap:argout", p);
+ Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Get any Java exception classes in the throws typemap
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ addThrows(n, "tmap:throws", p);
+ }
+ }
+ }
+
+ // Now write code to make the function call
+ if (!native_function_flag) {
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ // Handle exception classes specified in the "except" feature's "throws" attribute
+ addThrows(n, "feature:except", n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ addThrows(n, "tmap:out", n);
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ if (Len(tm))
+ Printf(f->code, "\n");
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, returntype, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ addThrows(n, "tmap:newfree", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ addThrows(n, "tmap:ret", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* Finish C function and intermediary class function definitions */
+ Printf(imclass_class_code, ")");
+ generateThrowsClause(n, imclass_class_code);
+ Printf(imclass_class_code, ";\n");
+
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ Replaceall(f->code, "$isvoid", is_void_return ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
+
+ if (!is_void_return)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", "");
+
+ /* Dump the function out */
+ if (!native_function_flag)
+ Wrapper_print(f, f_wrappers);
+
+ if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
+ moduleClassFunctionHandler(n);
+ }
+
+ /*
+ * Generate the proxy class getters/setters for public member variables.
+ * Not for enums and constants.
+ */
+ 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, getClassPrefix(), variable_name))) != 0;
+
+ String *getter_setter_name = NewString("");
+ if (!getter_flag)
+ Printf(getter_setter_name, "set");
+ else
+ Printf(getter_setter_name, "get");
+ Putc(toupper((int) *Char(variable_name)), getter_setter_name);
+ Printf(getter_setter_name, "%s", Char(variable_name) + 1);
+
+ Setattr(n, "proxyfuncname", getter_setter_name);
+ Setattr(n, "imfuncname", symname);
+
+ proxyClassFunctionHandler(n);
+ Delete(getter_setter_name);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ variable_wrapper_flag = true;
+ Language::variableWrapper(n); /* Default to functions */
+ variable_wrapper_flag = false;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------------------ */
+
+ virtual int globalvariableHandler(Node *n) {
+
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+ return ret;
+ }
+
+ String *getCurrentScopeName(String *nspace) {
+ String *scope = 0;
+ if (nspace || getCurrentClass()) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s", nspace);
+ if (Node* cls = getCurrentClass()) {
+ if (Node *outer = Getattr(cls, "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"));
+ }
+ Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
+ Delete(outerClassesPrefix);
+ } else
+ Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
+ }
+ }
+ return scope;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumDeclaration()
+ *
+ * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified:
+ * 1) Simple enums - simple constant within the proxy class or module class
+ * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name)
+ * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
+ * 4) Proper enums - proper Java enum
+ * Anonymous enums always default to 1)
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumDeclaration(Node *n) {
+
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+
+ enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
+ EnumFeature enum_feature = decodeEnumFeature(n);
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
+
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
+ if (comment_creation_chatter)
+ Printf(enum_code, "/* This was generated from enumDeclaration() */\n");
+ Printv(enum_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ String *scope = getCurrentScopeName(nspace);
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ // Pure Java baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
+
+ // Emit the enum
+ Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
+ " ", symname, *Char(pure_baseclass) ? // Bases
+ " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
+ " implements " : "", pure_interfaces, " {\n", NIL);
+ if (proxy_flag && is_wrapping_class())
+ Replaceall(enum_code, "$static ", "static ");
+ else
+ Replaceall(enum_code, "$static ", "");
+ Delete(scope);
+ } else {
+ if (symname && !Getattr(n, "unnamedinstance"))
+ Printf(constants_code, " // %s \n", symname);
+ // Translate and write javadoc comment for the enum itself if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(constants_code, "/* This was generated from enumDeclaration() */\n");
+ Printf(constants_code, Char(doxygen_comments));
+ Printf(constants_code, "\n");
+ Delete(doxygen_comments);
+ }
+ }
+
+ if (proxy_flag && !is_wrapping_class()) {
+ // Global enums / enums in a namespace
+ assert(!full_imclass_name);
+ constructIntermediateClassName(n);
+ }
+
+ // Emit each enum item
+ Language::enumDeclaration(n);
+
+ if (proxy_flag && !is_wrapping_class()) {
+ Delete(full_imclass_name);
+ full_imclass_name = 0;
+ }
+
+ if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
+ // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
+ // Finish the enum declaration
+ // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
+ Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
+ typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
+ "}", NIL);
+
+ Replaceall(enum_code, "$javaclassname", symname);
+
+ // Substitute $enumvalues - intended usage is for typesafe enums
+ if (Getattr(n, "enumvalues"))
+ Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
+ else
+ Replaceall(enum_code, "$enumvalues", "");
+
+ if (proxy_flag && is_wrapping_class()) {
+ // Enums defined within the C++ class are defined within the proxy class
+
+ // Add extra indentation
+ Replaceall(enum_code, "\n", "\n ");
+ Replaceall(enum_code, " \n", "\n");
+ Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
+ } else {
+ // Global enums are defined in their own file
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.java", output_directory, symname);
+ File *f_enum = NewFile(filen, "w", SWIG_output_files());
+ if (!f_enum) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the enum file
+ emitBanner(f_enum);
+
+ if (package || nspace) {
+ Printf(f_enum, "package ");
+ if (package)
+ Printv(f_enum, package, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(f_enum, nspace, NIL);
+ Printf(f_enum, ";\n");
+ }
+
+ Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
+ "\n", enum_code, "\n", NIL);
+
+ Printf(f_enum, "\n");
+ Delete(f_enum);
+ Delete(output_directory);
+ }
+ } else {
+ // Wrap C++ enum with simple constant
+ Printf(enum_code, "\n");
+ if (proxy_flag && is_wrapping_class())
+ Printv(proxy_class_constants_code, enum_code, NIL);
+ else
+ Printv(module_class_constants_code, enum_code, NIL);
+ }
+
+ Delete(enum_code);
+ enum_code = NULL;
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ int unnamedinstance = GetFlag(parent, "unnamedinstance");
+ String *parent_name = Getattr(parent, "name");
+ String *nspace = getNSpace();
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_CHAR) {
+ if (Getattr(n, "enumstringval")) {
+ String *val = NewStringf("'%(escape)s'", Getattr(n, "enumstringval"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+ } else {
+ String *numval = Getattr(n, "enumnumval");
+ if (numval) {
+ const char *p = Char(numval);
+ if (isdigit(p[0])) {
+ char *e;
+ errno = 0;
+ unsigned long long value = strtoull(p, &e, 0);
+ if (errno != ERANGE && *e == '\0' && value >= 0x80000000) {
+ // Use hex for larger unsigned integer constants in Java code since
+ // Java allows implicit conversion to a signed integer value.
+ String *hexval = NewStringf("0x%llx", value);
+ Setattr(n, "enumvalue", hexval);
+ Delete(hexval);
+ } else {
+ Setattr(n, "enumvalue", numval);
+ }
+ } else {
+ // Emit negative values as-is.
+ Setattr(n, "enumvalue", numval);
+ }
+ }
+ }
+
+ {
+ EnumFeature enum_feature = decodeEnumFeature(parent);
+
+ if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
+
+ // Add to language symbol table
+ String *scope = 0;
+ if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", enumClassPrefix);
+ } else {
+ scope = Copy(constants_interface_name);
+ }
+ } else {
+ scope = getCurrentScopeName(nspace);
+ if (!scope)
+ scope = Copy(Getattr(parent, "sym:name"));
+ else
+ Printf(scope, ".%s", Getattr(parent, "sym:name"));
+ }
+ if (!addSymbol(symname, n, scope))
+ return SWIG_ERROR;
+
+ if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(enum_code, ",\n");
+ }
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n");
+ Printv(enum_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) C/C++ enum with a proper Java enum
+ // Emit the enum item.
+ Printf(enum_code, " %s", symname);
+ if (Getattr(n, "enumvalue")) {
+ String *value = enumValue(n);
+ Printf(enum_code, "(%s)", value);
+ Delete(value);
+ }
+ } else {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ Setattr(n, "type", typemap_lookup_type);
+ const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
+
+ String *return_type = Copy(tm);
+ substituteClassname(typemap_lookup_type, return_type);
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
+ // Wrap (non-anonymous) enum using the typesafe enum pattern
+ if (Getattr(n, "enumvalue")) {
+ String *value = enumValue(n);
+ Printf(enum_code, " %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
+ Delete(value);
+ } else {
+ Printf(enum_code, " %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
+ }
+ } else {
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
+ String *value = enumValue(n);
+ Printf(enum_code, " %s final static %s %s = %s;\n", methodmods, return_type, symname, value);
+ Delete(value);
+ }
+ Delete(return_type);
+ }
+
+ // Add the enum value to the comma separated list being constructed in the enum declaration.
+ String *enumvalues = Getattr(parent, "enumvalues");
+ if (!enumvalues)
+ Setattr(parent, "enumvalues", Copy(symname));
+ else
+ Printv(enumvalues, ", ", symname, NIL);
+ Delete(scope);
+ }
+
+ Delete(newsymname);
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ * Used for wrapping constants - #define or %constant.
+ * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
+ * Java static final variables are generated for these.
+ * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable.
+ * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable.
+ * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation.
+ * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)).
+ * ------------------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *return_type = NewString("");
+ String *constants_code = NewString("");
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(constants_code, "/* This was generated from constantWrapper() */\n");
+ Printv(constants_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
+
+ const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
+ if (!is_enum_item) {
+ String *scope = 0;
+ if (proxy_class_name) {
+ String *nspace = getNSpace();
+ scope = NewString("");
+ if (nspace)
+ Printf(scope, "%s.", nspace);
+ Printf(scope, "%s", proxy_class_name);
+ } else {
+ scope = Copy(constants_interface_name);
+ }
+ if (!addSymbol(itemname, n, scope))
+ return SWIG_ERROR;
+ Delete(scope);
+ }
+
+ // The %javaconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:java:const");
+
+ /* Adjust the enum type for the Swig_typemap_lookup.
+ * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
+ if (is_enum_item) {
+ t = Getattr(parentNode(n), "enumtype");
+ Setattr(n, "type", t);
+ }
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("jstype", l, NULL);
+
+ /* Get Java return types */
+ bool classname_substituted_flag = false;
+
+ if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
+ classname_substituted_flag = substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ Printf(constants_code, " %s final static %s %s = ", methodmods, return_type, itemname);
+
+ // Check for the %javaconstvalue feature
+ String *value = Getattr(n, "feature:java:constvalue");
+
+ if (value) {
+ Printf(constants_code, "%s;\n", value);
+ } else if (!const_feature_flag) {
+ // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call.
+
+ if (classname_substituted_flag) {
+ if (SwigType_isenum(t)) {
+ // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
+ Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ // This handles function pointers using the %constant directive
+ Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+ } else {
+ Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ }
+
+ // Each constant and enum value is wrapped with a separate JNI function call
+ SetFlag(n, "feature:immutable");
+ enum_constant_flag = true;
+ variableWrapper(n);
+ enum_constant_flag = false;
+ } else {
+ // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code
+ if (Getattr(n, "wrappedasconstant")) {
+ Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
+ } else {
+ Printf(constants_code, "%s;\n", Getattr(n, "value"));
+ }
+ }
+
+ // Emit the generated code to appropriate place
+ // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed
+ if (!is_enum_item) {
+ if (proxy_flag && wrapping_member_flag)
+ Printv(proxy_class_constants_code, constants_code, NIL);
+ else
+ Printv(module_class_constants_code, constants_code, NIL);
+ }
+ // Cleanup
+ Swig_restore(n);
+ Delete(return_type);
+ Delete(constants_code);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * insertDirective()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int insertDirective(Node *n) {
+ int ret = SWIG_OK;
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ Replaceall(code, "$module", module_class_name);
+ Replaceall(code, "$imclassname", imclass_name);
+
+ if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
+ if (proxy_class_code) {
+ Swig_typemap_replace_embedded_typemap(code, n);
+ int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
+ Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
+ }
+ } else {
+ ret = Language::insertDirective(n);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * pragmaDirective()
+ *
+ * Valid Pragmas:
+ * jniclassbase - base (extends) for the intermediary class
+ * jniclasspackage - package in which to generate the intermediary class
+ * jniclassclassmodifiers - class modifiers for the intermediary class
+ * jniclasscode - text (java code) is copied verbatim to the intermediary class
+ * jniclassimports - import statements for the intermediary class
+ * jniclassinterfaces - interface (implements) for the intermediary class
+ *
+ * modulebase - base (extends) for the module class
+ * moduleclassmodifiers - class modifiers for the module class
+ * modulecode - text (java code) is copied verbatim to the module class
+ * moduleimports - import statements for the module class
+ * moduleinterfaces - interface (implements) for the module class
+ *
+ * constantsmodifiers - access modifiers for the constants interface
+ * ----------------------------------------------------------------------------- */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "java") == 0) {
+
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "jniclassbase") == 0) {
+ Delete(imclass_baseclass);
+ imclass_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "jniclasspackage") == 0) {
+ Delete(imclass_package);
+ imclass_package = Copy(strvalue);
+ String *imclass_class_package_jniname = makeValidJniName(imclass_package);
+ Printv(jnipackage, imclass_class_package_jniname, NIL);
+ Delete(imclass_class_package_jniname);
+ Replaceall(jnipackage, NSPACE_SEPARATOR, "_");
+ Append(jnipackage, "_");
+
+ String *wrapper_name = NewString("");
+ String *imclass_class_jniname = makeValidJniName(imclass_name);
+ Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, imclass_class_jniname);
+ Delete(imclass_class_jniname);
+
+ Swig_name_unregister("wrapper");
+ Swig_name_register("wrapper", Char(wrapper_name));
+
+ Delete(wrapper_name);
+ } else if (Strcmp(code, "jniclassclassmodifiers") == 0) {
+ Delete(imclass_class_modifiers);
+ imclass_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "jniclasscode") == 0) {
+ Printf(imclass_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "jniclassimports") == 0) {
+ Delete(imclass_imports);
+ imclass_imports = Copy(strvalue);
+ } else if (Strcmp(code, "jniclassinterfaces") == 0) {
+ Delete(imclass_interfaces);
+ imclass_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "modulebase") == 0) {
+ Delete(module_baseclass);
+ module_baseclass = Copy(strvalue);
+ } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
+ Delete(module_class_modifiers);
+ module_class_modifiers = Copy(strvalue);
+ } else if (Strcmp(code, "modulecode") == 0) {
+ Printf(module_class_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "moduleimports") == 0) {
+ Delete(module_imports);
+ module_imports = Copy(strvalue);
+ } else if (Strcmp(code, "moduleinterfaces") == 0) {
+ Delete(module_interfaces);
+ module_interfaces = Copy(strvalue);
+ } else if (Strcmp(code, "constantsmodifiers") == 0) {
+ Delete(constants_modifiers);
+ constants_modifiers = Copy(strvalue);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getQualifiedInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getQualifiedInterfaceName(Node *n) {
+ String *ret = Getattr(n, "interface:qname");
+ if (!ret) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *symname = Getattr(n, "interface:name");
+ if (nspace) {
+ if (package)
+ ret = NewStringf("%s.%s.%s", package, nspace, symname);
+ else
+ ret = NewStringf("%s.%s", nspace, symname);
+ } else {
+ ret = Copy(symname);
+ }
+ Setattr(n, "interface:qname", ret);
+ }
+ return ret;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getInterfaceName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getInterfaceName(SwigType *t, bool qualified) {
+ String *interface_name = NULL;
+ if (proxy_flag) {
+ Node *n = classLookup(t);
+ if (n && Getattr(n, "interface:name"))
+ interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
+ }
+ return interface_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addInterfaceNameAndUpcasts()
+ * ----------------------------------------------------------------------------- */
+
+ void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, List *base_list, SwigType *c_classname) {
+ for (Iterator it = First(base_list); it.item; it = Next(it)) {
+ Node *base = it.item;
+ SwigType *c_baseclassname = Getattr(base, "name");
+ String *interface_name = Getattr(base, "interface:name");
+ SwigType *bsmart = Getattr(base, "smart");
+ if (Len(interface_list))
+ Append(interface_list, ", ");
+ Append(interface_list, interface_name);
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(base, "javainterfacecode", Getattr(base, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ String *cptr_method_name = 0;
+ if (interface_code) {
+ Replaceall(interface_code, "$interfacename", interface_name);
+ Printv(interface_upcasts, interface_code, NIL);
+ cptr_method_name = Copy(Getattr(attributes, "tmap:javainterfacecode:cptrmethod"));
+ }
+ if (!cptr_method_name)
+ cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
+ Replaceall(cptr_method_name, ".", "_");
+ Replaceall(cptr_method_name, "$interfacename", interface_name);
+
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
+ upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname);
+
+ Delete(upcast_method_name);
+ Delete(cptr_method_name);
+ Delete(interface_code);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * upcastsCode()
+ *
+ * Add code for C++ casting to base class
+ * ----------------------------------------------------------------------------- */
+
+ void upcastsCode(SwigType *smart, SwigType *bsmart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
+ String *jniname = makeValidJniName(upcast_method_name);
+ String *wname = Swig_name_wrapper(jniname);
+
+ Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name);
+
+ if (smart) {
+ if (bsmart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(bsmart);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
+ " jlong baseptr = 0;\n"
+ " ", smartnamestr, " *argp1;\n"
+ " (void)jenv;\n"
+ " (void)jcls;\n"
+ " argp1 = *(", smartnamestr, " **)&jarg1;\n"
+ " *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n"
+ " return baseptr;\n"
+ "}\n", "\n", NIL);
+
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ }
+ } else {
+ String *classname = SwigType_namestr(c_classname);
+ String *baseclassname = SwigType_namestr(c_baseclassname);
+
+ Printv(upcasts_code,
+ "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
+ " jlong baseptr = 0;\n"
+ " (void)jenv;\n"
+ " (void)jcls;\n"
+ " *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n"
+ " return baseptr;\n"
+ "}\n", "\n", NIL);
+
+ Delete(baseclassname);
+ Delete(classname);
+ }
+
+ Delete(wname);
+ Delete(jniname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitProxyClassDefAndCPPCasts()
+ * ----------------------------------------------------------------------------- */
+
+ void emitProxyClassDefAndCPPCasts(Node *n) {
+ SwigType *c_classname = Getattr(n, "name");
+ SwigType *c_baseclassname = NULL;
+ String *baseclass = NULL;
+ String *interface_list = NewStringEmpty();
+ String *interface_upcasts = NewStringEmpty();
+ 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");
+ SwigType *smart = Getattr(n, "smart");
+ SwigType *bsmart = 0;
+
+ // Inheritance from pure Java classes
+ Node *attributes = NewHash();
+ const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!(GetFlag(base.item, "feature:ignore") || GetFlag(base.item, "feature:interface"))) {
+ SwigType *baseclassname = Getattr(base.item, "name");
+ if (!c_baseclassname) {
+ String *name = getProxyName(baseclassname);
+ if (name) {
+ c_baseclassname = baseclassname;
+ baseclass = name;
+ bsmart = Getattr(base.item, "smart");
+ }
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+
+ List *interface_bases = Getattr(n, "interface:bases");
+ if (interface_bases)
+ addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
+
+ bool derived = baseclass != 0;
+ if (derived && purebase_notderived)
+ pure_baseclass = empty_string;
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ baseclass = NULL;
+ if (purebase_notderived)
+ Swig_error(Getfile(n), Getline(n), "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
+ } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
+ Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the javabase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Pure Java interfaces
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
+
+ if (*Char(interface_list) && *Char(pure_interfaces))
+ Append(interface_list, ", ");
+ Append(interface_list, pure_interfaces);
+ // Start writing the proxy class
+ if (!has_outerclass) // Import statements
+ Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
+ if (comment_creation_chatter)
+ Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n");
+ Printv(proxy_class_def, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ if (has_outerclass)
+ 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(interface_list) ? // Pure Java interfaces
+ " implements " : "", interface_list, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
+ typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
+ NIL);
+
+ // C++ destructor is wrapped by the delete method
+ // Note that the method name is specified in a typemap attribute called methodname
+ String *destruct = NewString("");
+ const String *tm = NULL;
+ attributes = NewHash();
+ const String *destruct_methodname = NULL;
+ const String *destruct_methodmodifiers = NULL;
+ const String *destruct_parameters = NULL;
+ if (derived) {
+ tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters");
+ } else {
+ tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
+ destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
+ destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
+ destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters");
+ }
+ if (tm && *Char(tm)) {
+ if (!destruct_methodname) {
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!destruct_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!destruct_parameters)
+ destruct_parameters = empty_string;
+ }
+ // Emit the finalize and delete methods
+ if (tm) {
+ // Finalize method
+ if (*Char(destructor_call)) {
+ Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL);
+ }
+ // delete method
+ Printv(destruct, tm, NIL);
+ if (*Char(destructor_call))
+ Replaceall(destruct, "$jnicall", destructor_call);
+ else
+ Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
+ if (*Char(destruct)) {
+ Printv(proxy_class_def, "\n ", NIL);
+ const String *methodmods = Getattr(n, "destructmethodmodifiers");
+ if (methodmods)
+ Printv(proxy_class_def, methodmods, NIL);
+ else
+ Printv(proxy_class_def, destruct_methodmodifiers, NIL);
+ Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL);
+ }
+ }
+ if (*Char(interface_upcasts))
+ Printv(proxy_class_def, interface_upcasts, NIL);
+
+ /* Insert directordisconnect typemap, if this class has directors enabled */
+ /* 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(), getClassPrefix(), "change_ownership");
+
+ destruct_jnicall = NewStringf("%s()", destruct_methodname);
+ release_jnicall = NewStringf("%s.%s(this, swigCPtr, false)", full_imclass_name, changeown_method_name);
+ take_jnicall = NewStringf("%s.%s(this, swigCPtr, true)", full_imclass_name, changeown_method_name);
+
+ emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall);
+ emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall);
+ emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall);
+
+ Delete(destruct_jnicall);
+ Delete(changeown_method_name);
+ Delete(release_jnicall);
+ Delete(take_jnicall);
+ }
+
+ Delete(interface_upcasts);
+ Delete(interface_list);
+ Delete(attributes);
+ Delete(destruct);
+
+ // Emit extra user code
+ Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
+ "\n", NIL);
+
+ if (derived) {
+ String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
+ upcastsCode(smart, bsmart, upcast_method_name, c_classname, c_baseclassname);
+ Delete(upcast_method_name);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * emitInterfaceDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface, String *nspace) {
+ if (package || nspace) {
+ Printf(f_interface, "package ");
+ if (package)
+ Printv(f_interface, package, nspace ? "." : "", NIL);
+ if (nspace)
+ Printv(f_interface, nspace, NIL);
+ Printf(f_interface, ";\n");
+ }
+
+ Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
+ Printv(f_interface, typemapLookup(n, "javainterfacemodifiers", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL);
+ Printf(f_interface, " %s", interface_name);
+
+ String *additional = Getattr(n, "feature:interface:additional");
+ String *bases = additional ? Copy(additional) : 0;
+ if (List *baselist = Getattr(n, "bases")) {
+ for (Iterator base = First(baselist); base.item; base = Next(base)) {
+ if (GetFlag(base.item, "feature:ignore") || !GetFlag(base.item, "feature:interface"))
+ continue; // TODO: warn about skipped non-interface bases
+ String *base_iname = Getattr(base.item, "interface:name");
+ if (!bases)
+ bases = Copy(base_iname);
+ else {
+ Append(bases, ", ");
+ Append(bases, base_iname);
+ }
+ }
+ }
+ if (bases) {
+ Printv(f_interface, " extends ", bases, NIL);
+ Delete(bases);
+ }
+ Printf(f_interface, " {\n");
+
+ Node *attributes = NewHash();
+ String *interface_code = Copy(typemapLookup(n, "javainterfacecode", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
+ if (interface_code) {
+ String *interface_declaration = Copy(Getattr(attributes, "tmap:javainterfacecode:declaration"));
+ if (interface_declaration) {
+ Replaceall(interface_declaration, "$interfacename", interface_name);
+ Printv(f_interface, interface_declaration, NIL);
+ Delete(interface_declaration);
+ }
+ Delete(interface_code);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * classDeclaration()
+ * ---------------------------------------------------------------------- */
+
+ int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ File *f_proxy = NULL;
+ File *f_interface = 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;
+ bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
+ String *old_interface_class_code = interface_class_code;
+ interface_class_code = 0;
+
+ 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 = 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);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (Cmp(proxy_class_name, module_class_name) == 0) {
+ Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
+ Exit(EXIT_FAILURE);
+ }
+ } else {
+ 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);
+ }
+ }
+
+ String *interface_name = GetFlag(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
+ if (outerClassesPrefix) {
+ String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
+ if (!addSymbol(proxy_class_name, n, fnspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
+ return SWIG_ERROR;
+ if (nspace)
+ Delete(fnspace);
+ Delete(outerClassesPrefix);
+ } else {
+ if (!addSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+ if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
+ return SWIG_ERROR;
+ }
+
+ // Each outer proxy class goes into a separate file
+ if (!has_outerclass) {
+ 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);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ Delete(output_directory);
+
+ // Start writing out the proxy class file
+ emitBanner(f_proxy);
+
+ 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("");
+
+ if (GetFlag(n, "feature:interface")) {
+ interface_class_code = NewString("");
+ String *output_directory = outputDirectory(nspace);
+ String *filen = NewStringf("%s%s.java", output_directory, interface_name);
+ f_interface = NewFile(filen, "w", SWIG_output_files());
+ if (!f_interface) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, filen); // file name ownership goes to the list
+ emitBanner(f_interface);
+ emitInterfaceDeclaration(n, interface_name, interface_class_code, nspace);
+ Delete(filen);
+ Delete(output_directory);
+ }
+ }
+
+ Language::classHandler(n);
+
+ if (proxy_flag) {
+ emitProxyClassDefAndCPPCasts(n);
+
+ 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);
+ Replaceall(proxy_class_constants_code, "$javaclassname", proxy_class_name);
+ Replaceall(interface_class_code, "$javaclassname", proxy_class_name);
+
+ Replaceall(proxy_class_def, "$javaclazzname", javaclazzname);
+ Replaceall(proxy_class_code, "$javaclazzname", javaclazzname);
+ Replaceall(proxy_class_constants_code, "$javaclazzname", javaclazzname);
+ Replaceall(interface_class_code, "$javaclazzname", javaclazzname);
+
+ Replaceall(proxy_class_def, "$module", module_class_name);
+ Replaceall(proxy_class_code, "$module", module_class_name);
+ Replaceall(proxy_class_constants_code, "$module", module_class_name);
+ Replaceall(interface_class_code, "$module", module_class_name);
+
+ Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
+ Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
+ Replaceall(interface_class_code, "$imclassname", full_imclass_name);
+
+ 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) {
+ 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");
+ 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;
+ }
+
+ if (f_interface) {
+ Printv(f_interface, interface_class_code, "}\n", NIL);
+ Delete(f_interface);
+ f_interface = 0;
+ }
+
+ emitDirectorExtraMethods(n);
+
+ Delete(interface_class_code);
+ interface_class_code = old_interface_class_code;
+ Delete(javaclazzname);
+ Delete(proxy_class_name);
+ proxy_class_name = old_proxy_class_name;
+ Delete(full_proxy_class_name);
+ full_proxy_class_name = old_full_proxy_class_name;
+ Delete(full_imclass_name);
+ full_imclass_name = old_full_imclass_name;
+ Delete(destructor_call);
+ destructor_call = old_destructor_call;
+ Delete(destructor_throws_clause);
+ destructor_throws_clause = old_destructor_throws_clause;
+ Delete(proxy_class_constants_code);
+ 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;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ member_func_flag = true;
+ Language::memberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ 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);
+ Delete(overloaded_name);
+ }
+ member_func_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+
+ static_flag = true;
+ member_func_flag = true;
+ Language::staticmemberfunctionHandler(n);
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ 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);
+ Delete(overloaded_name);
+ }
+ static_flag = false;
+ member_func_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * proxyClassFunctionHandler()
+ *
+ * Function called for creating a Java wrapper function around a c++ function in the
+ * proxy class. Used for both static and non-static C++ class functions.
+ * C++ class static functions map to Java static functions.
+ * Two extra attributes in the Node must be available. These are "proxyfuncname" -
+ * the name of the Java class proxy function, which in turn will call "imfuncname" -
+ * the intermediary (JNI) function name in the intermediary class.
+ * ----------------------------------------------------------------------------- */
+
+ void proxyClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ bool is_interface = GetFlag(parentNode(n), "feature:interface") && !checkAttribute(n, "kind", "variable")
+ && !static_flag && Getattr(n, "interface:owner") == 0;
+
+ if (!proxy_flag)
+ return;
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in directors
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("jtype", l, NULL);
+ Swig_typemap_attach_parms("jstype", l, NULL);
+ Swig_typemap_attach_parms("javain", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
+ // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
+ SwigType *covariant = Getattr(n, "covariant");
+ substituteClassname(covariant ? covariant : t, tm);
+ Printf(return_type, "%s", tm);
+ if (covariant)
+ Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
+ "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0));
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ 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, getClassPrefix(), variable_name))) == 0);
+ }
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n");
+ Printv(function_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ /* Start generating the proxy function */
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s ", methodmods);
+ if (static_flag)
+ Printf(function_code, "static ");
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+
+ if (is_interface)
+ Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
+
+ Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
+ if (!static_flag) {
+ Printf(imcall, "swigCPtr");
+
+ String *this_type = Copy(getClassType());
+ String *name = NewString("jself");
+ String *qualifier = Getattr(n, "qualifier");
+ if (qualifier)
+ SwigType_push(this_type, qualifier);
+ SwigType_add_pointer(this_type);
+ Parm *this_parm = NewParm(this_type, name, n);
+ Swig_typemap_attach_parms("jtype", this_parm, NULL);
+ Swig_typemap_attach_parms("jstype", this_parm, NULL);
+
+ if (prematureGarbageCollectionPreventionParameter(this_type, this_parm))
+ Printf(imcall, ", this");
+
+ Delete(this_parm);
+ Delete(name);
+ Delete(this_type);
+ }
+
+ emit_mark_varargs(l);
+
+ int gencomma = !static_flag;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ /* Ignore the 'this' argument for variable wrappers */
+ if (!(variable_wrapper_flag && i == 0) || static_flag) {
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the Java parameter type */
+ if ((tm = Getattr(p, "tmap:jstype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, setter_flag);
+
+ // Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:javain"))) {
+ addThrows(n, "tmap:javain", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$javainput", arg);
+ String *pre = Getattr(p, "tmap:javain:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$javainput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:javain:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$javainput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma >= 2) {
+ Printf(function_code, ", ");
+ if (is_interface)
+ Printf(interface_class_code, ", ");
+ }
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+ if (is_interface)
+ Printf(interface_class_code, "%s %s", param_type, arg);
+
+ if (prematureGarbageCollectionPreventionParameter(pt, p)) {
+ String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
+ if (pgcppname) {
+ String *argname = Copy(pgcppname);
+ Replaceall(argname, "$javainput", arg);
+ Printf(imcall, ", %s", argname);
+ Delete(argname);
+ } else {
+ Printf(imcall, ", %s", arg);
+ }
+ }
+
+ Delete(arg);
+ Delete(param_type);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
+ if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
+ addThrows(n, "tmap:javaout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ if (is_pre_code || is_post_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+
+ // For director methods: generate code to selectively make a normal polymorphic call or
+ // an explicit method call - needed to prevent infinite recursion calls in director methods.
+ 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(), getClassPrefix(), ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+
+ String *excode = NewString("");
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
+ else
+ Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ Delete(ex_overloaded_name);
+ Delete(excode);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+
+ Replaceall(tm, "$imfuncname", intermediary_function_name);
+ Replaceall(tm, "$jnicall", imcall);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (is_interface) {
+ Printf(interface_class_code, ")");
+ generateThrowsClause(n, interface_class_code);
+ Printf(interface_class_code, ";\n");
+ }
+ generateThrowsClause(n, function_code);
+ Printf(function_code, " %s\n\n", tm ? tm : empty_string);
+ Printv(proxy_class_code, function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ----------------------------------------------------------------------
+ * constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int constructorHandler(Node *n) {
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *function_code = NewString("");
+ String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the javain typemap has code in the pre or post attributes
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *im_return_type = NewString("");
+ bool feature_director = (parentNode(n) && Swig_directorclass(n));
+
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
+ if (Getattr(n, "overload:ignore"))
+ return SWIG_OK;
+
+ if (proxy_flag) {
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
+ String *imcall = NewString("");
+
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
+ Printf(im_return_type, "%s", tm);
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(function_code, "/* This was generated from constructionhandler() */\n");
+ Printv(function_code, Char(doxygen_comments), NIL);
+ Delete(doxygen_comments);
+ }
+
+ Printf(function_code, " %s %s(", methodmods, proxy_class_name);
+ Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
+
+ Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("jtype", l, NULL);
+ Swig_typemap_attach_parms("jstype", l, NULL);
+ Swig_typemap_attach_parms("javain", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; p; i++) {
+
+ /* Ignored varargs */
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ /* Ignored parameters */
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the Java parameter type */
+ if ((tm = Getattr(p, "tmap:jstype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+
+ // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:javain"))) {
+ addThrows(n, "tmap:javain", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$javainput", arg);
+ String *pre = Getattr(p, "tmap:javain:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$javainput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:javain:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$javainput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(function_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ Printf(function_code, "%s %s", param_type, arg);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", arg);
+ ++gencomma;
+
+ if (prematureGarbageCollectionPreventionParameter(pt, p)) {
+ String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
+ if (pgcppname) {
+ String *argname = Copy(pgcppname);
+ Replaceall(argname, "$javainput", arg);
+ Printf(imcall, ", %s", argname);
+ Delete(argname);
+ } else {
+ Printf(imcall, ", %s", arg);
+ }
+ }
+
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(function_code, ")");
+ Printf(helper_code, ")");
+ generateThrowsClause(n, function_code);
+
+ /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
+ Hash *attributes = NewHash();
+ String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
+ String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type,
+ WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
+ if (construct_tm) {
+ if (!feature_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(function_code, " ", construct_tm, "\n", NIL);
+ }
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ if (is_pre_code || is_post_code) {
+ generateThrowsClause(n, helper_code);
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ Printf(helper_code, "\n }\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
+ Printv(proxy_class_code, helper_code, "\n", NIL);
+ Replaceall(function_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(function_code, "$imcall", imcall);
+ }
+
+ Printv(proxy_class_code, function_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(im_return_type);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+
+ if (proxy_flag) {
+ Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
+ generateThrowsClause(n, destructor_throws_clause);
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ if (methodmods)
+ Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
+ }
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberconstantHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getOverloadedName()
+ * ----------------------------------------------------------------------------- */
+
+ String *getOverloadedName(Node *n) {
+
+ /* Although JNI functions are designed to handle overloaded Java functions,
+ * a Java long is used for all classes in the SWIG intermediary class.
+ * The intermediary class methods are thus mangled when overloaded to give
+ * a unique name. */
+ String *overloaded_name = Copy(Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
+ }
+
+ return overloaded_name;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * moduleClassFunctionHandler()
+ * ----------------------------------------------------------------------------- */
+
+ void moduleClassFunctionHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+
+ // Translate and write javadoc comment if flagged
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ String *doxygen_comments = doxygenTranslator->getDocumentation(n, " ");
+ if (comment_creation_chatter)
+ Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n");
+ Printv(function_code, doxygen_comments, NIL);
+ Delete(doxygen_comments);
+ }
+
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("jstype", l, NULL);
+ Swig_typemap_attach_parms("javain", l, NULL);
+
+ /* Get return types */
+ if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
+ substituteClassname(t, tm);
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ /* Change function name for global variables */
+ if (proxy_flag && global_variable_flag) {
+ // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
+ func_name = NewString("");
+ setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
+ if (setter_flag)
+ Printf(func_name, "set");
+ else
+ Printf(func_name, "get");
+ Putc(toupper((int) *Char(variable_name)), func_name);
+ Printf(func_name, "%s", Char(variable_name) + 1);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+ Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
+ Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+
+ bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ /* Get the Java parameter type */
+ if ((tm = Getattr(p, "tmap:jstype"))) {
+ substituteClassname(pt, tm);
+ Printf(param_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, global_or_member_variable);
+
+ // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
+ if ((tm = Getattr(p, "tmap:javain"))) {
+ addThrows(n, "tmap:javain", p);
+ substituteClassname(pt, tm);
+ Replaceall(tm, "$javainput", arg);
+ String *pre = Getattr(p, "tmap:javain:pre");
+ if (pre) {
+ substituteClassname(pt, pre);
+ Replaceall(pre, "$javainput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:javain:post");
+ if (post) {
+ substituteClassname(pt, post);
+ Replaceall(post, "$javainput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ if (prematureGarbageCollectionPreventionParameter(pt, p)) {
+ String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
+ if (pgcppname) {
+ String *argname = Copy(pgcppname);
+ Replaceall(argname, "$javainput", arg);
+ Printf(imcall, ", %s", argname);
+ Delete(argname);
+ } else {
+ Printf(imcall, ", %s", arg);
+ }
+ }
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ")");
+
+ // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class)
+ if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
+ addThrows(n, "tmap:javaout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ if (is_pre_code || is_post_code) {
+ Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ Insert(tm, 0, "{");
+ Printf(tm, "\n }");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ substituteClassname(t, tm);
+ Replaceall(tm, "$imfuncname", overloaded_name);
+ Replaceall(tm, "$jnicall", imcall);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ generateThrowsClause(n, function_code);
+ Printf(function_code, " %s\n\n", tm ? tm : empty_string);
+ Printv(module_class_code, function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *--------------------------------------------------------------------*/
+
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+ substituteClassname(type, tm);
+ }
+
+ /*----------------------------------------------------------------------
+ * decodeEnumFeature()
+ * Decode the possible enum features, which are one of:
+ * %javaenum(simple)
+ * %javaenum(typeunsafe) - default
+ * %javaenum(typesafe)
+ * %javaenum(proper)
+ *--------------------------------------------------------------------*/
+
+ EnumFeature decodeEnumFeature(Node *n) {
+ EnumFeature enum_feature = TypeunsafeEnum;
+ String *feature = Getattr(n, "feature:java:enum");
+ if (feature) {
+ if (Cmp(feature, "simple") == 0)
+ enum_feature = SimpleEnum;
+ else if (Cmp(feature, "typesafe") == 0)
+ enum_feature = TypesafeEnum;
+ else if (Cmp(feature, "proper") == 0)
+ enum_feature = ProperEnum;
+ }
+ return enum_feature;
+ }
+
+ /* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in Java generated
+ * code. If the %javaconst feature is not used, the string will contain the intermediary
+ * class call to obtain the enum value. The intermediary class and JNI methods to obtain
+ * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
+ * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20};
+ * The %javaconstvalue feature overrides all other ways to generate the constant value.
+ * The caller must delete memory allocated for the returned string.
+ * ------------------------------------------------------------------------ */
+
+ String *enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ // Check for the %javaconstvalue feature
+ String *value = Getattr(n, "feature:java:constvalue");
+
+ if (!value) {
+ // The %javaconst feature determines how the constant value is obtained
+ int const_feature_flag = GetFlag(n, "feature:java:const");
+
+ if (const_feature_flag) {
+ // Use the C syntax to make a true Java constant and hope that it compiles as Java code
+ value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
+ } else {
+ String *newsymname = 0;
+ if (!getCurrentClass() || !proxy_flag) {
+ String *enumClassPrefix = getEnumClassPrefix();
+ if (enumClassPrefix) {
+ // A global scoped enum
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ symname = newsymname;
+ }
+ }
+
+ // Get the enumvalue from a JNI call
+ if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
+ constantWrapper(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
+ } else {
+ memberconstantHandler(n);
+ value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
+ }
+ Delete(newsymname);
+ }
+ }
+ return value;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getEnumName()
+ *
+ * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
+ * and the package is also not added to the name.
+ * ----------------------------------------------------------------------------- */
+
+ String *getEnumName(SwigType *t, bool jnidescriptor) {
+ Node *enumname = NULL;
+ Node *n = enumLookup(t);
+ if (n) {
+ enumname = Getattr(n, "enumname");
+ if (!enumname || jnidescriptor) {
+ String *symname = Getattr(n, "sym:name");
+ if (symname) {
+ // Add in class scope when referencing enum if not a global enum
+ String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
+ String *proxyname = 0;
+ if (scopename_prefix) {
+ proxyname = getProxyName(scopename_prefix, jnidescriptor);
+ }
+ if (proxyname) {
+ const char *class_separator = jnidescriptor ? "$" : ".";
+ enumname = NewStringf("%s%s%s", proxyname, class_separator, symname);
+ } else {
+ // global enum or enum in a namespace
+ String *nspace = Getattr(n, "sym:nspace");
+ if (nspace) {
+ if (package && !jnidescriptor)
+ enumname = NewStringf("%s.%s.%s", package, nspace, symname);
+ else
+ enumname = NewStringf("%s.%s", nspace, symname);
+ } else {
+ enumname = Copy(symname);
+ }
+ }
+ if (!jnidescriptor) {
+ Setattr(n, "enumname", enumname); // Cache it
+ Delete(enumname);
+ }
+ Delete(scopename_prefix);
+ }
+ }
+ }
+
+ return enumname;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassname()
+ *
+ * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions
+ * that SWIG knows about. Also substitutes enums with enum name.
+ * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
+ * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
+ * Note that the path separator is a '.' unless jnidescriptor is set.
+ * Inputs:
+ * pt - parameter type
+ * tm - typemap contents that might contain the special variable to be replaced
+ * jnidescriptor - if set, inner class names are separated with '$' otherwise a '/' is used for the path separator
+ * Outputs:
+ * tm - typemap contents complete with the special variable substitution
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * ----------------------------------------------------------------------------- */
+
+ bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$javaclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*javaclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ if (Len(classnametype) > 0) {
+ substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor);
+ substitution_performed = true;
+ }
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&javaclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$javainterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$javainterfacename", jnidescriptor, true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*javainterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*javainterfacename", jnidescriptor, true);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&javainterfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&javainterfacename", jnidescriptor, true);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", jnidescriptor, false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$*interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ Delete(SwigType_pop(interfacenametype));
+ if (Len(interfacenametype) > 0) {
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", jnidescriptor, false);
+ substitution_performed = true;
+ }
+ Delete(interfacenametype);
+ }
+ if (Strstr(tm, "$&interfacename")) {
+ SwigType *interfacenametype = Copy(strippedtype);
+ SwigType_add_pointer(interfacenametype);
+ substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", jnidescriptor, false);
+ substitution_performed = true;
+ Delete(interfacenametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteClassnameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
+ String *replacementname;
+
+ if (SwigType_isenum(classnametype)) {
+ String *enumname = getEnumName(classnametype, jnidescriptor);
+ if (enumname) {
+ replacementname = Copy(enumname);
+ } else {
+ bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
+ if (anonymous_enum) {
+ replacementname = NewString("int");
+ } else {
+ // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+ Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ } else {
+ String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too
+ if (classname) {
+ replacementname = Copy(classname);
+ } else {
+ // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
+ replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
+
+ // Add to hash table so that the type wrapper classes can be created later
+ Setattr(swig_types_hash, replacementname, classnametype);
+ }
+ }
+ if (jnidescriptor)
+ Replaceall(replacementname,".","/");
+ Replaceall(tm, classnamespecialvariable, replacementname);
+
+ Delete(replacementname);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substituteInterfacenameSpecialVariable()
+ * ----------------------------------------------------------------------------- */
+
+ void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool jnidescriptor, bool qualified) {
+
+ String *interfacename = getInterfaceName(interfacenametype/*, jnidescriptor*/, qualified);
+ if (interfacename) {
+ String *replacementname = Copy(interfacename);
+
+ if (jnidescriptor)
+ Replaceall(replacementname,".","/");
+ Replaceall(tm, interfacenamespecialvariable, replacementname);
+
+ Delete(replacementname);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * emitTypeWrapperClass()
+ * ----------------------------------------------------------------------------- */
+
+ void emitTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ String *swigtype = NewString("");
+ String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname);
+ File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
+ if (!f_swigtype) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the type wrapper class file
+ emitBanner(f_swigtype);
+
+ if (package)
+ Printf(f_swigtype, "package %s;\n", package);
+
+ // Pure Java baseclass and interfaces
+ const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE);
+ const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE);
+
+ // Emit the class
+ Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE), // Import statements
+ "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
+ " $javaclassname", // Class name and bases
+ *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
+ " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
+ typemapLookup(n, "javacode", type, WARN_NONE), // extra Java code
+ "}\n", "\n", NIL);
+
+ Replaceall(swigtype, "$javaclassname", classname);
+ Replaceall(swigtype, "$module", module_class_name);
+ Replaceall(swigtype, "$imclassname", imclass_name);
+
+ // For unknown enums
+ Replaceall(swigtype, "$static ", "");
+ Replaceall(swigtype, "$enumvalues", "");
+
+ Printv(f_swigtype, swigtype, NIL);
+
+ Delete(f_swigtype);
+ Delete(swigtype);
+ Delete(n);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * typemapLookup()
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * ----------------------------------------------------------------------------- */
+
+ const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE)
+ Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ if (!typemap_attributes)
+ Delete(node);
+ return tm;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addThrows()
+ *
+ * Adds exception classes to a throws list. The throws list is the list of classes
+ * that will form the Java throws clause. Mainly for checked exceptions.
+ * ----------------------------------------------------------------------------- */
+
+ void addThrows(Node *n, const String *attribute, Node *parameter) {
+ // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute
+ String *throws_attribute = NewStringf("%s:throws", attribute);
+ String *throws = Getattr(parameter, throws_attribute);
+
+ if (throws && Len(throws) > 0) {
+ String *throws_list = Getattr(n, "java:throwslist");
+ if (!throws_list) {
+ throws_list = NewList();
+ Setattr(n, "java:throwslist", throws_list);
+ }
+ // Put the exception classes in the throws clause into a temporary List
+ List *temp_classes_list = Split(throws, ',', INT_MAX);
+
+ // Add the exception classes to the node throws list, but don't duplicate if already in list
+ if (temp_classes_list && Len(temp_classes_list) > 0) {
+ for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
+ String *exception_class = NewString(cls.item);
+ Replaceall(exception_class, " ", ""); // remove spaces
+ Replaceall(exception_class, "\t", ""); // remove tabs
+ if (Len(exception_class) > 0) {
+ // $javaclassname substitution
+ SwigType *pt = Getattr(parameter, "type");
+ substituteClassname(pt, exception_class);
+
+ // Don't duplicate the Java exception class in the throws clause
+ bool found_flag = false;
+ for (Iterator item = First(throws_list); item.item; item = Next(item)) {
+ if (Strcmp(item.item, exception_class) == 0)
+ found_flag = true;
+ }
+ if (!found_flag)
+ Append(throws_list, exception_class);
+ }
+ Delete(exception_class);
+ }
+ }
+ Delete(temp_classes_list);
+ }
+ Delete(throws_attribute);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * generateThrowsClause()
+ *
+ * Generates throws clause for checked exception
+ * ----------------------------------------------------------------------------- */
+
+ void generateThrowsClause(Node *n, String *code) {
+ // Add the throws clause into code
+ List *throws_list = Getattr(n, "java:throwslist");
+ if (throws_list) {
+ Iterator cls = First(throws_list);
+ Printf(code, " throws %s", cls.item);
+ while ((cls = Next(cls)).item)
+ Printf(code, ", %s", cls.item);
+ }
+ }
+
+ /* -----------------------------------------------------------------------------
+ * prematureGarbageCollectionPreventionParameter()
+ *
+ * Get the proxy class name for use in an additional generated parameter. The
+ * additional parameter is added to a native method call purely to prevent
+ * premature garbage collection of proxy classes which pass their C++ class pointer
+ * in a Java long to the JNI layer.
+ * ----------------------------------------------------------------------------- */
+
+ String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
+ String *pgcpp_java_type = 0;
+ String *jtype = NewString(Getattr(p, "tmap:jtype"));
+
+ // Strip C comments
+ String *stripped_jtype = Swig_strip_c_comments(jtype);
+ if (stripped_jtype) {
+ Delete(jtype);
+ jtype = stripped_jtype;
+ }
+
+ // Remove whitespace
+ Replaceall(jtype, " ", "");
+ Replaceall(jtype, "\t", "");
+
+ if (Cmp(jtype, "long") == 0) {
+ if (proxy_flag) {
+ if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
+ String *interface_name = getInterfaceName(t, true);
+ pgcpp_java_type = interface_name ? interface_name : getProxyName(t);
+ if (!pgcpp_java_type) {
+ // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
+ String *jstype = NewString(Getattr(p, "tmap:jstype"));
+ if (jstype) {
+ Hash *classes = getClassHash();
+ if (classes) {
+ // Strip C comments
+ String *stripped_jstype = Swig_strip_c_comments(jstype);
+ if (stripped_jstype) {
+ Delete(jstype);
+ jstype = stripped_jstype;
+ }
+ // Remove whitespace
+ Replaceall(jstype, " ", "");
+ Replaceall(jstype, "\t", "");
+
+ Iterator ki;
+ for (ki = First(classes); ki.key; ki = Next(ki)) {
+ Node *cls = ki.item;
+ if (cls && !Getattr(cls, "feature:ignore")) {
+ String *symname = Getattr(cls, "sym:name");
+ if (symname && Strcmp(symname, jstype) == 0) {
+ pgcpp_java_type = symname;
+ }
+ }
+ }
+ }
+ }
+ Delete(jstype);
+ }
+ }
+ }
+ }
+ Delete(jtype);
+ return pgcpp_java_type;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * outputDirectory()
+ *
+ * Return the directory to use for generating Java classes/enums and create the
+ * subdirectory (does not create if language specific outdir does not exist).
+ * ----------------------------------------------------------------------------- */
+
+ String *outputDirectory(String *nspace) {
+ String *output_directory = Copy(SWIG_output_directory());
+ if (nspace) {
+ String *nspace_subdirectory = Copy(nspace);
+ Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
+ String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
+ if (newdir_error) {
+ Printf(stderr, "%s\n", newdir_error);
+ Delete(newdir_error);
+ Exit(EXIT_FAILURE);
+ }
+ Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
+ Delete(nspace_subdirectory);
+ }
+ return output_directory;
+ }
+
+ /*----------------------------------------------------------------------
+ * Start of director methods
+ *--------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------
+ * getUpcallJNIMethod()
+ *--------------------------------------------------------------------*/
+
+ String *getUpcallJNIMethod(String *descrip) {
+ static struct {
+ char code;
+ const char *method;
+ } upcall_methods[] = {
+ {
+ 'B', "CallStaticByteMethod"}, {
+ 'C', "CallStaticCharMethod"}, {
+ 'D', "CallStaticDoubleMethod"}, {
+ 'F', "CallStaticFloatMethod"}, {
+ 'I', "CallStaticIntMethod"}, {
+ 'J', "CallStaticLongMethod"}, {
+ 'L', "CallStaticObjectMethod"}, {
+ 'S', "CallStaticShortMethod"}, {
+ 'V', "CallStaticVoidMethod"}, {
+ 'Z', "CallStaticBooleanMethod"}, {
+ '[', "CallStaticObjectMethod"}
+ };
+
+ char code;
+ int i;
+
+ code = *Char(descrip);
+ for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i)
+ if (code == upcall_methods[i].code)
+ return NewString(upcall_methods[i].method);
+ return NULL;
+ }
+
+ /*----------------------------------------------------------------------
+ * emitDirectorUpcalls()
+ *--------------------------------------------------------------------*/
+
+ void emitDirectorUpcalls() {
+ if (n_dmethods) {
+ Wrapper *w = NewWrapper();
+ String *jni_imclass_name = makeValidJniName(imclass_name);
+ String *swig_module_init = NewString("swig_module_init");
+ String *swig_module_init_jni = makeValidJniName(swig_module_init);
+ String *dmethod_data = NewString("");
+ int n_methods = 0;
+ Iterator udata_iter;
+
+ udata_iter = First(dmethods_seq);
+ while (udata_iter.item) {
+ UpcallData *udata = udata_iter.item;
+ Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
+ ++n_methods;
+
+ udata_iter = Next(udata_iter);
+
+ if (udata_iter.item)
+ Putc(',', dmethod_data);
+ Putc('\n', dmethod_data);
+ }
+
+ Printf(f_runtime, "namespace Swig {\n");
+ Printf(f_runtime, " namespace {\n");
+ Printf(f_runtime, " jclass jclass_%s = NULL;\n", imclass_name);
+ Printf(f_runtime, " jmethodID director_method_ids[%d];\n", n_methods);
+ Printf(f_runtime, " }\n");
+ Printf(f_runtime, "}\n");
+
+ Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
+ Printf(w->code, "static struct {\n");
+ Printf(w->code, " const char *method;\n");
+ Printf(w->code, " const char *signature;\n");
+ Printf(w->code, "} methods[%d] = {\n", n_methods);
+ Printv(w->code, dmethod_data, NIL);
+ Printf(w->code, "};\n");
+
+ Wrapper_add_local(w, "i", "int i");
+
+ Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name);
+ Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name);
+ Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n");
+ Printf(w->code, " Swig::director_method_ids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
+ Printf(w->code, " if (!Swig::director_method_ids[i]) return;\n");
+ Printf(w->code, "}\n");
+
+ Printf(w->code, "}\n");
+
+ Wrapper_print(w, f_wrappers);
+ Delete(dmethod_data);
+ Delete(swig_module_init_jni);
+ Delete(swig_module_init);
+ Delete(jni_imclass_name);
+ DelWrapper(w);
+ }
+ }
+
+ /*----------------------------------------------------------------------
+ * emitDirectorExtraMethods()
+ *
+ * This is where the director connect method is generated.
+ *--------------------------------------------------------------------*/
+ void emitDirectorExtraMethods(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // 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(), getClassPrefix(), "director_connect");
+ String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
+ SwigType *smart = Getattr(n, "smart");
+ String *smartptr = smart ? SwigType_namestr(smart) : 0;
+ String *dirClassName = directorClassName(n);
+ Wrapper *code_wrap;
+
+ Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n",
+ swig_director_connect, full_proxy_class_name);
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def,
+ "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, "
+ "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni);
+
+ if (smartptr) {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
+ Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
+ }
+ else {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
+ }
+
+ Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
+ "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(swig_director_connect_jni);
+ Delete(swig_director_connect);
+
+ // Output the swigReleaseOwnership, swigTakeOwnership methods:
+ 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);
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def,
+ "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
+ jnipackage, jni_imclass_name, changeown_jnimethod_name);
+
+ if (smartptr) {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
+ Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
+ Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
+ Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
+ } else {
+ Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
+ Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
+ }
+
+ Printf(code_wrap->code, " (void)jcls;\n");
+ Printf(code_wrap->code, " if (director) {\n");
+ Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
+ Printf(code_wrap->code, " }\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(changeown_method_name);
+ Delete(changeown_jnimethod_name);
+ Delete(norm_name);
+ Delete(dirClassName);
+ Delete(jni_imclass_name);
+ }
+
+ /*----------------------------------------------------------------------
+ * emitCodeTypemap()
+ *
+ * Output a code typemap that uses $methodname and $jnicall, as used
+ * in the directordisconnect, director_release and director_take
+ * typemaps.
+ *--------------------------------------------------------------------*/
+
+ void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) {
+ const String *tm = NULL;
+ Node *tmattrs = NewHash();
+ String *lookup_tmname = NewString(typemap);
+ String *method_attr_name;
+ String *method_attr;
+
+ if (derived) {
+ Append(lookup_tmname, "_derived");
+ }
+
+ tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs);
+ method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname);
+ method_attr = Getattr(tmattrs, method_attr_name);
+
+ if (*Char(tm)) {
+ if (method_attr) {
+ String *codebody = Copy(tm);
+ Replaceall(codebody, "$methodname", method_attr);
+ Replaceall(codebody, "$jnicall", jnicall);
+ Append(proxy_class_def, codebody);
+ Delete(codebody);
+ } else {
+ Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name);
+ }
+ } else {
+ Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name);
+ }
+
+ Delete(tmattrs);
+ Delete(lookup_tmname);
+ // Delete(method_attr);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * substitutePackagePath()
+ *
+ * Replace $packagepath using the javapackage typemap associated with passed
+ * parm or global package if p is 0. "$packagepath/" is replaced with "" if
+ * no package is set. Note that the path separator is a '/'.
+ * ----------------------------------------------------------------------------- */
+
+ void substitutePackagePath(String *text, Parm *p) {
+ String *pkg_path= 0;
+
+ if (p)
+ pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
+ if (!pkg_path || Len(pkg_path) == 0)
+ pkg_path = Copy(package_path);
+
+ if (Len(pkg_path) > 0) {
+ Replaceall(pkg_path, ".", "/");
+ Replaceall(text, "$packagepath", pkg_path);
+ } else {
+ Replaceall(text, "$packagepath/", empty_string);
+ Replaceall(text, "$packagepath", empty_string);
+ }
+ Delete(pkg_path);
+ }
+
+ /* ---------------------------------------------------------------
+ * Canonicalize the JNI field descriptor
+ *
+ * Replace the $packagepath and $javaclassname family of special
+ * variables with the desired package and Java proxy name as
+ * required in the JNI field descriptors.
+ *
+ * !!SFM!! If $packagepath occurs in the field descriptor, but
+ * package_path isn't set (length == 0), then strip it and the
+ * optional trailing '/' from the resulting name.
+ *
+ * --------------------------------------------------------------- */
+
+ String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) {
+ SwigType *type = Getattr(p, "type");
+ String *descriptor_out = Copy(descriptor_in);
+
+ substituteClassname(type, descriptor_out, true);
+ substitutePackagePath(descriptor_out, p);
+
+ return descriptor_out;
+ }
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Java object.
+ *
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *overloaded_name = 0;
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = 0;
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = directorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ String *jnidesc = NewString("");
+ String *classdesc = NewString("");
+ String *jniret_desc = NewString("");
+ String *classret_desc = NewString("");
+ SwigType *c_ret_type = NULL;
+ String *jupcall_args = NewString("swigjobj");
+ String *imclass_dmethod = 0;
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ int classmeth_off = curr_class_dmethod - first_class_dmethod;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+ String *qualified_classname = getProxyName(getClassName());
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ if (!ignored_method) {
+ overloaded_name = getOverloadedName(n);
+ imclass_dmethod = Swig_name_member(getNSpace(), dirclassname, overloaded_name);
+ }
+
+
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a Java exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ SwigType *noref_type = SwigType_del_reference(Copy(returntype));
+ String *noref_ltype = SwigType_lstr(noref_type, 0);
+ String *return_ltype = SwigType_lstr(returntype, 0);
+
+ Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
+ Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
+ Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
+ Printf(w->code, "c_result = &result_default;\n");
+ Delete(return_ltype);
+ Delete(noref_ltype);
+ Delete(noref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ if (!ignored_method) {
+ /* Create the intermediate class wrapper */
+ tm = Swig_typemap_lookup("jtype", n, "", 0);
+ if (tm) {
+ Printf(callback_def, " public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+ }
+
+ String *cdesc = NULL;
+ SwigType *covariant = Getattr(n, "covariant");
+ SwigType *adjustedreturntype = covariant ? covariant : returntype;
+ Parm *adjustedreturntypeparm = NewParmNode(adjustedreturntype, n);
+
+ if (Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0)
+ && (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) {
+
+ // Note that in the case of polymorphic (covariant) return types, the
+ // method's return type is changed to be the base of the C++ return
+ // type
+ String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm);
+ Append(classret_desc, jnidesc_canon);
+ Delete(jnidesc_canon);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ /* Get the JNI field descriptor for this return type, add the JNI field descriptor
+ to jniret_desc */
+ if ((c_ret_type = Swig_typemap_lookup("jni", n, "", 0))) {
+ Parm *tp = NewParmNode(c_ret_type, n);
+
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+
+ String *jdesc = NULL;
+ if (Swig_typemap_lookup("directorin", tp, "", 0)
+ && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
+
+ // Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this
+ // We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
+ if (GetFlag(tp, "tmap:directorin:nouse"))
+ jdesc = cdesc;
+ String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp);
+ Append(jniret_desc, jnidesc_canon);
+ Delete(jnidesc_canon);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(tp);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(adjustedreturntypeparm);
+
+ Swig_director_parms_fixup(l);
+
+ /* Attach the standard typemaps */
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("jni", l, 0);
+ Swig_typemap_attach_parms("jtype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("javadirectorin", l, 0);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ if (!ignored_method) {
+ /* Add Java environment pointer to wrapper */
+ String *jenvstr = NewString("jenv");
+ String *jobjstr = NewString("swigjobj");
+
+ Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL);
+ Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL);
+ Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL);
+ Delete(jenvstr);
+ Delete(jobjstr);
+
+ /* Preamble code */
+ Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off);
+ }
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, ");
+ Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+
+ /* Make sure that we return something in the case of a pure
+ * virtual method call for syntactical reasons. */
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ else if (!ignored_method)
+ Printf(w->code, "return;\n");
+ }
+
+ if (!ignored_method) {
+ Printf(w->code, "}\n");
+ Printf(w->code, "swigjobj = swig_get_self(jenv);\n");
+ Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n");
+ }
+
+ /* Start the Java field descriptor for the intermediate class's upcall (insert jself object) */
+ Parm *tp = NewParmNode(c_classname, n);
+ String *jdesc;
+
+ if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
+ && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
+ String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
+ Append(jnidesc, jni_canon);
+ Delete(jni_canon);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap for type %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(tp);
+
+ /* Go through argument list, convert from native to Java */
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Add various typemap's 'throws' clauses */
+ addThrows(n, "tmap:directorin", p);
+ addThrows(n, "tmap:out", p);
+
+ /* And add to the upcall args */
+ Printf(jupcall_args, ", %s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = Getattr(p, "tmap:jni"))) {
+ Parm *tp = NewParm(c_param_type, Getattr(p, "name"), n);
+ String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL;
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
+
+ /* Add input marshalling code and update JNI field descriptor */
+ if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
+ && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))
+ && (tm = Getattr(p, "tmap:directorin"))
+ && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) {
+
+ // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type -
+ // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
+ if (GetFlag(tp, "tmap:directorin:nouse"))
+ jdesc = cdesc;
+ String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
+ Append(jnidesc, jni_canon);
+ Delete(jni_canon);
+
+ Setattr(p, "emit:directorinput", arg);
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = Getattr(p, "tmap:jtype"))) {
+ String *din = Copy(Getattr(p, "tmap:javadirectorin"));
+ addThrows(n, "tmap:javadirectorin", p);
+
+ if (din) {
+ Replaceall(din, "$module", module_class_name);
+ Replaceall(din, "$imclassname", imclass_name);
+ substituteClassname(pt, din);
+ Replaceall(din, "$jniinput", ln);
+
+ if (i > 0)
+ Printf(imcall_args, ", ");
+ Printf(callback_def, ", %s %s", tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else
+ Printv(imcall_args, ln, NIL);
+
+ jni_canon = canonicalizeJNIDescriptor(cdesc, p);
+ Append(classdesc, jni_canon);
+ Delete(jni_canon);
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+
+ Delete(desc_tm);
+ } else {
+ if (!desc_tm) {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ } else if (!jdesc) {
+ Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
+ "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = Getattr(p, "tmap:directorin:next");
+ } else if (!tm) {
+ Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ } else if (!cdesc) {
+ Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
+ "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ output_director = false;
+ }
+
+ } else {
+ Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(arg);
+ Delete(c_decl);
+ Delete(ln);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ // Get any Java exception classes in the throws typemap
+ ParmList *throw_parm_list = NULL;
+
+ // May need to add Java throws clause to director methods if %catches defined
+ // Get any Java exception classes in the throws typemap
+ ParmList *catches_list = Getattr(n, "catchlist");
+ if (catches_list) {
+ Swig_typemap_attach_parms("throws", catches_list, 0);
+ Swig_typemap_attach_parms("directorthrows", catches_list, 0);
+ for (p = catches_list; p; p = nextSibling(p)) {
+ addThrows(n, "tmap:throws", p);
+ }
+ }
+
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ Swig_typemap_attach_parms("directorthrows", throw_parm_list, 0);
+ }
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ // %catches replaces the specified exception specification
+ if (!catches_list) {
+ addThrows(n, "tmap:throws", p);
+ }
+
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("jself.%s(%s)", symname, imcall_args);
+
+ // Handle exception classes specified in the "except" feature's "throws" attribute
+ addThrows(n, "feature:except", n);
+
+ if (!is_void) {
+ if ((tm = Swig_typemap_lookup("javadirectorout", n, "", 0))) {
+ addThrows(n, "tmap:javadirectorout", n);
+ substituteClassname(returntype, tm);
+ Replaceall(tm, "$javacall", upcall);
+
+ Printf(callback_code, " return %s;\n", tm);
+ }
+
+ if ((tm = Swig_typemap_lookup("out", n, "", 0)))
+ addThrows(n, "tmap:out", n);
+
+ Delete(tm);
+ } else
+ Printf(callback_code, " %s;\n", upcall);
+
+ Printf(callback_code, " }\n");
+ Delete(upcall);
+
+ /* Finish off the inherited upcall's definition */
+ Putc(')', callback_def);
+ generateThrowsClause(n, callback_def);
+ Printf(callback_def, " {\n");
+
+ if (!ignored_method) {
+ /* Emit the actual upcall through */
+ String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);
+ String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc);
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl);
+ String *methid = Getattr(udata, "imclass_methodidx");
+ String *methop = getUpcallJNIMethod(jniret_desc);
+
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
+
+ // Generate code to handle any Java exception thrown by director delegation
+ directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+
+ /* Copy jresult into c_result... */
+ if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
+ addThrows(n, "tmap:directorout", n);
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ addThrows(n, "tmap:directorargout", p);
+ Replaceall(tm, "$result", makeParameterName(n, p, i, false));
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(imclass_desc);
+ Delete(class_desc);
+
+ /* Terminate wrapper code */
+ Printf(w->code, "} else {\n");
+ Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object in %s::%s \");\n",
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ Printf(w->code, "}\n");
+
+ Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n");
+
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!GetFlag(n, "feature:ignore"))
+ Printv(imclass_directors, callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ Delete(inline_extra_method);
+ Delete(qualified_return);
+ Delete(jnidesc);
+ Delete(c_ret_type);
+ Delete(jniret_desc);
+ Delete(declaration);
+ Delete(callback_def);
+ Delete(callback_code);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ------------------------------------------------------------
+ * directorExceptHandler()
+ *
+ * Emit code to map Java exceptions back to C++ exceptions when
+ * feature("director:except") is applied to a method node.
+ * This is generated after the Java method upcall.
+ * ------------------------------------------------------------ */
+
+ void directorExceptHandler(Node *n, ParmList *throw_parm_list, Wrapper *w) {
+
+ String *directorexcept = Getattr(n, "feature:director:except");
+ if (!directorexcept) {
+ directorexcept = NewString("");
+ Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n");
+ Printf(directorexcept, "if ($error) {");
+ Printf(directorexcept, "$directorthrowshandlers\n");
+ Printf(directorexcept, " Swig::DirectorException::raise(jenv, $error);\n");
+ Printf(directorexcept, "}\n");
+ } else {
+ directorexcept = Copy(directorexcept);
+ }
+
+ // Can explicitly disable director:except by setting to "" or "0"
+ if (Len(directorexcept) > 0 && Cmp(directorexcept, "0") != 0) {
+
+ // Replace $packagepath
+ substitutePackagePath(directorexcept, 0);
+
+ // Replace $directorthrowshandlers with any defined typemap handlers (or nothing)
+ if (Strstr(directorexcept, "$directorthrowshandlers")) {
+ String *directorthrowshandlers_code = NewString("");
+
+ for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
+ String *tm = Getattr(p, "tmap:directorthrows");
+
+ if (tm) {
+ // replace $packagepath/$javaclassname
+ String *directorthrows = canonicalizeJNIDescriptor(tm, p);
+ Printv(directorthrowshandlers_code, directorthrows, NIL);
+ Delete(directorthrows);
+ } else {
+ String *t = Getattr(p,"type");
+ Swig_warning(WARN_TYPEMAP_DIRECTORTHROWS_UNDEF, Getfile(n), Getline(n), "No directorthrows typemap defined for %s\n", SwigType_str(t, 0));
+ }
+ }
+ Replaceall(directorexcept, "$directorthrowshandlers", directorthrowshandlers_code);
+ Delete(directorthrowshandlers_code);
+ }
+
+ Replaceall(directorexcept, "$error", "swigerror");
+ Printf(w->code, " %s\n", directorexcept);
+ }
+ Delete(directorexcept);
+ }
+
+ /* ------------------------------------------------------------
+ * directorPrefixArgs()
+ * ------------------------------------------------------------ */
+
+ void directorPrefixArgs(Node *n) {
+ Parm *p;
+
+ /* Need to prepend 'jenv' to the director constructor's argument list */
+
+ String *jenv_type = NewString("JNIEnv");
+
+ SwigType_add_pointer(jenv_type);
+
+ p = NewParm(jenv_type, NewString("jenv"), n);
+ Setattr(p, "arg:byname", "1");
+ set_nextSibling(p, NULL);
+
+ Setattr(n, "director:prefix_args", p);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *dirclassname = directorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ /* insert jenv prefix argument */
+ parms = CopyParmList(superparms);
+
+ String *jenv_type = NewString("JNIEnv");
+ SwigType_add_pointer(jenv_type);
+ p = NewParm(jenv_type, NewString("jenv"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ directorPrefixArgs(n);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 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, "}\n\n");
+
+ Delete(classtype);
+ Delete(target);
+ Delete(call);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(jenv_type);
+ Delete(parms);
+ Delete(dirclassname);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ String *dirClassName = directorClassName(n);
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "%s::%s(JNIEnv *jenv) : %s {", dirClassName, dirClassName, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " %s(JNIEnv *jenv);\n", dirClassName);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(classname);
+ Delete(dirClassName);
+ directorPrefixArgs(n);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorInit()
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ Delete(none_comparison);
+ none_comparison = NewString(""); // not used
+
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ directorDeclaration(n);
+
+ Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
+ Printf(f_directors_h, "\npublic:\n");
+ Printf(f_directors_h, " void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n");
+
+ /* Keep track of the director methods for this class */
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ return Language::classDirectorInit(n);
+ }
+
+ /* ----------------------------------------------------------------------
+ * classDirectorDestructor()
+ * ---------------------------------------------------------------------- */
+
+ int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *full_classname = Getattr(current_class, "name");
+ String *classname = Swig_class_name(current_class);
+ String *dirClassName = directorClassName(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", dirClassName);
+ Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", dirClassName);
+ Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", dirClassName);
+ Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName);
+ }
+
+ /* Ensure that correct directordisconnect typemap's method name is called
+ * here: */
+
+ Node *disconn_attr = NewHash();
+ String *disconn_methodname = NULL;
+
+ typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
+ disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
+
+ Printv(w->code, " swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(disconn_attr);
+ Delete(classname);
+ Delete(dirClassName);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ String *full_classname = Getattr(n, "name");
+ String *classname = getProxyName(full_classname, true);
+ String *director_classname = directorClassName(n);
+ String *internal_classname;
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(package_path) > 0)
+ internal_classname = NewStringf("%s/%s", package_path, classname);
+ else
+ internal_classname = NewStringf("%s", classname);
+
+ // If the namespace is multiple levels, the result of getNSpace() will have inserted
+ // .'s to delimit namespaces, so we need to replace those with /'s
+ Replace(internal_classname, NSPACE_SEPARATOR, "/", DOH_REPLACE_ANY);
+
+ Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname);
+
+ Printf(w->def, "static jclass baseclass = swig_new_global_ref(jenv, \"%s\");\n", internal_classname);
+ Printf(w->def, "if (!baseclass) return;\n");
+
+ if (first_class_dmethod != curr_class_dmethod) {
+ Printf(w->def, "static SwigDirectorMethod methods[] = {\n");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+
+ Printf(w->def, "SwigDirectorMethod(jenv, baseclass, \"%s\", \"%s\")", Getattr(udata, "method"), Getattr(udata, "fdesc"));
+ if (i != curr_class_dmethod - 1)
+ Putc(',', w->def);
+ Putc('\n', w->def);
+ }
+
+ Printf(w->def, "};");
+ }
+
+ Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n");
+
+ int n_methods = curr_class_dmethod - first_class_dmethod;
+
+ if (n_methods) {
+ /* Emit the swig_overrides() method and the swig_override array */
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_overrides(int n) {\n");
+ Printf(f_directors_h, " return (n < %d ? swig_override[n] : false);\n", n_methods);
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "protected:\n");
+ Printf(f_directors_h, " Swig::BoolArray<%d> swig_override;\n", n_methods);
+
+ /* Emit the code to look up the class's methods, initialize the override array */
+
+ Printf(w->code, " bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n");
+ Printf(w->code, " for (int i = 0; i < %d; ++i) {\n", n_methods);
+ // Generally, derived classes have a mix of overridden and
+ // non-overridden methods and it is worth making a GetMethodID
+ // check during initialization to determine if each method is
+ // overridden, thus avoiding unnecessary calls into Java.
+ //
+ // On the other hand, when derived classes are
+ // expected to override all director methods then the
+ // GetMethodID calls are inefficient, and it is better to let
+ // the director unconditionally call up into Java. The resulting code
+ // will still behave correctly (though less efficiently) when Java
+ // code doesn't override a given method.
+ //
+ // The assumeoverride feature on a director controls whether or not
+ // overrides are assumed.
+ if (GetFlag(n, "feature:director:assumeoverride")) {
+ Printf(w->code, " swig_override[i] = derived;\n");
+ } else {
+ Printf(w->code, " swig_override[i] = false;\n");
+ Printf(w->code, " if (derived) {\n");
+ Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].name, methods[i].desc);\n");
+ Printf(w->code, " swig_override[i] = methods[i].methid && (methid != methods[i].methid);\n");
+ Printf(w->code, " jenv->ExceptionClear();\n");
+ Printf(w->code, " }\n");
+ }
+ Printf(w->code, "}\n");
+ } else {
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_overrides(int n) {\n");
+ Printf(f_directors_h, " return false;\n");
+ Printf(f_directors_h, " }\n");
+ }
+
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n");
+ Printf(w->code, "}\n");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(internal_classname);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* --------------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------------*/
+
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /*----------------------------------------------------------------------
+ * extraDirectorProtectedCPPMethodsRequired()
+ *--------------------------------------------------------------------*/
+
+ bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+ /*----------------------------------------------------------------------
+ * directorDeclaration()
+ *
+ * Generate the director class's declaration
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *--------------------------------------------------------------------*/
+
+ void directorDeclaration(Node *n) {
+ String *base = Getattr(n, "classtype");
+ String *class_ctor = NewString("Swig::Director(jenv)");
+
+ String *directorname = directorClassName(n);
+ String *declaration = Swig_class_declaration(n, directorname);
+
+ Printf(declaration, " : public %s, public Swig::Director", base);
+
+ // Stash stuff for later.
+ Setattr(n, "director:decl", declaration);
+ Setattr(n, "director:ctor", class_ctor);
+ }
+
+ /*----------------------------------------------------------------------
+ * nestedClassesSupport()
+ *--------------------------------------------------------------------*/
+
+ NestedClassSupport nestedClassesSupport() const {
+ return NCS_Full;
+ }
+}; /* class JAVA */
+
+/* -----------------------------------------------------------------------------
+ * swig_java() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_java() {
+ return new JAVA();
+}
+extern "C" Language *swig_java(void) {
+ return new_swig_java();
+}
+
+/* -----------------------------------------------------------------------------
+ * Static member variables
+ * ----------------------------------------------------------------------------- */
+
+const char *JAVA::usage = "\
+Java Options (available with -java)\n\
+ -doxygen - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\
+ -debug-doxygen-parser - Display doxygen parser module debugging information\n\
+ -debug-doxygen-translator - Display doxygen translator module debugging information\n\
+ -nopgcpp - Suppress premature garbage collection prevention parameter\n\
+ -noproxy - Generate the low-level functional interface instead\n\
+ of proxy classes\n\
+ -oldvarnames - Old intermediary method names for variable wrappers\n\
+ -package <name> - Set name of the Java package to <name>\n\
+\n";
diff --git a/contrib/tools/swig/Source/Modules/javascript.cxx b/contrib/tools/swig/Source/Modules/javascript.cxx
new file mode 100644
index 00000000000..086060cf0e4
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/javascript.cxx
@@ -0,0 +1,3257 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * javascript.cxx
+ *
+ * Javascript language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+/**
+ * Enables extra debugging information in typemaps.
+ */
+static bool js_template_enable_debug = false;
+
+#define ERR_MSG_ONLY_ONE_ENGINE_PLEASE "Only one engine can be specified at a time."
+
+// keywords used for state variables
+#define NAME "name"
+#define NAME_MANGLED "name_mangled"
+#define INDEX "idx"
+#define TYPE "type"
+#define TYPE_MANGLED "type_mangled"
+#define WRAPPER_NAME "wrapper"
+#define IS_IMMUTABLE "is_immutable"
+#define IS_STATIC "is_static"
+#define IS_ABSTRACT "is_abstract"
+#define IS_WRAPPED "is_wrapped"
+#define GETTER "getter"
+#define SETTER "setter"
+#define PARENT "parent"
+#define PARENT_MANGLED "parent_mangled"
+#define CTOR "ctor"
+#define CTOR_WRAPPERS "ctor_wrappers"
+#define CTOR_DISPATCHERS "ctor_dispatchers"
+#define DTOR "dtor"
+#define ARGCOUNT "wrap:argc"
+#define ARGREQUIRED "wrap:argmin"
+#define HAS_TEMPLATES "has_templates"
+#define FORCE_CPP "force_cpp"
+#define RESET true
+
+// keys for global state variables
+#define CREATE_NAMESPACES "create_namespaces"
+#define REGISTER_NAMESPACES "register_namespaces"
+#define INITIALIZER "initializer"
+
+// keys for class scoped state variables
+#define MEMBER_VARIABLES "member_variables"
+#define MEMBER_FUNCTIONS "member_functions"
+#define STATIC_FUNCTIONS "static_functions"
+#define STATIC_VARIABLES "static_variables"
+
+
+/**
+ * A convenience class to manage state variables for emitters.
+ * The implementation delegates to SWIG Hash DOHs and provides
+ * named sub-hashes for class, variable, and function states.
+ */
+class JSEmitterState {
+
+public:
+ JSEmitterState();
+ ~JSEmitterState();
+ DOH *globals();
+ DOH *globals(const char *key, DOH *initial = 0);
+ DOH *clazz(bool reset = false);
+ DOH *clazz(const char *key, DOH *initial = 0);
+ DOH *function(bool reset = false);
+ DOH *function(const char *key, DOH *initial = 0);
+ DOH *variable(bool reset = false);
+ DOH *variable(const char *key, DOH *initial = 0);
+ static int IsSet(DOH *val);
+
+private:
+ DOH *getState(const char *key, bool reset = false);
+ Hash *globalHash;
+};
+
+/**
+ * A convenience class that wraps a code snippet used as template
+ * for code generation.
+ */
+class Template {
+
+public:
+ Template(const String *code);
+ Template(const String *code, const String *templateName);
+ Template(const Template & other);
+ ~Template();
+ String *str();
+ Template & replace(const String *pattern, const String *repl);
+ Template & print(DOH *doh);
+ Template & pretty_print(DOH *doh);
+ void operator=(const Template & t);
+ Template & trim();
+
+private:
+ String *code;
+ String *templateName;
+};
+
+/**
+ * JSEmitter represents an abstraction of javascript code generators
+ * for different javascript engines.
+ **/
+class JSEmitter {
+
+protected:
+
+ typedef JSEmitterState State;
+
+ enum MarshallingMode {
+ Setter,
+ Getter,
+ Ctor,
+ Function
+ };
+
+public:
+
+ enum JSEngine {
+ JavascriptCore,
+ V8,
+ NodeJS,
+ NAPI
+ };
+
+ JSEmitter(JSEngine engine);
+
+ virtual ~ JSEmitter();
+
+ /**
+ * Opens output files and temporary output DOHs.
+ */
+ virtual int initialize(Node *n);
+
+ /**
+ * Writes all collected code into the output file(s).
+ */
+ virtual int dump(Node *n) = 0;
+
+ /**
+ * Cleans up all open output DOHs.
+ */
+ virtual int close() = 0;
+
+ /**
+ * Switches the context for code generation.
+ *
+ * Classes, global variables and global functions may need to
+ * be registered in certain static tables.
+ * This method should be used to switch output DOHs correspondingly.
+ */
+ virtual int switchNamespace(Node *);
+
+ /**
+ * Invoked at the beginning of the classHandler.
+ */
+ virtual int enterClass(Node *);
+
+ /**
+ * Invoked at the end of the classHandler.
+ */
+ virtual int exitClass(Node *) {
+ return SWIG_OK;
+ }
+
+ /**
+ * Invoked at the beginning of the variableHandler.
+ */
+ virtual int enterVariable(Node *);
+
+ /**
+ * Invoked at the end of the variableHandler.
+ */
+ virtual int exitVariable(Node *) {
+ return SWIG_OK;
+ }
+
+ /**
+ * Invoked at the beginning of the functionHandler.
+ */
+ virtual int enterFunction(Node *);
+
+ /**
+ * Invoked at the end of the functionHandler.
+ */
+ virtual int exitFunction(Node *) {
+ return SWIG_OK;
+ }
+
+ /**
+ * Invoked by functionWrapper callback after call to Language::functionWrapper.
+ */
+ virtual int emitWrapperFunction(Node *n);
+
+ /**
+ * Invoked by nativeWrapper callback
+ */
+ virtual int emitNativeFunction(Node *n);
+
+ /**
+ * Invoked from constantWrapper after call to Language::constantWrapper.
+ **/
+ virtual int emitConstant(Node *n);
+
+ /**
+ * Registers a given code snippet for a given key name.
+ *
+ * This method is called by the fragmentDirective handler
+ * of the JAVASCRIPT language module.
+ **/
+ int registerTemplate(const String *name, const String *code);
+
+ /**
+ * Retrieve the code template registered for a given name.
+ */
+ Template getTemplate(const String *name);
+
+ State & getState();
+
+protected:
+
+ /**
+ * Helper function for detecting if the constructor Node does not use a name that matches
+ * the expected name for a constructor. Occurs when %rename is used for just a constructor
+ * or %template instantiates a templated constructor with a different name to the class.
+ */
+ bool isRenamedConstructor(Node *n);
+
+ /**
+ * Generates code for a constructor function.
+ */
+ virtual int emitCtor(Node *n);
+
+ /**
+ * Generates code for a destructor function.
+ */
+ virtual int emitDtor(Node *n);
+
+ /**
+ * Generates code for a function.
+ */
+ virtual int emitFunction(Node *n, bool is_member, bool is_static);
+
+ virtual int emitFunctionDispatcher(Node *n, bool /*is_member */ );
+
+ /**
+ * Generates code for a getter function.
+ */
+ virtual int emitGetter(Node *n, bool is_member, bool is_static);
+
+ /**
+ * Generates code for a setter function.
+ */
+ virtual int emitSetter(Node *n, bool is_member, bool is_static);
+
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) = 0;
+
+ virtual String *emitInputTypemap(Node *n, Parm *params, Wrapper *wrapper, String *arg);
+
+ virtual String *emitCheckTypemap(Node *n, Parm *params, Wrapper *wrapper, String *arg);
+
+ virtual void marshalOutput(Node *n, ParmList *params, Wrapper *wrapper, String *actioncode, const String *cresult = 0, bool emitReturnVariable = true);
+
+ virtual void emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params);
+
+ /**
+ * Helper function to retrieve the first parent class node.
+ */
+ Node *getBaseClass(Node *n);
+
+ virtual int createNamespace(String *scope);
+
+ virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled);
+
+ virtual int emitNamespaces() = 0;
+
+ virtual const char *getFunctionTemplate(bool);
+
+ virtual const char *getFunctionDispatcherTemplate(bool);
+
+ virtual const char *getOverloadedFunctionTemplate(bool);
+
+ virtual const char *getSetterTemplate(bool);
+
+ virtual const char *getGetterTemplate(bool);
+
+protected:
+
+ JSEngine engine;
+ Hash *templates;
+ State state;
+
+ // contains context specific data (DOHs)
+ // to allow generation of namespace related code
+ // which are switched on namespace change
+ Hash *namespaces;
+ Hash *current_namespace;
+ String *defaultResultName;
+ File *f_wrappers;
+};
+
+/* factory methods for concrete JSEmitters: */
+
+JSEmitter *swig_javascript_create_JSCEmitter();
+JSEmitter *swig_javascript_create_V8Emitter();
+JSEmitter *swig_javascript_create_NodeJSEmitter();
+JSEmitter *swig_javascript_create_NAPIEmitter();
+
+/**********************************************************************
+ * JAVASCRIPT: SWIG module implementation
+ **********************************************************************/
+
+class JAVASCRIPT:public Language {
+
+public:
+
+ JAVASCRIPT():emitter(NULL) {
+ }
+ ~JAVASCRIPT() {
+ delete emitter;
+ }
+
+ virtual int functionHandler(Node *n);
+ virtual int globalfunctionHandler(Node *n);
+ virtual int variableHandler(Node *n);
+ virtual int globalvariableHandler(Node *n);
+ virtual int staticmemberfunctionHandler(Node *n);
+ virtual int classHandler(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int constantWrapper(Node *n);
+ virtual int nativeWrapper(Node *n);
+ virtual void main(int argc, char *argv[]);
+ virtual int top(Node *n);
+
+ /**
+ * Registers all %fragments assigned to section "templates".
+ **/
+ virtual int fragmentDirective(Node *n);
+
+public:
+
+ virtual String *getNSpace() const;
+
+private:
+
+ JSEmitter *emitter;
+};
+
+/* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Low level code generator for functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::functionWrapper(Node *n) {
+
+ // note: the default implementation only prints a message
+ // Language::functionWrapper(n);
+ emitter->emitWrapperFunction(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * functionHandler()
+ *
+ * Function handler for generating wrappers for functions
+ * --------------------------------------------------------------------- */
+int JAVASCRIPT::functionHandler(Node *n) {
+
+ if (GetFlag(n, "isextension") == 1) {
+ SetFlag(n, "ismember");
+ }
+
+ emitter->enterFunction(n);
+ Language::functionHandler(n);
+ emitter->exitFunction(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * globalfunctionHandler()
+ *
+ * Function handler for generating wrappers for functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::globalfunctionHandler(Node *n) {
+ emitter->switchNamespace(n);
+ Language::globalfunctionHandler(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Function handler for generating wrappers for static member functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::staticmemberfunctionHandler(Node *n) {
+ /*
+ * Note: storage=static is removed by Language::staticmemberfunctionHandler.
+ * So, don't rely on that after here. Instead use the state variable which is
+ * set by JSEmitter::enterFunction().
+ */
+ Language::staticmemberfunctionHandler(n);
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * variableHandler()
+ *
+ * Function handler for generating wrappers for variables
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::variableHandler(Node *n) {
+
+ emitter->enterVariable(n);
+ Language::variableHandler(n);
+ emitter->exitVariable(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * globalvariableHandler()
+ *
+ * Function handler for generating wrappers for global variables
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::globalvariableHandler(Node *n) {
+ emitter->switchNamespace(n);
+ Language::globalvariableHandler(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * constantHandler()
+ *
+ * Function handler for generating wrappers for constants
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::constantWrapper(Node *n) {
+ emitter->switchNamespace(n);
+
+ // Note: callbacks trigger this wrapper handler
+ // TODO: handle callback declarations
+ if (Equal(Getattr(n, "kind"), "function")) {
+ return SWIG_OK;
+ }
+ // TODO: the emitter for constants must be implemented in a cleaner way
+ // currently we treat it like a read-only variable
+ // however, there is a remaining bug with function pointer constants
+ // which could be fixed with a cleaner approach
+ emitter->emitConstant(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * nativeWrapper()
+ *
+ * Function wrapper for generating placeholders for native functions
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::nativeWrapper(Node *n) {
+ emitter->emitNativeFunction(n);
+
+ return SWIG_OK;
+}
+
+/* ---------------------------------------------------------------------
+ * classHandler()
+ *
+ * Function handler for generating wrappers for class
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::classHandler(Node *n) {
+ emitter->switchNamespace(n);
+
+ emitter->enterClass(n);
+ Language::classHandler(n);
+ emitter->exitClass(n);
+
+ return SWIG_OK;
+}
+
+int JAVASCRIPT::fragmentDirective(Node *n) {
+
+ // catch all fragment directives that have "templates" as location
+ // and register them at the emitter.
+ String *section = Getattr(n, "section");
+
+ if (Equal(section, "templates") && !ImportMode) {
+ emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code"));
+ } else {
+ return Language::fragmentDirective(n);
+ }
+
+ return SWIG_OK;
+}
+
+String *JAVASCRIPT::getNSpace() const {
+ return Language::getNSpace();
+}
+
+/* ---------------------------------------------------------------------
+ * top()
+ *
+ * Function handler for processing top node of the parse tree
+ * Wrapper code generation essentially starts from here
+ * --------------------------------------------------------------------- */
+
+int JAVASCRIPT::top(Node *n) {
+ emitter->initialize(n);
+
+ Language::top(n);
+
+ emitter->dump(n);
+ emitter->close();
+
+ return SWIG_OK;
+}
+
+static const char *usage = (char *)"\
+Javascript Options (available with -javascript)\n\
+ -jsc - creates a JavascriptCore extension \n\
+ -v8 - creates a v8 extension \n\
+ -node - creates a node.js extension \n\
+ -napi - creates a NAPI extension \n\
+ -debug-codetemplates - generates information about the origin of code templates\n";
+
+/* ---------------------------------------------------------------------
+ * main()
+ *
+ * Entry point for the JAVASCRIPT module
+ * --------------------------------------------------------------------- */
+
+void JAVASCRIPT::main(int argc, char *argv[]) {
+ // Set javascript subdirectory in SWIG library
+ SWIG_library_directory("javascript");
+
+ int engine = -1;
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-v8") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ Exit(EXIT_FAILURE);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::V8;
+ } else if (strcmp(argv[i], "-jsc") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ Exit(EXIT_FAILURE);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::JavascriptCore;
+ } else if (strcmp(argv[i], "-node") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ Exit(EXIT_FAILURE);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::NodeJS;
+ } else if (strcmp(argv[i], "-napi") == 0) {
+ if (engine != -1) {
+ Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE);
+ Exit(EXIT_FAILURE);
+ }
+ Swig_mark_arg(i);
+ engine = JSEmitter::NAPI;
+ } else if (strcmp(argv[i], "-debug-codetemplates") == 0) {
+ Swig_mark_arg(i);
+ js_template_enable_debug = true;
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ return;
+ }
+ }
+ }
+
+ switch (engine) {
+ case JSEmitter::NodeJS:
+ case JSEmitter::V8:
+ {
+ emitter = swig_javascript_create_V8Emitter();
+ Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0);
+ SWIG_library_directory("javascript/v8");
+ // V8 API is C++, so output must be C++ compatible even when wrapping C code
+ if (!cparse_cplusplus) {
+ Swig_cparse_cplusplusout(1);
+ }
+ if (engine == JSEmitter::NodeJS) {
+ Preprocessor_define("BUILDING_NODE_EXTENSION 1", 0);
+ }
+ break;
+ }
+ case JSEmitter::JavascriptCore:
+ {
+ emitter = swig_javascript_create_JSCEmitter();
+ Preprocessor_define("SWIG_JAVASCRIPT_JSC 1", 0);
+ SWIG_library_directory("javascript/jsc");
+ break;
+ }
+ case JSEmitter::NAPI:
+ {
+ emitter = swig_javascript_create_NAPIEmitter();
+ Preprocessor_define("SWIG_JAVASCRIPT_NAPI 1", 0);
+ SWIG_library_directory("javascript/napi");
+ Preprocessor_define("BUILDING_NODE_EXTENSION 1", 0);
+ if (!cparse_cplusplus) {
+ Swig_cparse_cplusplusout(1);
+ }
+ break;
+ }
+ default:
+ {
+ Printf(stderr, "SWIG Javascript: Unknown engine. Please specify one of '-jsc', '-v8', '-node' or '-napi'.\n");
+ Exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGJAVASCRIPT 1", 0);
+
+ // Set configuration file
+ SWIG_config_file("javascript.swg");
+
+ allow_overloading();
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_javascript() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_javascript() {
+ return new JAVASCRIPT();
+}
+
+extern "C" Language *swig_javascript(void) {
+ return new_swig_javascript();
+}
+
+/**********************************************************************
+ * Emitter implementations
+ **********************************************************************/
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter()
+ * ----------------------------------------------------------------------------- */
+
+JSEmitter::JSEmitter(JSEmitter::JSEngine engine)
+: engine(engine), templates(NewHash()), namespaces(NULL), current_namespace(NULL), defaultResultName(NewString("result")), f_wrappers(NULL) {
+}
+
+/* -----------------------------------------------------------------------------
+ * ~JSEmitter()
+ * ----------------------------------------------------------------------------- */
+
+JSEmitter::~JSEmitter() {
+ Delete(templates);
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::RegisterTemplate() : Registers a code template
+ *
+ * Note: this is used only by JAVASCRIPT::fragmentDirective().
+ * ----------------------------------------------------------------------------- */
+
+int JSEmitter::registerTemplate(const String *name, const String *code) {
+ if (!State::IsSet(state.globals(HAS_TEMPLATES))) {
+ SetFlag(state.globals(), HAS_TEMPLATES);
+ }
+ return Setattr(templates, name, code);
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::getTemplate() : Provides a registered code template
+ * ----------------------------------------------------------------------------- */
+
+Template JSEmitter::getTemplate(const String *name) {
+ String *templ = Getattr(templates, name);
+
+ if (!templ) {
+ Printf(stderr, "Could not find template %s\n.", name);
+ Exit(EXIT_FAILURE);
+ }
+
+ Template t(templ, name);
+ return t;
+}
+
+JSEmitterState & JSEmitter::getState() {
+ return state;
+}
+
+int JSEmitter::initialize(Node * /*n */ ) {
+
+ if (namespaces != NULL) {
+ Delete(namespaces);
+ }
+ namespaces = NewHash();
+ Hash *global_namespace = createNamespaceEntry("exports", 0, 0);
+
+ Setattr(namespaces, "::", global_namespace);
+ current_namespace = global_namespace;
+
+ f_wrappers = NewString("");
+
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::getBaseClass() : the node of the base class or NULL
+ *
+ * Note: the first base class is provided. Multiple inheritance is not
+ * supported.
+ * ----------------------------------------------------------------------------- */
+
+Node *JSEmitter::getBaseClass(Node *n) {
+ // retrieve the first base class that is not %ignored
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ return base.item;
+ }
+ return NULL;
+}
+
+ /* -----------------------------------------------------------------------------
+ * JSEmitter::emitWrapperFunction() : dispatches emitter functions.
+ *
+ * This allows having small sized, dedicated emitting functions.
+ * All state dependent branching is done here.
+ * ----------------------------------------------------------------------------- */
+
+int JSEmitter::emitWrapperFunction(Node *n) {
+ int ret = SWIG_OK;
+
+ String *kind = Getattr(n, "kind");
+
+ if (kind) {
+
+ if (Equal(kind, "function")
+ // HACK: sneaky.ctest revealed that typedef'd (global) functions must be
+ // detected via the 'view' attribute.
+ || (Equal(kind, "variable") && Equal(Getattr(n, "view"), "globalfunctionHandler"))
+ ) {
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+ bool is_static = GetFlag(state.function(), IS_STATIC) != 0;
+ ret = emitFunction(n, is_member, is_static);
+ } else if (Cmp(kind, "variable") == 0) {
+ bool is_static = GetFlag(state.variable(), IS_STATIC) != 0;
+ // HACK: smartpointeraccessed static variables are not treated as statics
+ if (GetFlag(n, "allocate:smartpointeraccess")) {
+ is_static = false;
+ }
+
+ bool is_member = GetFlag(n, "ismember") != 0;
+ bool is_setter = GetFlag(n, "memberset") != 0 || GetFlag(n, "varset") != 0;
+ bool is_getter = GetFlag(n, "memberget") != 0 || GetFlag(n, "varget") != 0;
+ if (is_setter) {
+ ret = emitSetter(n, is_member, is_static);
+ } else if (is_getter) {
+ ret = emitGetter(n, is_member, is_static);
+ }
+
+ } else {
+ Printf(stderr, "Warning: unsupported wrapper function type\n");
+ ret = SWIG_ERROR;
+ }
+ } else {
+ String *view = Getattr(n, "view");
+
+ if (Cmp(view, "constructorHandler") == 0) {
+ ret = emitCtor(n);
+ } else if (Cmp(view, "destructorHandler") == 0) {
+ ret = emitDtor(n);
+ } else {
+ Printf(stderr, "Warning: unsupported wrapper function type");
+ ret = SWIG_ERROR;
+ }
+ }
+
+ return ret;
+}
+
+int JSEmitter::emitNativeFunction(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+ enterFunction(n);
+ state.function(WRAPPER_NAME, wrapname);
+ exitFunction(n);
+ return SWIG_OK;
+}
+
+int JSEmitter::enterClass(Node *n) {
+ state.clazz(RESET);
+ state.clazz(NAME, Getattr(n, "sym:name"));
+ state.clazz("nspace", current_namespace);
+
+ // Creating a mangled name using the current namespace and the symbol name
+ String *mangled_name = NewString("");
+ Printf(mangled_name, "%s_%s", Getattr(current_namespace, NAME_MANGLED), Getattr(n, "sym:name"));
+ state.clazz(NAME_MANGLED, SwigType_manglestr(mangled_name));
+ Delete(mangled_name);
+
+ state.clazz(TYPE, NewString(Getattr(n, "classtype")));
+
+ String *type = SwigType_manglestr(Getattr(n, "classtypeobj"));
+ String *classtype_mangled = NewString("");
+ Printf(classtype_mangled, "p%s", type);
+ state.clazz(TYPE_MANGLED, classtype_mangled);
+ Delete(type);
+
+ String *ctor_wrapper = NewString("_wrap_new_veto_");
+ Append(ctor_wrapper, state.clazz(NAME));
+ state.clazz(CTOR, ctor_wrapper);
+ state.clazz(CTOR_DISPATCHERS, NewString(""));
+ state.clazz(DTOR, NewString("0"));
+
+ // HACK: assume that a class is abstract
+ // this is resolved by emitCtor (which is only called for non abstract classes)
+ SetFlag(state.clazz(), IS_ABSTRACT);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::enterFunction(Node *n) {
+ state.function(RESET);
+ state.function(NAME, Getattr(n, "sym:name"));
+ if (Equal(Getattr(n, "storage"), "static")) {
+ SetFlag(state.function(), IS_STATIC);
+ }
+ return SWIG_OK;
+}
+
+int JSEmitter::enterVariable(Node *n) {
+ // reset the state information for variables.
+ state.variable(RESET);
+
+ // Retrieve a pure symbol name. Using 'sym:name' as a basis, as it considers %renamings.
+ if (Equal(Getattr(n, "view"), "memberconstantHandler")) {
+ // Note: this is kind of hacky/experimental
+ // For constants/enums 'sym:name' contains e.g., 'Foo_Hello' instead of 'Hello'
+ state.variable(NAME, Getattr(n, "memberconstantHandler:sym:name"));
+ } else {
+ state.variable(NAME, Swig_scopename_last(Getattr(n, "sym:name")));
+ }
+
+ if (Equal(Getattr(n, "storage"), "static")) {
+ SetFlag(state.variable(), IS_STATIC);
+ }
+
+ if (Language::instance()->is_immutable(n)) {
+ SetFlag(state.variable(), IS_IMMUTABLE);
+ }
+ // FIXME: test "arrays_global" does not compile with that as it is not allowed to assign to char[]
+ if (Equal(Getattr(n, "type"), "a().char")) {
+ SetFlag(state.variable(), IS_IMMUTABLE);
+ }
+
+ return SWIG_OK;
+}
+
+const char *JSEmitter::getFunctionTemplate(bool) {
+ return "js_function";
+}
+
+const char *JSEmitter::getFunctionDispatcherTemplate(bool) {
+ return "js_function_dispatcher";
+}
+
+const char *JSEmitter::getOverloadedFunctionTemplate(bool) {
+ return "js_overloaded_function";
+}
+
+const char *JSEmitter::getGetterTemplate(bool) {
+ return "js_getter";
+}
+
+const char *JSEmitter::getSetterTemplate(bool) {
+ return "js_setter";
+}
+
+bool JSEmitter::isRenamedConstructor(Node *n) {
+ Node *cls = parentNode(n);
+ if (!Equal(nodeType(cls), "class")) {
+ cls = parentNode(cls);
+ assert(Equal(nodeType(cls), "class"));
+ }
+
+ return !Equal(Getattr(n, "constructorHandler:sym:name"), Getattr(cls, "sym:name"));
+}
+
+int JSEmitter::emitCtor(Node *n) {
+
+ // Constructor renaming does not work in JavaScript.
+ // This allows us to slip past the unit tests which are broken for all JavaScript backends.
+ // TODO: fix by correcting the bad constructor name - this is the approach used in the Java module.
+ if (isRenamedConstructor(n))
+ return SWIG_ERROR;
+
+ Wrapper *wrapper = NewWrapper();
+
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+
+ Template t_ctor(getTemplate("js_ctor"));
+
+ // prepare the function wrapper name
+ String *iname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *wrap_name = Swig_name_wrapper(iname);
+ if (is_overloaded) {
+ t_ctor = getTemplate("js_overloaded_ctor");
+ Append(wrap_name, Getattr(n, "sym:overname"));
+ }
+ Setattr(n, "wrap:name", wrap_name);
+ // note: we can remove the is_abstract flag now, as this
+ // is called for non-abstract classes only.
+ Setattr(state.clazz(), IS_ABSTRACT, 0);
+
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ Printf(wrapper->locals, "%sresult;", SwigType_str(Getattr(n, "type"), 0));
+
+ marshalInputArgs(n, params, wrapper, Ctor, true, false);
+ String *action = emit_action(n);
+ Printv(wrapper->code, action, "\n", 0);
+
+ emitCleanupCode(n, wrapper, params);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(wrapper->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(wrapper->code, "$symname", iname);
+
+ t_ctor.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .replace("$jsargcount", Getattr(n, ARGCOUNT))
+ .replace("$jsparent", state.clazz(PARENT_MANGLED))
+ .replace("$jsargrequired", Getattr(n, ARGREQUIRED))
+ .pretty_print(f_wrappers);
+
+ Template t_ctor_case(getTemplate("js_ctor_dispatch_case"));
+ t_ctor_case.replace("$jswrapper", wrap_name)
+ .replace("$jsargcount", Getattr(n, ARGCOUNT))
+ .replace("$jsargrequired", Getattr(n, ARGREQUIRED));
+ Append(state.clazz(CTOR_DISPATCHERS), t_ctor_case.str());
+
+ DelWrapper(wrapper);
+
+ // create a dispatching ctor
+ if (is_overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ Template t_mainctor(getTemplate("js_ctor_dispatcher"));
+ t_mainctor.replace("$jswrapper", wrap_name)
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsdispatchcases", state.clazz(CTOR_DISPATCHERS))
+ .replace("$jsparent", state.clazz(PARENT_MANGLED))
+ .pretty_print(f_wrappers);
+ state.clazz(CTOR, wrap_name);
+ }
+ } else {
+ state.clazz(CTOR, wrap_name);
+ }
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitDtor(Node *n) {
+
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+
+ SwigType *type = state.clazz(TYPE);
+ String *p_classtype = SwigType_add_pointer(state.clazz(TYPE));
+ String *ctype = SwigType_lstr(p_classtype, "");
+ String *jsfree = NewString("");
+
+ // (Taken from JSCore implementation.)
+ /* The if (Extend) block was taken from the Ruby implementation.
+ * The problem is that in the case of an %extend to create a destructor for a struct to coordinate automatic memory cleanup with the Javascript collector,
+ * the SWIG function was not being generated. More specifically:
+ struct MyData {
+ %extend {
+ ~MyData() {
+ FreeData($self);
+ }
+ }
+ };
+ %newobject CreateData;
+ struct MyData* CreateData(void);
+ %delobject FreeData;
+ void FreeData(struct MyData* the_data);
+
+ where the use case is something like:
+ var my_data = example.CreateData();
+ my_data = null;
+
+ This function was not being generated:
+ SWIGINTERN void delete_MyData(struct MyData *self){
+ FreeData(self);
+ }
+
+ I don't understand fully why it wasn't being generated. It just seems to happen in the Lua generator.
+ There is a comment about staticmemberfunctionHandler having an inconsistency and I tracked down dome of the SWIGINTERN void delete_*
+ code to that function in the Language base class.
+ The Ruby implementation seems to have an explicit check for if(Extend) and explicitly generates the code, so that's what I'm doing here.
+ The Ruby implementation does other stuff which I omit.
+ */
+ if (Extend) {
+ String *wrap = Getattr(n, "wrap:code");
+ if (wrap) {
+ Printv(f_wrappers, wrap, NIL);
+ }
+ }
+ // HACK: this is only for the v8 emitter. maybe set an attribute wrap:action of node
+ // TODO: generate dtors more similar to other wrappers
+ // EW: I think this is wrong. delete should only be used when new was used to create. If malloc was used, free needs to be used.
+ if (SwigType_isarray(type)) {
+ Printf(jsfree, "delete [] (%s)", ctype);
+ } else {
+ Printf(jsfree, "delete (%s)", ctype);
+ }
+
+ String *destructor_action = Getattr(n, "wrap:action");
+ // Adapted from the JSCore implementation.
+ /* The next challenge is to generate the correct finalize function for JavaScriptCore to call.
+ Originally, it would use this fragment from javascriptcode.swg
+ %fragment ("JS_destructordefn", "templates")
+ %{
+ void _wrap_${classname_mangled}_finalize(JSObjectRef thisObject)
+ {
+ SWIG_PRV_DATA* t = (SWIG_PRV_DATA*)JSObjectGetPrivate(thisObject);
+ if(t && t->swigCMemOwn) free ((${type}*)t->swigCObject);
+ free(t);
+ }
+ %}
+
+ But for the above example case of %extend to define a destructor on a struct, we need to override the system to not call
+ free ((${type}*)t->swigCObject);
+ and substitute it with what the user has provided.
+ To solve this, I created a variation fragment called JS_destructoroverridedefn:
+ SWIG_PRV_DATA* t = (SWIG_PRV_DATA*)JSObjectGetPrivate(thisObject);
+ if(t && t->swigCMemOwn) {
+ ${type}* arg1 = (${type}*)t->swigCObject;
+ ${destructor_action}
+ }
+ free(t);
+
+ Based on what I saw in the Lua and Ruby modules, I use Getattr(n, "wrap:action")
+ to decide if the user has a preferred destructor action.
+ Based on that, I decide which fragment to use.
+ And in the case of the custom action, I substitute that action in.
+ I noticed that destructor_action has the form
+ delete_MyData(arg1);
+ The explicit arg1 is a little funny, so I structured the fragment to create a temporary variable called arg1 to make the generation easier.
+ This might suggest this solution misunderstands a more complex case.
+
+ Also, there is a problem where destructor_action is always true for me, even when not requesting %extend as above.
+ So this code doesn't actually quite work as I expect. The end result is that the code still works because
+ destructor_action calls free like the original template. The one caveat is the string in destructor_action casts to char* which is weird.
+ I think there is a deeper underlying SWIG issue because I don't think it should be char*. However, it doesn't really matter for free.
+
+ Maybe the fix for the destructor_action always true problem is that this is supposed to be embedded in the if(Extend) block above.
+ But I don't fully understand the conditions of any of these things, and since it works for the moment, I don't want to break more stuff.
+ */
+ if (destructor_action) {
+ Template t_dtor = getTemplate("js_dtoroverride");
+ state.clazz(DTOR, wrap_name);
+ t_dtor.replace("${classname_mangled}", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jsfree", jsfree)
+ .replace("$jstype", ctype);
+
+ t_dtor.replace("${destructor_action}", destructor_action);
+ Wrapper_pretty_print(t_dtor.str(), f_wrappers);
+ } else {
+ Template t_dtor = getTemplate("js_dtor");
+ state.clazz(DTOR, wrap_name);
+ t_dtor.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jsfree", jsfree)
+ .replace("$jstype", ctype)
+ .pretty_print(f_wrappers);
+ }
+
+ Delete(p_classtype);
+ Delete(ctype);
+ Delete(jsfree);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitGetter(Node *n, bool is_member, bool is_static) {
+ Wrapper *wrapper = NewWrapper();
+ Template t_getter(getTemplate(getGetterTemplate(is_member)));
+
+ // prepare wrapper name
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ Setattr(n, "wrap:name", wrap_name);
+ state.variable(GETTER, wrap_name);
+
+ // prepare local variables
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ // prepare code part
+ String *action = emit_action(n);
+ marshalInputArgs(n, params, wrapper, Getter, is_member, is_static);
+ marshalOutput(n, params, wrapper, action);
+
+ emitCleanupCode(n, wrapper, params);
+
+ t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .pretty_print(f_wrappers);
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitSetter(Node *n, bool is_member, bool is_static) {
+
+ // skip variables that are immutable
+ if (State::IsSet(state.variable(IS_IMMUTABLE))) {
+ return SWIG_OK;
+ }
+
+ Wrapper *wrapper = NewWrapper();
+
+ Template t_setter(getTemplate(getSetterTemplate(is_member)));
+
+ // prepare wrapper name
+ String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
+ Setattr(n, "wrap:name", wrap_name);
+ state.variable(SETTER, wrap_name);
+
+ // prepare local variables
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ // prepare code part
+ String *action = emit_action(n);
+ marshalInputArgs(n, params, wrapper, Setter, is_member, is_static);
+ Append(wrapper->code, action);
+
+ emitCleanupCode(n, wrapper, params);
+
+ t_setter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .pretty_print(f_wrappers);
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * JSEmitter::emitConstant() : triggers code generation for constants
+ * ----------------------------------------------------------------------------- */
+
+int JSEmitter::emitConstant(Node *n) {
+ // HACK: somehow it happened under Mac OS X that before everything started
+ // a lot of SWIG internal constants were emitted
+ // This didn't happen on other platforms yet...
+ // we ignore those premature definitions
+ if (!State::IsSet(state.globals(HAS_TEMPLATES))) {
+ return SWIG_ERROR;
+ }
+
+ Wrapper *wrapper = NewWrapper();
+ SwigType *type = Getattr(n, "type");
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_get(Getattr(current_namespace, NAME_MANGLED), iname);
+ String *value = Getattr(n, "value");
+
+ // HACK: forcing usage of cppvalue for v8 (which turned out to fix typedef_struct.i, et. al)
+ if (State::IsSet(state.globals(FORCE_CPP)) && Getattr(n, "cppvalue") != NULL) {
+ value = Getattr(n, "cppvalue");
+ }
+
+ bool is_member = GetFlag(n, "ismember");
+ Template t_getter(getTemplate(getGetterTemplate(is_member)));
+
+ // call the variable methods as a constants are
+ // registered in same way
+ enterVariable(n);
+ state.variable(GETTER, wname);
+ // TODO: why do we need this?
+ Setattr(n, "wrap:name", wname);
+
+ // special treatment of member pointers
+ if (SwigType_type(type) == T_MPOINTER) {
+ // TODO: this could go into a code-template
+ String *mpointer_wname = NewString("");
+ Printf(mpointer_wname, "_wrapConstant_%s", iname);
+ Setattr(n, "memberpointer:constant:wrap:name", mpointer_wname);
+ String *str = SwigType_str(type, mpointer_wname);
+ Printf(f_wrappers, "static %s = %s;\n", str, value);
+ Delete(str);
+ value = mpointer_wname;
+ }
+
+ marshalOutput(n, 0, wrapper, NewString(""), value, false);
+
+ t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wname)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .pretty_print(f_wrappers);
+
+ exitVariable(n);
+
+ // This is the counterpart to the "constant" test in
+ // exitVariable, it prevents double setting of
+ // symbols that are both constants and variables
+ SetFlag(n, "constant");
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
+ Wrapper *wrapper = NewWrapper();
+ Template t_function(getTemplate(getFunctionTemplate(is_member)));
+
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+
+ // prepare the function wrapper name
+ String *iname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *wrap_name = Swig_name_wrapper(iname);
+ if (is_overloaded) {
+ t_function = getTemplate(getOverloadedFunctionTemplate(is_member));
+ Append(wrap_name, Getattr(n, "sym:overname"));
+ }
+ Setattr(n, "wrap:name", wrap_name);
+ state.function(WRAPPER_NAME, wrap_name);
+
+ // prepare local variables
+ ParmList *params = Getattr(n, "parms");
+ emit_parameter_variables(params, wrapper);
+ emit_attach_parmmaps(params, wrapper);
+
+ marshalInputArgs(n, params, wrapper, Function, is_member, is_static);
+ String *action = emit_action(n);
+ marshalOutput(n, params, wrapper, action);
+ emitCleanupCode(n, wrapper, params);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(wrapper->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(wrapper->code, "$symname", iname);
+
+ t_function.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", wrap_name)
+ .replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code)
+ .replace("$jsargcount", Getattr(n, ARGCOUNT))
+ .replace("$jsargrequired", Getattr(n, ARGREQUIRED))
+ .pretty_print(f_wrappers);
+
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::emitFunctionDispatcher(Node *n, bool is_member) {
+ Wrapper *wrapper = NewWrapper();
+
+ // Generate call list, go to first node
+ Node *sibl = n;
+
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+
+ do {
+ String *siblname = Getattr(sibl, "wrap:name");
+
+ if (siblname) {
+ // handle function overloading
+ Template t_dispatch_case = getTemplate("js_function_dispatch_case");
+ t_dispatch_case.replace("$jswrapper", siblname)
+ .replace("$jsargcount", Getattr(sibl, ARGCOUNT))
+ .replace("$jsargrequired", Getattr(sibl, ARGREQUIRED));
+
+ Append(wrapper->code, t_dispatch_case.str());
+ }
+
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+
+ Template t_function(getTemplate(getFunctionDispatcherTemplate(is_member)));
+
+ // Note: this dispatcher function gets called after the last overloaded function has been created.
+ // At this time, n.wrap:name contains the name of the last wrapper function.
+ // To get a valid function name for the dispatcher function we take the last wrapper name and
+ // subtract the extension "sym:overname",
+ String *wrap_name = NewString(Getattr(n, "wrap:name"));
+ String *overname = Getattr(n, "sym:overname");
+
+ Node *methodclass = Swig_methodclass(n);
+ String *class_name = Getattr(methodclass, "sym:name");
+
+ int l1 = Len(wrap_name);
+ int l2 = Len(overname);
+ Delslice(wrap_name, l1 - l2, l1);
+
+ String *new_string = NewStringf("%s_%s", class_name, wrap_name);
+ String *final_wrap_name = Swig_name_wrapper(new_string);
+
+ Setattr(n, "wrap:name", final_wrap_name);
+ state.function(WRAPPER_NAME, final_wrap_name);
+
+
+
+ t_function.replace("$jslocals", wrapper->locals)
+ .replace("$jscode", wrapper->code);
+
+ // call this here, to replace all variables
+ t_function.replace("$jswrapper", final_wrap_name)
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .pretty_print(f_wrappers);
+
+ // Delete the state variable
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+}
+
+String *JSEmitter::emitInputTypemap(Node *n, Parm *p, Wrapper *wrapper, String *arg) {
+ String *code = NewString("");
+ // Get input typemap for current param
+ String *tm = Getattr(p, "tmap:in");
+ String *tm_def = Getattr(p, "tmap:default");
+ SwigType *type = Getattr(p, "type");
+ int argmin = -1;
+ int argidx = -1;
+ bool is_optional = false;
+
+ if (Getattr(n, ARGREQUIRED)) {
+ argmin = GetInt(n, ARGREQUIRED);
+ }
+ if (Getattr(p, INDEX)) {
+ argidx = GetInt(p, INDEX);
+ }
+
+ if (tm_def != NULL) {
+ is_optional = true;
+ }
+ if (argmin >= 0 && argidx >= 0 && argidx >= argmin) {
+ is_optional = true;
+ }
+ if (is_optional && Getattr(p, INDEX) == NULL) {
+ Printf(stderr, "Argument %s in %s cannot be a default argument\n", Getattr(p, NAME), state.function(NAME));
+ return SWIG_ERROR;
+ }
+
+ if (is_optional) {
+ Template t_check_default(getTemplate("js_check_arg"));
+
+ t_check_default.replace("$jsarg", Getattr(p, INDEX)).pretty_print(code);
+ Printf(code, "{\n");
+ }
+
+ if (tm != NULL) {
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ // do replacements for built-in variables
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$symname", Getattr(n, "sym:name"));
+ if (!checkAttribute(p, "tmap:in:noblock", "1")) {
+ Printf(code, "{\n");
+ }
+ Printf(code, "%s", tm);
+ if (!checkAttribute(p, "tmap:in:noblock", "1")) {
+ Printf(code, "\n}\n");
+ }
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
+ return NULL;
+ }
+
+ if (is_optional) {
+ Printf(code, "}\n");
+ }
+
+ // numinputs=0 typemaps are emitted by the legacy code in
+ // emit_attach_parmmaps() in emit.cxx, check the comment there
+ // All generators work around this
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+ Append(wrapper->code, code);
+ }
+ return code;
+}
+
+String *JSEmitter::emitCheckTypemap(Node *, Parm *p, Wrapper *wrapper, String *arg) {
+ String *tm = Getattr(p, "tmap:check");
+
+ if (tm != NULL) {
+ Replaceall(tm, "$input", arg);
+ Printf(wrapper->code, "%s\n", tm);
+ }
+
+ return tm;
+}
+
+void JSEmitter::marshalOutput(Node *n, ParmList *params, Wrapper *wrapper, String *actioncode, const String *cresult, bool emitReturnVariable) {
+ SwigType *type = Getattr(n, "type");
+ String *tm;
+ Parm *p;
+
+ // adds a declaration for the result variable
+ if (emitReturnVariable)
+ emit_return_variable(n, type, wrapper);
+ // if not given, use default result identifier ('result') for output typemap
+ if (cresult == 0)
+ cresult = defaultResultName;
+
+ tm = Swig_typemap_lookup_out("out", n, cresult, wrapper, actioncode);
+ bool should_own = GetFlag(n, "feature:new") != 0;
+
+ if (tm) {
+ Replaceall(tm, "$objecttype", Swig_scopename_last(SwigType_str(SwigType_strip_qualifiers(type), 0)));
+
+ if (should_own) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Append(wrapper->code, tm);
+
+ if (Len(tm) > 0) {
+ Printf(wrapper->code, "\n");
+ }
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), Getattr(n, "name"));
+ }
+
+ if (params) {
+ for (p = params; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ Replaceall(wrapper->code, "$result", "jsresult");
+}
+
+void JSEmitter::emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params) {
+ Parm *p;
+ String *tm;
+
+ for (p = params; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ //addThrows(n, "tmap:freearg", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (GetFlag(n, "feature:new")) {
+ tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm != NIL) {
+ //addThrows(throws_hash, "newfree", n);
+ Printv(wrapper->code, tm, "\n", NIL);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(wrapper->code, "%s\n", tm);
+ Delete(tm);
+ }
+}
+
+int JSEmitter::switchNamespace(Node *n) {
+ // HACK: somehow this gets called for member functions.
+ // We can safely ignore them, as members are not associated to a namespace (only their class)
+ if (GetFlag(n, "ismember")) {
+ return SWIG_OK;
+ }
+ // if nspace is deactivated, everything goes into the global scope
+ if (!GetFlag(n, "feature:nspace")) {
+ current_namespace = Getattr(namespaces, "::");
+ return SWIG_OK;
+ }
+// EXPERIMENTAL: we want to use Language::getNSpace() here
+// However, it is not working yet.
+// For namespace functions Language::getNSpace() does not give a valid result
+#if 0
+ JAVASCRIPT *lang = static_cast<JAVASCRIPT*>(Language::instance());
+ String *_nspace = lang->getNSpace();
+ if (!Equal(nspace, _nspace)) {
+ Printf(stdout, "##### Custom vs Language::getNSpace(): %s | %s\n", nspace, _nspace);
+ }
+#endif
+
+ String *nspace = Getattr(n, "sym:nspace");
+
+ if (nspace == NULL) {
+ // It seems that only classes have 'sym:nspace' set.
+ // We try to get the namespace from the qualified name (i.e., everything before the last '::')
+ nspace = Swig_scopename_prefix(Getattr(n, "name"));
+ }
+ // If there is not even a scopename prefix then it must be global scope
+ if (nspace == NULL) {
+ current_namespace = Getattr(namespaces, "::");
+ return SWIG_OK;
+ }
+
+ String *scope = NewString(nspace);
+ // replace "." with "::" that we can use Swig_scopename_last
+ Replaceall(scope, ".", "::");
+
+ // if the scope is not yet registered
+ // create (parent) namespaces recursively
+ if (!Getattr(namespaces, scope)) {
+ createNamespace(scope);
+ }
+ current_namespace = Getattr(namespaces, scope);
+
+ return SWIG_OK;
+}
+
+int JSEmitter::createNamespace(String *scope) {
+
+ String *parent_scope = Swig_scopename_prefix(scope);
+ Hash *parent_namespace;
+ if (parent_scope == 0) {
+ parent_namespace = Getattr(namespaces, "::");
+ } else if (!Getattr(namespaces, parent_scope)) {
+ createNamespace(parent_scope);
+ parent_namespace = Getattr(namespaces, parent_scope);
+ } else {
+ parent_namespace = Getattr(namespaces, parent_scope);
+ }
+ assert(parent_namespace != 0);
+
+ Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name")), Char(Getattr(parent_namespace, "name_mangled")));
+ Setattr(namespaces, scope, new_namespace);
+
+ Delete(parent_scope);
+ return SWIG_OK;
+}
+
+Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent, const char *parent_mangled) {
+ Hash *entry = NewHash();
+ String *name = NewString(_name);
+ Setattr(entry, NAME, Swig_scopename_last(name));
+ Setattr(entry, NAME_MANGLED, Swig_name_mangle_string(name));
+ Setattr(entry, PARENT, NewString(parent));
+ Setattr(entry, PARENT_MANGLED, NewString(parent_mangled));
+
+ Delete(name);
+ return entry;
+}
+
+/**********************************************************************
+ * JavascriptCore: JSEmitter implementation for JavascriptCore engine
+ **********************************************************************/
+
+class JSCEmitter:public JSEmitter {
+
+public:
+ JSCEmitter();
+ virtual ~ JSCEmitter();
+ virtual int initialize(Node *n);
+ virtual int dump(Node *n);
+ virtual int close();
+
+protected:
+ virtual int enterVariable(Node *n);
+ virtual int exitVariable(Node *n);
+ virtual int enterFunction(Node *n);
+ virtual int exitFunction(Node *n);
+ virtual int enterClass(Node *n);
+ virtual int exitClass(Node *n);
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static);
+ virtual Hash *createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled);
+ virtual int emitNamespaces();
+
+private:
+
+ String *NULL_STR;
+ String *VETO_SET;
+
+ // output file and major code parts
+ File *f_wrap_cpp;
+ File *f_runtime;
+ File *f_header;
+ File *f_init;
+
+};
+
+JSCEmitter::JSCEmitter()
+: JSEmitter(JSEmitter::JavascriptCore), NULL_STR(NewString("NULL")), VETO_SET(NewString("JS_veto_set_variable")), f_wrap_cpp(NULL), f_runtime(NULL), f_header(NULL), f_init(NULL) {
+}
+
+JSCEmitter::~JSCEmitter() {
+ Delete(NULL_STR);
+ Delete(VETO_SET);
+}
+
+
+/* ---------------------------------------------------------------------
+ * marshalInputArgs()
+ *
+ * Process all of the arguments passed into the argv array
+ * and convert them into C/C++ function arguments using the
+ * supplied typemaps.
+ * --------------------------------------------------------------------- */
+
+void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) {
+ Parm *p;
+ String *tm = NULL;
+
+ // determine an offset index, as members have an extra 'this' argument
+ // except: static members and ctors.
+ int startIdx = 0;
+ if (is_member && !is_static && mode != Ctor) {
+ startIdx = 1;
+ }
+ // store number of arguments for argument checks
+ int num_args = emit_num_arguments(parms) - startIdx;
+ String *argcount = NewString("");
+ Printf(argcount, "%d", num_args);
+ Setattr(n, ARGCOUNT, argcount);
+ int num_required = emit_num_required(parms) - startIdx;
+ SetInt(n, ARGREQUIRED, num_required);
+
+ // process arguments
+ int i = 0;
+ for (p = parms; p;) {
+ String *arg = NewString("");
+ String *type = Getattr(p, "type");
+
+ // ignore varargs
+ if (SwigType_isvarargs(type))
+ break;
+
+ switch (mode) {
+ case Getter:
+ case Function:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "thisObject", 0);
+ i++;
+ } else {
+ Printf(arg, "argv[%d]", i - startIdx);
+ SetInt(p, INDEX, i - startIdx);
+ i += GetInt(p, "tmap:in:numinputs");
+ }
+ break;
+ case Setter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "thisObject", 0);
+ i++;
+ } else {
+ Printv(arg, "value", 0);
+ i++;
+ }
+ break;
+ case Ctor:
+ Printf(arg, "argv[%d]", i);
+ SetInt(p, INDEX, i);
+ i += GetInt(p, "tmap:in:numinputs");
+ break;
+ default:
+ Printf(stderr, "Illegal MarshallingMode.");
+ Exit(EXIT_FAILURE);
+ }
+
+ tm = emitInputTypemap(n, p, wrapper, arg);
+ Delete(arg);
+
+ if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ for (p = parms; p;) {
+ tm = emitCheckTypemap(n, p, wrapper, Getattr(p, "emit:input"));
+ if (tm) {
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+int JSCEmitter::initialize(Node *n) {
+
+ JSEmitter::initialize(n);
+
+ /* Get the output file name */
+ String *outfile = Getattr(n, "outfile");
+
+ /* Initialize I/O */
+ f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_wrap_cpp) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ /* Initialization of members */
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+
+ state.globals(CREATE_NAMESPACES, NewString(""));
+ state.globals(REGISTER_NAMESPACES, NewString(""));
+ state.globals(INITIALIZER, NewString(""));
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", f_wrap_cpp);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+
+ Swig_banner(f_wrap_cpp);
+
+ Swig_obligatory_macros(f_runtime, "JAVASCRIPT");
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::dump(Node *n) {
+ /* Get the module name */
+ String *module = Getattr(n, "name");
+
+ Template initializer_define(getTemplate("js_initializer_define"));
+ initializer_define.replace("$jsname", module).pretty_print(f_header);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printv(f_wrap_cpp, f_runtime, "\n", 0);
+ Printv(f_wrap_cpp, f_header, "\n", 0);
+ Printv(f_wrap_cpp, f_wrappers, "\n", 0);
+
+ emitNamespaces();
+
+ // compose the initializer function using a template
+ Template initializer(getTemplate("js_initializer"));
+ initializer.replace("$jsname", module)
+ .replace("$jsregisterclasses", state.globals(INITIALIZER))
+ .replace("$jscreatenamespaces", state.globals(CREATE_NAMESPACES))
+ .replace("$jsregisternamespaces", state.globals(REGISTER_NAMESPACES))
+ .pretty_print(f_init);
+
+ Printv(f_wrap_cpp, f_init, 0);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::close() {
+ Delete(f_runtime);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(namespaces);
+ Delete(f_wrap_cpp);
+ return SWIG_OK;
+}
+
+int JSCEmitter::enterFunction(Node *n) {
+
+ JSEmitter::enterFunction(n);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::exitFunction(Node *n) {
+ Template t_function = getTemplate("jsc_function_declaration");
+
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+
+ // handle overloaded functions
+ if (is_overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ //state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name")));
+ // create dispatcher
+ emitFunctionDispatcher(n, is_member);
+ } else {
+ //don't register wrappers of overloaded functions in function tables
+ return SWIG_OK;
+ }
+ }
+
+ t_function.replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME));
+
+ if (is_member) {
+ if (GetFlag(state.function(), IS_STATIC)) {
+ t_function.pretty_print(state.clazz(STATIC_FUNCTIONS));
+ } else {
+ t_function.pretty_print(state.clazz(MEMBER_FUNCTIONS));
+ }
+ } else {
+ t_function.pretty_print(Getattr(current_namespace, "functions"));
+ }
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::enterVariable(Node *n) {
+ JSEmitter::enterVariable(n);
+ state.variable(GETTER, NULL_STR);
+ state.variable(SETTER, VETO_SET);
+ return SWIG_OK;
+}
+
+int JSCEmitter::exitVariable(Node *n) {
+ Template t_variable(getTemplate("jsc_variable_declaration"));
+ t_variable.replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER));
+
+ if (GetFlag(n, "ismember")) {
+ if (GetFlag(state.variable(), IS_STATIC)
+ || Equal(Getattr(n, "nodeType"), "enumitem")) {
+ t_variable.pretty_print(state.clazz(STATIC_VARIABLES));
+ } else {
+ t_variable.pretty_print(state.clazz(MEMBER_VARIABLES));
+ }
+ } else {
+ t_variable.pretty_print(Getattr(current_namespace, "values"));
+ }
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::enterClass(Node *n) {
+ JSEmitter::enterClass(n);
+ state.clazz(MEMBER_VARIABLES, NewString(""));
+ state.clazz(MEMBER_FUNCTIONS, NewString(""));
+ state.clazz(STATIC_VARIABLES, NewString(""));
+ state.clazz(STATIC_FUNCTIONS, NewString(""));
+
+ Template t_class_decl = getTemplate("jsc_class_declaration");
+ t_class_decl.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .pretty_print(f_wrappers);
+
+ return SWIG_OK;
+}
+
+int JSCEmitter::exitClass(Node *n) {
+ Template t_class_tables(getTemplate("jsc_class_tables"));
+ t_class_tables.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsclassvariables", state.clazz(MEMBER_VARIABLES))
+ .replace("$jsclassfunctions", state.clazz(MEMBER_FUNCTIONS))
+ .replace("$jsstaticclassfunctions", state.clazz(STATIC_FUNCTIONS))
+ .replace("$jsstaticclassvariables", state.clazz(STATIC_VARIABLES))
+ .pretty_print(f_wrappers);
+
+ /* adds the ctor wrappers at this position */
+ // Note: this is necessary to avoid extra forward declarations.
+ //Append(f_wrappers, state.clazz(CTOR_WRAPPERS));
+
+ // for abstract classes add a vetoing ctor
+ if (GetFlag(state.clazz(), IS_ABSTRACT)) {
+ Template t_veto_ctor(getTemplate("js_veto_ctor"));
+ t_veto_ctor.replace("$jswrapper", state.clazz(CTOR))
+ .replace("$jsname", state.clazz(NAME))
+ .pretty_print(f_wrappers);
+ }
+
+ /* adds a class template statement to initializer function */
+ Template t_classtemplate(getTemplate("jsc_class_definition"));
+
+ /* prepare registration of base class */
+ String *jsclass_inheritance = NewString("");
+ Node *base_class = getBaseClass(n);
+ if (base_class != NULL) {
+ Template t_inherit(getTemplate("jsc_class_inherit"));
+ t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsbaseclassmangled", SwigType_manglestr(Getattr(base_class, "name")))
+ .pretty_print(jsclass_inheritance);
+ } else {
+ Template t_inherit(getTemplate("jsc_class_noinherit"));
+ t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .pretty_print(jsclass_inheritance);
+ }
+
+ t_classtemplate.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsclass_inheritance", jsclass_inheritance)
+ .replace("$jsctor", state.clazz(CTOR))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .pretty_print(state.globals(INITIALIZER));
+ Delete(jsclass_inheritance);
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0"));
+
+ /* adds a class registration statement to initializer function */
+ Template t_registerclass(getTemplate("jsc_class_registration"));
+ t_registerclass.replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsnspace", Getattr(state.clazz("nspace"), NAME_MANGLED))
+ .pretty_print(state.globals(INITIALIZER));
+
+ return SWIG_OK;
+}
+
+Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent, const char *parent_mangled) {
+ Hash *entry = JSEmitter::createNamespaceEntry(name, parent, parent_mangled);
+ Setattr(entry, "functions", NewString(""));
+ Setattr(entry, "values", NewString(""));
+ return entry;
+}
+
+int JSCEmitter::emitNamespaces() {
+ Iterator it;
+ for (it = First(namespaces); it.item; it = Next(it)) {
+ Hash *entry = it.item;
+ String *name = Getattr(entry, NAME);
+ String *name_mangled = Getattr(entry, NAME_MANGLED);
+ String *parent_mangled = Getattr(entry, PARENT_MANGLED);
+ String *functions = Getattr(entry, "functions");
+ String *variables = Getattr(entry, "values");
+
+ // skip the global namespace which is given by the application
+
+ Template namespace_definition(getTemplate("jsc_nspace_declaration"));
+ namespace_definition.replace("$jsglobalvariables", variables)
+ .replace("$jsglobalfunctions", functions)
+ .replace("$jsnspace", name_mangled)
+ .replace("$jsmangledname", name_mangled)
+ .pretty_print(f_wrap_cpp);
+
+ Template t_createNamespace(getTemplate("jsc_nspace_definition"));
+ t_createNamespace.replace("$jsmangledname", name_mangled);
+ Append(state.globals(CREATE_NAMESPACES), t_createNamespace.str());
+
+ // Don't register 'exports' as namespace. It is return to the application.
+ if (!Equal("exports", name)) {
+ Template t_registerNamespace(getTemplate("jsc_nspace_registration"));
+ t_registerNamespace.replace("$jsmangledname", name_mangled)
+ .replace("$jsname", name)
+ .replace("$jsparent", parent_mangled);
+ Append(state.globals(REGISTER_NAMESPACES), t_registerNamespace.str());
+ }
+ }
+
+ return SWIG_OK;
+}
+
+JSEmitter *swig_javascript_create_JSCEmitter() {
+ return new JSCEmitter();
+}
+
+/**********************************************************************
+ * V8: JSEmitter implementation for V8 engine
+ **********************************************************************/
+
+class V8Emitter:public JSEmitter {
+
+public:
+ V8Emitter();
+
+ virtual ~ V8Emitter();
+ virtual int initialize(Node *n);
+ virtual int dump(Node *n);
+ virtual int close();
+ virtual int enterClass(Node *n);
+ virtual int exitClass(Node *n);
+ virtual int enterVariable(Node *n);
+ virtual int exitVariable(Node *n);
+ virtual int exitFunction(Node *n);
+
+protected:
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static);
+ virtual int emitNamespaces();
+
+protected:
+ /* built-in parts */
+ String *f_runtime;
+ String *f_header;
+ String *f_init;
+ String *f_post_init;
+
+ /* part for class templates */
+ String *f_class_templates;
+
+ /* parts for initilizer */
+ String *f_init_namespaces;
+ String *f_init_class_templates;
+ String *f_init_wrappers;
+ String *f_init_inheritance;
+ String *f_init_class_instances;
+ String *f_init_static_wrappers;
+ String *f_init_register_classes;
+ String *f_init_register_namespaces;
+
+ // the output cpp file
+ File *f_wrap_cpp;
+
+ String *NULL_STR;
+ String *VETO_SET;
+ String *moduleName;
+
+};
+
+V8Emitter::V8Emitter()
+: JSEmitter(JSEmitter::V8), NULL_STR(NewString("0")), VETO_SET(NewString("JS_veto_set_variable")) {
+}
+
+V8Emitter::~V8Emitter() {
+ Delete(NULL_STR);
+ Delete(VETO_SET);
+}
+
+int V8Emitter::initialize(Node *n) {
+ JSEmitter::initialize(n);
+
+ moduleName = Getattr(n, "name");
+
+ // Get the output file name
+ String *outfile = Getattr(n, "outfile");
+ f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_wrap_cpp) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ f_runtime = NewString("");
+ f_header = NewString("");
+ f_class_templates = NewString("");
+ f_init = NewString("");
+ f_post_init = NewString("");
+
+ f_init_namespaces = NewString("");
+ f_init_class_templates = NewString("");
+ f_init_wrappers = NewString("");
+ f_init_inheritance = NewString("");
+ f_init_class_instances = NewString("");
+ f_init_static_wrappers = NewString("");
+ f_init_register_classes = NewString("");
+ f_init_register_namespaces = NewString("");
+
+ // note: this is necessary for built-in generation of SWIG runtime code
+ Swig_register_filebyname("begin", f_wrap_cpp);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("post-init", f_post_init);
+
+ state.globals(FORCE_CPP, NewString("1"));
+
+ Swig_banner(f_wrap_cpp);
+
+ Swig_obligatory_macros(f_runtime, "JAVASCRIPT");
+
+ return SWIG_OK;
+}
+
+int V8Emitter::dump(Node *n) {
+ /* Get the module name */
+ String *module = Getattr(n, "name");
+
+ Template initializer_define(getTemplate("js_initializer_define"));
+ initializer_define.replace("$jsname", module).pretty_print(f_header);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printv(f_wrap_cpp, f_runtime, "\n", 0);
+ Printv(f_wrap_cpp, f_header, "\n", 0);
+ Printv(f_wrap_cpp, f_class_templates, "\n", 0);
+ Printv(f_wrap_cpp, f_wrappers, "\n", 0);
+
+ emitNamespaces();
+
+ // compose the initializer function using a template
+ // filled with sub-parts
+ Template initializer(getTemplate("js_initializer"));
+ initializer.replace("$jsname", moduleName)
+ .replace("$jsv8nspaces", f_init_namespaces)
+ .replace("$jsv8classtemplates", f_init_class_templates)
+ .replace("$jsv8wrappers", f_init_wrappers)
+ .replace("$jsv8inheritance", f_init_inheritance)
+ .replace("$jsv8classinstances", f_init_class_instances)
+ .replace("$jsv8staticwrappers", f_init_static_wrappers)
+ .replace("$jsv8registerclasses", f_init_register_classes)
+ .replace("$jsv8registernspaces", f_init_register_namespaces);
+ Printv(f_init, initializer.str(), 0);
+
+ Printv(f_wrap_cpp, f_init, 0);
+
+ Printv(f_wrap_cpp, f_post_init, 0);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::close() {
+ Delete(f_runtime);
+ Delete(f_header);
+ Delete(f_class_templates);
+ Delete(f_init_namespaces);
+ Delete(f_init_class_templates);
+ Delete(f_init_wrappers);
+ Delete(f_init_inheritance);
+ Delete(f_init_class_instances);
+ Delete(f_init_static_wrappers);
+ Delete(f_init_register_classes);
+ Delete(f_init_register_namespaces);
+ Delete(f_init);
+ Delete(f_post_init);
+ Delete(f_wrap_cpp);
+ return SWIG_OK;
+}
+
+int V8Emitter::enterClass(Node *n) {
+ JSEmitter::enterClass(n);
+
+ // emit declaration of a v8 class template
+ Template t_decl_class(getTemplate("jsv8_declare_class_template"));
+ t_decl_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .trim()
+ .pretty_print(f_class_templates);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::exitClass(Node *n) {
+ if (GetFlag(state.clazz(), IS_ABSTRACT)) {
+ Template t_veto_ctor(getTemplate("js_veto_ctor"));
+ t_veto_ctor.replace("$jswrapper", state.clazz(CTOR))
+ .replace("$jsname", state.clazz(NAME))
+ .pretty_print(f_wrappers);
+ }
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ String *clientData = NewString("");
+ Printf(clientData, "&%s_clientData", state.clazz(NAME_MANGLED));
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0"));
+
+ // emit definition of v8 class template
+ Template t_def_class = getTemplate("jsv8_define_class_template");
+ t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .trim()
+ .pretty_print(f_init_class_templates);
+
+ Template t_class_instance = getTemplate("jsv8_create_class_instance");
+ t_class_instance.replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsctor", state.clazz(CTOR))
+ .trim()
+ .pretty_print(f_init_class_instances);
+
+ // emit inheritance setup
+ Node *baseClass = getBaseClass(n);
+ if (baseClass) {
+ String *base_name = Getattr(baseClass, "name");
+
+ Template t_inherit = getTemplate("jsv8_inherit");
+
+ String *base_name_mangled = SwigType_manglestr(base_name);
+ t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsbaseclass", base_name_mangled)
+ .trim()
+ .pretty_print(f_init_inheritance);
+ Delete(base_name_mangled);
+ }
+ // emit registration of class template
+ Template t_register = getTemplate("jsv8_register_class");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsparent", Getattr(state.clazz("nspace"), NAME_MANGLED))
+ .trim()
+ .pretty_print(f_init_register_classes);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::enterVariable(Node *n) {
+ JSEmitter::enterVariable(n);
+
+ state.variable(GETTER, NULL_STR);
+ state.variable(SETTER, VETO_SET);
+
+ return SWIG_OK;
+}
+
+int V8Emitter::exitVariable(Node *n) {
+ if (GetFlag(n, "ismember")) {
+ if (GetFlag(state.variable(), IS_STATIC) || Equal(Getattr(n, "nodeType"), "enumitem")) {
+ Template t_register = getTemplate("jsv8_register_static_variable");
+ t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ } else {
+ Template t_register = getTemplate("jsv8_register_member_variable");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+ } else {
+ // Note: a global variable is treated like a static variable
+ // with the parent being a nspace object (instead of class object)
+ Template t_register = getTemplate("jsv8_register_static_variable");
+ t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+
+ return SWIG_OK;
+}
+
+int V8Emitter::exitFunction(Node *n) {
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+
+ // create a dispatcher for overloaded functions
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+ if (is_overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ //state.function(WRAPPER_NAME, Swig_name_wrapper(Getattr(n, "name")));
+ emitFunctionDispatcher(n, is_member);
+ } else {
+ //don't register wrappers of overloaded functions in function tables
+ return SWIG_OK;
+ }
+ }
+ // register the function at the specific context
+ if (is_member) {
+ if (GetFlag(state.function(), IS_STATIC)) {
+ Template t_register = getTemplate("jsv8_register_static_function");
+ t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ } else {
+ Template t_register = getTemplate("jsv8_register_member_function");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+ } else {
+ // Note: a global function is treated like a static function
+ // with the parent being a nspace object instead of class object
+ Template t_register = getTemplate("jsv8_register_static_function");
+ t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ }
+
+ return SWIG_OK;
+}
+
+void V8Emitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) {
+ Parm *p;
+ String *tm = NULL;
+
+ int startIdx = 0;
+ if (is_member && !is_static && mode != Ctor) {
+ startIdx = 1;
+ }
+ // store number of arguments for argument checks
+ int num_args = emit_num_arguments(parms) - startIdx;
+ String *argcount = NewString("");
+ Printf(argcount, "%d", num_args);
+ Setattr(n, ARGCOUNT, argcount);
+ int num_required = emit_num_required(parms) - startIdx;
+ SetInt(n, ARGREQUIRED, num_required);
+
+ int i = 0;
+ for (p = parms; p;) {
+ String *arg = NewString("");
+ String *type = Getattr(p, "type");
+
+ // ignore varargs
+ if (SwigType_isvarargs(type))
+ break;
+
+ switch (mode) {
+ case Getter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.Holder()", 0);
+ i++;
+ } else {
+ Printf(arg, "args[%d]", i - startIdx);
+ SetInt(p, INDEX, i - startIdx);
+ i += GetInt(p, "tmap:in:numinputs");
+ }
+ break;
+ case Function:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "args.Holder()", 0);
+ i++;
+ } else {
+ Printf(arg, "args[%d]", i - startIdx);
+ SetInt(p, INDEX, i - startIdx);
+ i += GetInt(p, "tmap:in:numinputs");
+ }
+ break;
+ case Setter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.Holder()", 0);
+ i++;
+ } else {
+ Printv(arg, "value", 0);
+ i++;
+ }
+ break;
+ case Ctor:
+ Printf(arg, "args[%d]", i);
+ SetInt(p, INDEX, i);
+ i += GetInt(p, "tmap:in:numinputs");
+ break;
+ default:
+ Printf(stderr, "Illegal MarshallingMode.");
+ Exit(EXIT_FAILURE);
+ }
+
+ tm = emitInputTypemap(n, p, wrapper, arg);
+ Delete(arg);
+
+ if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ for (p = parms; p;) {
+ tm = emitCheckTypemap(n, p, wrapper, Getattr(p, "emit:input"));
+ if (tm) {
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+int V8Emitter::emitNamespaces() {
+ Iterator it;
+ for (it = First(namespaces); it.item; it = Next(it)) {
+ Hash *entry = it.item;
+ String *name = Getattr(entry, NAME);
+ String *name_mangled = Getattr(entry, NAME_MANGLED);
+ String *parent = Getattr(entry, PARENT);
+ String *parent_mangled = Getattr(entry, PARENT_MANGLED);
+
+ bool do_create = true;
+ bool do_register = true;
+
+ if (Equal(parent, "")) {
+ do_register = false;
+ }
+ // Note: 'exports' is by convention the name of the object where
+ // globals are stored into
+ if (Equal(name, "exports")) {
+ do_create = false;
+ }
+
+ if (do_create) {
+ // create namespace object and register it to the parent scope
+ Template t_create_ns = getTemplate("jsv8_create_namespace");
+ t_create_ns.replace("$jsmangledname", name_mangled)
+ .trim()
+ .pretty_print(f_init_namespaces);
+ }
+
+ if (do_register) {
+ Template t_register_ns = getTemplate("jsv8_register_namespace");
+ t_register_ns.replace("$jsmangledname", name_mangled)
+ .replace("$jsname", name)
+ .replace("$jsparent", parent_mangled)
+ .trim();
+
+ // prepend in order to achieve reversed order of registration statements
+ String *tmp_register_stmt = NewString("");
+ t_register_ns.pretty_print(tmp_register_stmt);
+ Insert(f_init_register_namespaces, 0, tmp_register_stmt);
+ Delete(tmp_register_stmt);
+ }
+ }
+
+ return SWIG_OK;
+}
+
+/**********************************************************************
+ * NAPI: JSEmitter implementation for N-API
+ **********************************************************************/
+
+class NAPIEmitter:public JSEmitter {
+public:
+ NAPIEmitter();
+
+ virtual ~NAPIEmitter();
+ virtual int initialize(Node *n);
+ virtual int dump(Node *n);
+ virtual int close();
+ virtual int enterClass(Node *n);
+ virtual int exitClass(Node *n);
+ virtual int enterVariable(Node *n);
+ virtual int exitVariable(Node *n);
+ virtual int exitFunction(Node *n);
+
+protected:
+ virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static);
+ virtual int emitNamespaces();
+ virtual int emitCtor(Node *);
+ virtual int emitDtor(Node *);
+ virtual int emitClassMethodDeclaration(Node *);
+
+ virtual const char *getFunctionTemplate(bool is_member);
+ virtual const char *getFunctionDispatcherTemplate(bool is_member);
+ virtual const char *getOverloadedFunctionTemplate(bool is_member);
+ virtual const char *getSetterTemplate(bool is_member);
+ virtual const char *getGetterTemplate(bool is_member);
+
+protected:
+ /* built-in parts */
+ String *f_runtime;
+ String *f_header;
+ String *f_init;
+ String *f_post_init;
+
+ /* class declarations */
+ String *f_class_declarations;
+
+ /* parts for initilizer */
+ String *f_init_namespaces;
+ String *f_init_wrappers;
+ String *f_init_inheritance;
+ String *f_init_static_wrappers;
+ String *f_init_register_classes;
+ String *f_init_register_namespaces;
+
+ // the output cpp file
+ File *f_wrap_cpp;
+
+ String *NULL_STR;
+ String *VETO_SET;
+ String *moduleName;
+
+ // the current index in the class table
+ size_t class_idx;
+};
+
+NAPIEmitter::NAPIEmitter()
+: JSEmitter(JSEmitter::NAPI), NULL_STR(NewString("0")), VETO_SET(NewString("JS_veto_set_variable")), class_idx(0) {
+}
+
+NAPIEmitter::~NAPIEmitter() {
+ Delete(NULL_STR);
+ Delete(VETO_SET);
+}
+
+int NAPIEmitter::initialize(Node *n) {
+ JSEmitter::initialize(n);
+
+ moduleName = Getattr(n, "name");
+
+ // Get the output file name
+ String *outfile = Getattr(n, "outfile");
+ f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_wrap_cpp) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ f_runtime = NewString("");
+ f_header = NewString("");
+ f_init = NewString("");
+ f_post_init = NewString("");
+
+ f_class_declarations = NewString("");
+
+ f_init_namespaces = NewString("");
+ f_init_wrappers = NewString("");
+ f_init_inheritance = NewString("");
+ f_init_static_wrappers = NewString("");
+ f_init_register_classes = NewString("");
+ f_init_register_namespaces = NewString("");
+
+ // note: this is necessary for built-in generation of SWIG runtime code
+ Swig_register_filebyname("begin", f_wrap_cpp);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("post-init", f_post_init);
+
+ state.globals(FORCE_CPP, NewString("1"));
+
+ Swig_banner(f_wrap_cpp);
+
+ Swig_obligatory_macros(f_runtime, "JAVASCRIPT");
+
+ return SWIG_OK;
+}
+
+int NAPIEmitter::dump(Node *n) {
+ /* Get the module name */
+ String *module = Getattr(n, "name");
+
+ Template initializer_define(getTemplate("js_initializer_define"));
+ initializer_define.replace("$jsname", module).pretty_print(f_header);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printv(f_wrap_cpp, f_runtime, "\n", 0);
+ Printv(f_wrap_cpp, f_header, "\n", 0);
+ Printv(f_wrap_cpp, f_class_declarations, "\n", 0);
+ Printv(f_wrap_cpp, f_wrappers, "\n", 0);
+
+ emitNamespaces();
+
+ String *inheritance = NewStringEmpty();
+ if (Len(f_init_inheritance) > 0) {
+ Template t_inheritance(getTemplate("js_init_inheritance"));
+ t_inheritance.pretty_print(inheritance);
+ }
+
+ // compose the initializer function using a template
+ // filled with sub-parts
+ Template initializer(getTemplate("js_initializer"));
+ initializer.replace("$jsname", moduleName)
+ .replace("$jsnapinspaces", f_init_namespaces)
+ .replace("$jsnapipreinheritance", inheritance)
+ .replace("$jsnapiinitinheritance", f_init_inheritance)
+ .replace("$jsnapiregisterclasses", f_init_register_classes)
+ .replace("$jsnapiregisternspaces", f_init_register_namespaces);
+ Printv(f_init, initializer.str(), 0);
+
+ Printv(f_wrap_cpp, f_init, 0);
+
+ Printv(f_wrap_cpp, f_post_init, 0);
+
+ Delete(inheritance);
+ return SWIG_OK;
+}
+
+int NAPIEmitter::close() {
+ Delete(f_runtime);
+ Delete(f_header);
+ Delete(f_class_declarations);
+ Delete(f_init_namespaces);
+ Delete(f_init_wrappers);
+ Delete(f_init_inheritance);
+ Delete(f_init_static_wrappers);
+ Delete(f_init_register_classes);
+ Delete(f_init_register_namespaces);
+ Delete(f_init);
+ Delete(f_post_init);
+ Delete(f_wrap_cpp);
+ return SWIG_OK;
+}
+
+const char *NAPIEmitter::getFunctionTemplate(bool is_member) {
+ return is_member ? "js_function" : "js_global_function";
+}
+
+const char *NAPIEmitter::getFunctionDispatcherTemplate(bool is_member) {
+ return is_member ? "js_function_dispatcher" : "js_global_function_dispatcher";
+}
+
+const char *NAPIEmitter::getOverloadedFunctionTemplate(bool is_member) {
+ return is_member ? "js_overloaded_function" : "js_global_overloaded_function";
+}
+
+const char *NAPIEmitter::getGetterTemplate(bool is_member) {
+ return is_member ? "js_getter" : "js_global_getter";
+}
+
+const char *NAPIEmitter::getSetterTemplate(bool is_member) {
+ return is_member ? "js_setter" : "js_global_setter";
+}
+
+int NAPIEmitter::enterClass(Node *n) {
+ JSEmitter::enterClass(n);
+
+ // emit registration of class template
+ String *idx = NewString("");
+ Printf(idx, "%d", class_idx++);
+ Template t_register = getTemplate("jsnapi_registerclass");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsparent", Getattr(state.clazz("nspace"), NAME_MANGLED))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsclassidx", idx)
+ .trim()
+ .pretty_print(f_init_register_classes);
+ Delete(idx);
+
+ // emit inheritance
+ String *baseMangled;
+ Node *baseClass = getBaseClass(n);
+ SetFlag(n, IS_WRAPPED);
+ if (baseClass && GetFlag(baseClass, IS_WRAPPED)) {
+ String *jsName = NewString("");
+ String *nspace = Getattr(baseClass, "sym:nspace");
+ if (Len(nspace) == 0)
+ nspace = Getattr(current_namespace, NAME_MANGLED);
+ Printf(jsName, "%s_%s", nspace, Getattr(baseClass, "sym:name"));
+ baseMangled = SwigType_manglestr(jsName);
+ Delete(jsName);
+
+ f_init_wrappers = Copy(Getattr(baseClass, MEMBER_FUNCTIONS));
+ f_init_static_wrappers = Copy(Getattr(baseClass, STATIC_FUNCTIONS));
+ } else {
+ baseMangled = NewString("SWIG_NAPI_ObjectWrap");
+ f_init_wrappers = NewString("");
+ f_init_static_wrappers = NewString("");
+ }
+ state.clazz(PARENT_MANGLED, baseMangled);
+
+ Template t_setup_inheritance(getTemplate("jsnapi_setup_inheritance"));
+ t_setup_inheritance.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", state.clazz(CTOR))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsparent", baseMangled)
+ .pretty_print(f_init_inheritance);
+
+ // emit declaration of a NAPI class template
+ Template t_decl_class(getTemplate("jsnapi_class_prologue_template"));
+ t_decl_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsparent", baseMangled)
+ .trim()
+ .pretty_print(f_class_declarations);
+
+ Delete(baseMangled);
+ return SWIG_OK;
+}
+
+int NAPIEmitter::exitClass(Node *n) {
+ if (GetFlag(state.clazz(), IS_ABSTRACT)) {
+ Template t_veto_ctor(getTemplate("js_veto_ctor"));
+ t_veto_ctor.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", state.clazz(CTOR))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsparent", state.clazz(PARENT_MANGLED))
+ .pretty_print(f_wrappers);
+ }
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ String *clientData = NewString("");
+ Printf(clientData, "&%s_clientData", state.clazz(NAME_MANGLED));
+
+ /* Note: this makes sure that there is a swig_type added for this class */
+ SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0"));
+
+ // emit definition of NAPI class template
+ Template t_def_class = getTemplate("jsnapi_class_epilogue_template");
+ t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .trim()
+ .pretty_print(f_class_declarations);
+
+ Template t_class_instance = getTemplate("jsnapi_declare_class_instance");
+ t_class_instance.replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .trim()
+ .pretty_print(f_class_declarations);
+
+ Template t_class_template = getTemplate("jsnapi_getclass");
+ t_class_template.replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsnapiwrappers", f_init_wrappers)
+ .replace("$jsnapistaticwrappers", f_init_static_wrappers)
+ .replace("$jsparent", state.clazz(PARENT_MANGLED))
+ .trim()
+ .pretty_print(f_class_declarations);
+
+ /* Save these to be reused in the child classes */
+ Setattr(n, MEMBER_FUNCTIONS, f_init_wrappers);
+ Setattr(n, STATIC_FUNCTIONS, f_init_static_wrappers);
+ return SWIG_OK;
+}
+
+int NAPIEmitter::enterVariable(Node *n) {
+ // Somehow, this is not always reset
+ // (some constructs like smart pointers reuse Nodes)
+ UnsetFlag(n, "constant");
+
+ JSEmitter::enterVariable(n);
+
+ state.variable(GETTER, VETO_SET);
+ state.variable(SETTER, VETO_SET);
+
+ return SWIG_OK;
+}
+
+int NAPIEmitter::exitVariable(Node *n) {
+ // Due to special handling of C++ "static const" member variables
+ // (refer to the comment in lang.cxx:Language::staticmembervariableHandler)
+ // a static const member variable may get transformed into a constant
+ // and be emitted by emitConstant which will result calling exitVariable twice
+ if (GetFlag(n, "constant")) {
+ return SWIG_OK;
+ }
+
+ if (GetFlag(n, "ismember")) {
+ String *modifier = NewStringEmpty();
+ if (GetFlag(state.variable(), IS_STATIC) || Equal(Getattr(n, "nodeType"), "enumitem")) {
+ Template t_register = getTemplate("jsnapi_register_static_variable");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER) != VETO_SET ? state.variable(SETTER)
+ : "JS_veto_set_static_variable")
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ Append(modifier, "static");
+ } else {
+ Template t_register = getTemplate("jsnapi_register_member_variable");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+
+ // emit declaration of a class member function
+ Template t_getter = getTemplate("jsnapi_class_method_declaration");
+ t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .replace("$jswrapper", state.variable(GETTER))
+ .replace("$jsstatic", modifier)
+ .trim()
+ .pretty_print(f_class_declarations);
+ if (state.variable(SETTER) != VETO_SET) {
+ Template t_setter = getTemplate("jsnapi_class_setter_declaration");
+ t_setter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .replace("$jswrapper", state.variable(SETTER))
+ .replace("$jsstatic", modifier)
+ .trim()
+ .pretty_print(f_class_declarations);
+ }
+ Delete(modifier);
+ } else {
+ Template t_register = getTemplate("jsnapi_register_global_variable");
+ t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
+ .replace("$jsname", state.variable(NAME))
+ .replace("$jsgetter", state.variable(GETTER))
+ .replace("$jssetter", state.variable(SETTER))
+ .trim()
+ .pretty_print(f_init_register_namespaces);
+ }
+
+ return SWIG_OK;
+}
+
+int NAPIEmitter::emitClassMethodDeclaration(Node *) {
+ // emit declaration of a class member function
+ Template t_def_class = getTemplate("jsnapi_class_method_declaration");
+ t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.clazz(NAME))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsdtor", state.clazz(DTOR))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .replace("$jsstatic", GetFlag(state.function(), IS_STATIC) ? "static" : "")
+ .trim()
+ .pretty_print(f_class_declarations);
+
+ return SWIG_OK;
+}
+
+int NAPIEmitter::exitFunction(Node *n) {
+ bool is_member = GetFlag(n, "ismember") != 0 || GetFlag(n, "feature:extend") != 0;
+
+ // create a dispatcher for overloaded functions
+ bool is_overloaded = GetFlag(n, "sym:overloaded") != 0;
+ if (is_overloaded) {
+ emitClassMethodDeclaration(n);
+ if (!Getattr(n, "sym:nextSibling")) {
+ emitFunctionDispatcher(n, is_member);
+ } else {
+ return SWIG_OK;
+ }
+ }
+ // register the function at the specific context
+ if (is_member) {
+ if (GetFlag(state.function(), IS_STATIC)) {
+ Template t_register = getTemplate("jsnapi_register_static_function");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_static_wrappers);
+ } else {
+ Template t_register = getTemplate("jsnapi_register_member_function");
+ t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_wrappers);
+ }
+
+ emitClassMethodDeclaration(n);
+ } else {
+ // Note: a global function is treated like a static function
+ // with the parent being a nspace object instead of class object
+ Template t_register = getTemplate("jsnapi_register_global_function");
+ t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED))
+ .replace("$jsname", state.function(NAME))
+ .replace("$jswrapper", state.function(WRAPPER_NAME))
+ .trim()
+ .pretty_print(f_init_register_namespaces);
+ }
+
+ return SWIG_OK;
+}
+
+void NAPIEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) {
+ Parm *p;
+ String *tm;
+
+ int startIdx = 0;
+ if (is_member && !is_static && mode != Ctor) {
+ startIdx = 1;
+ }
+ // store number of arguments for argument checks
+ int num_args = emit_num_arguments(parms) - startIdx;
+ String *argcount = NewString("");
+ Printf(argcount, "%d", num_args);
+ Setattr(n, ARGCOUNT, argcount);
+ int num_required = emit_num_required(parms) - startIdx;
+ SetInt(n, ARGREQUIRED, num_required);
+
+ int i = 0;
+ for (p = parms; p;) {
+ String *arg = NewString("");
+ String *type = Getattr(p, "type");
+
+ // ignore varargs
+ if (SwigType_isvarargs(type))
+ break;
+
+ switch (mode) {
+ case Getter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.This()", 0);
+ i++;
+ } else {
+ Printf(arg, "info[%d]", i - startIdx);
+ SetInt(p, INDEX, i - startIdx);
+ i += GetInt(p, "tmap:in:numinputs");
+ }
+ break;
+ case Function:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.This()", 0);
+ i++;
+ } else {
+ Printf(arg, "info[%d]", i - startIdx);
+ SetInt(p, INDEX, i - startIdx);
+ i += GetInt(p, "tmap:in:numinputs");
+ }
+ break;
+ case Setter:
+ if (is_member && !is_static && i == 0) {
+ Printv(arg, "info.This()", 0);
+ i++;
+ } else {
+ Printv(arg, "value", 0);
+ i++;
+ }
+ break;
+ case Ctor:
+ Printf(arg, "info[%d]", i);
+ SetInt(p, INDEX, i - startIdx);
+ i += GetInt(p, "tmap:in:numinputs");
+ break;
+ default:
+ Printf(stderr, "Illegal MarshallingMode.");
+ Exit(EXIT_FAILURE);
+ }
+
+ tm = emitInputTypemap(n, p, wrapper, arg);
+ Delete(arg);
+
+ if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ for (p = parms; p;) {
+ tm = emitCheckTypemap(n, p, wrapper, Getattr(p, "emit:input"));
+ if (tm) {
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+}
+
+int NAPIEmitter::emitNamespaces() {
+ Iterator it;
+ for (it = First(namespaces); it.item; it = Next(it)) {
+ Hash *entry = it.item;
+ String *name = Getattr(entry, NAME);
+ String *name_mangled = Getattr(entry, NAME_MANGLED);
+ String *parent = Getattr(entry, PARENT);
+ String *parent_mangled = Getattr(entry, PARENT_MANGLED);
+
+ bool do_create = true;
+ bool do_register = true;
+
+ if (Equal(parent, "")) {
+ do_register = false;
+ }
+ // Note: 'exports' is by convention the name of the object where
+ // globals are stored into
+ if (Equal(name, "exports")) {
+ do_create = false;
+ }
+
+ if (do_create) {
+ // create namespace object and register it to the parent scope
+ Template t_create_ns = getTemplate("jsnapi_create_namespace");
+ t_create_ns.replace("$jsmangledname", name_mangled)
+ .trim()
+ .pretty_print(f_init_namespaces);
+ }
+
+ if (do_register) {
+ Template t_register_ns = getTemplate("jsnapi_register_namespace");
+ t_register_ns.replace("$jsmangledname", name_mangled)
+ .replace("$jsname", name)
+ .replace("$jsparent", parent_mangled)
+ .trim();
+
+ // prepend in order to achieve reversed order of registration statements
+ String *tmp_register_stmt = NewString("");
+ t_register_ns.pretty_print(tmp_register_stmt);
+ Insert(f_init_register_namespaces, 0, tmp_register_stmt);
+ Delete(tmp_register_stmt);
+ }
+ }
+
+ return SWIG_OK;
+}
+
+int NAPIEmitter::emitCtor(Node *n) {
+ int r = JSEmitter::emitCtor(n);
+ if (r != SWIG_OK)
+ return r;
+
+ Template t_getter = getTemplate("jsnapi_class_method_declaration");
+ t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .replace("$jswrapper", Getattr(n, "wrap:name"))
+ .replace("$jsmangledtype", state.clazz(TYPE_MANGLED))
+ .replace("$jsstatic", "")
+ .trim()
+ .pretty_print(f_class_declarations);
+ return SWIG_OK;
+}
+
+int NAPIEmitter::emitDtor(Node *n) {
+ // NAPI destructors must have a class declaration
+ Template t_getter = getTemplate("jsnapi_class_dtor_declaration");
+ t_getter.replace("$jsmangledname", state.clazz(NAME_MANGLED))
+ .trim()
+ .pretty_print(f_class_declarations);
+ return JSEmitter::emitDtor(n);
+}
+
+JSEmitter *swig_javascript_create_V8Emitter() {
+ return new V8Emitter();
+}
+
+JSEmitter *swig_javascript_create_NAPIEmitter() {
+ return new NAPIEmitter();
+}
+
+/**********************************************************************
+ * Helper implementations
+ **********************************************************************/
+
+JSEmitterState::JSEmitterState()
+: globalHash(NewHash()) {
+ // initialize sub-hashes
+ Setattr(globalHash, "class", NewHash());
+ Setattr(globalHash, "function", NewHash());
+ Setattr(globalHash, "variable", NewHash());
+}
+
+JSEmitterState::~JSEmitterState() {
+ Delete(globalHash);
+}
+
+DOH *JSEmitterState::getState(const char *key, bool new_key) {
+ if (new_key) {
+ Hash *hash = NewHash();
+ Setattr(globalHash, key, hash);
+ }
+ return Getattr(globalHash, key);
+}
+
+DOH *JSEmitterState::globals() {
+ return globalHash;
+}
+
+DOH *JSEmitterState::globals(const char *key, DOH *initial) {
+ if (initial != 0) {
+ Setattr(globalHash, key, initial);
+ }
+ return Getattr(globalHash, key);
+}
+
+DOH *JSEmitterState::clazz(bool new_key) {
+ return getState("class", new_key);
+}
+
+DOH *JSEmitterState::clazz(const char *key, DOH *initial) {
+ DOH *c = clazz();
+ if (initial != 0) {
+ Setattr(c, key, initial);
+ }
+ return Getattr(c, key);
+}
+
+DOH *JSEmitterState::function(bool new_key) {
+ return getState("function", new_key);
+}
+
+DOH *JSEmitterState::function(const char *key, DOH *initial) {
+ DOH *f = function();
+ if (initial != 0) {
+ Setattr(f, key, initial);
+ }
+ return Getattr(f, key);
+}
+
+DOH *JSEmitterState::variable(bool new_key) {
+ return getState("variable", new_key);
+}
+
+DOH *JSEmitterState::variable(const char *key, DOH *initial) {
+ DOH *v = variable();
+ if (initial != 0) {
+ Setattr(v, key, initial);
+ }
+ return Getattr(v, key);
+}
+
+/*static*/
+int JSEmitterState::IsSet(DOH *val) {
+ if (!val) {
+ return 0;
+ } else {
+ const char *cval = Char(val);
+ if (!cval)
+ return 0;
+ return (strcmp(cval, "0") != 0) ? 1 : 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Template::Template() : creates a Template class for given template code
+ * ----------------------------------------------------------------------------- */
+
+Template::Template(const String *code_) {
+
+ if (!code_) {
+ Printf(stdout, "Template code was null. Illegal input for template.");
+ Exit(EXIT_FAILURE);
+ }
+ code = NewString(code_);
+ templateName = NewString("");
+}
+
+Template::Template(const String *code_, const String *templateName_) {
+
+ if (!code_) {
+ Printf(stdout, "Template code was null. Illegal input for template.");
+ Exit(EXIT_FAILURE);
+ }
+
+ code = NewString(code_);
+ templateName = NewString(templateName_);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Template::~Template() : cleans up of Template.
+ * ----------------------------------------------------------------------------- */
+
+Template::~Template() {
+ Delete(code);
+ Delete(templateName);
+}
+
+/* -----------------------------------------------------------------------------
+ * String* Template::str() : retrieves the current content of the template.
+ * ----------------------------------------------------------------------------- */
+
+String *Template::str() {
+ if (js_template_enable_debug) {
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *debug_code = NewString("");
+ Printf(pre_code, "/* begin fragment(\"%s\") */", templateName);
+ Printf(post_code, "/* end fragment(\"%s\") */", templateName);
+ Printf(debug_code, "%s\n%s\n%s\n", pre_code, code, post_code);
+
+ Delete(code);
+ Delete(pre_code);
+ Delete(post_code);
+
+ code = debug_code;
+ }
+ return code;
+}
+
+Template & Template::trim() {
+ const char *str = Char(code);
+ if (str == 0)
+ return *this;
+
+ int length = Len(code);
+ if (length == 0)
+ return *this;
+
+ int idx;
+ for (idx = 0; idx < length; ++idx) {
+ if (str[idx] != ' ' && str[idx] != '\t' && str[idx] != '\r' && str[idx] != '\n')
+ break;
+ }
+ int start_pos = idx;
+
+ for (idx = length - 1; idx >= start_pos; --idx) {
+ if (str[idx] != ' ' && str[idx] != '\t' && str[idx] != '\r' && str[idx] != '\n')
+ break;
+ }
+ int end_pos = idx;
+
+ int new_length = end_pos - start_pos + 1;
+ char *newstr = new char[new_length + 1];
+ memcpy(newstr, str + start_pos, new_length);
+ newstr[new_length] = 0;
+
+ Delete(code);
+ code = NewString(newstr);
+ delete[]newstr;
+
+ return *this;
+}
+
+/* -----------------------------------------------------------------------------
+ * Template& Template::replace(const String* pattern, const String* repl) :
+ *
+ * replaces all occurrences of a given pattern with a given replacement.
+ *
+ * - pattern: the pattern to be replaced
+ * - repl: the replacement string
+ * - returns a reference to the Template to allow chaining of methods.
+ * ----------------------------------------------------------------------------- */
+
+Template & Template::replace(const String *pattern, const String *repl) {
+ Replaceall(code, pattern, repl);
+ return *this;
+}
+
+Template & Template::print(DOH *doh) {
+ Printv(doh, str(), 0);
+ return *this;
+}
+
+Template & Template::pretty_print(DOH *doh) {
+ Wrapper_pretty_print(str(), doh);
+ return *this;
+}
+
+Template::Template(const Template & t) {
+ code = NewString(t.code);
+ templateName = NewString(t.templateName);
+}
+
+void Template::operator=(const Template & t) {
+ Delete(code);
+ Delete(templateName);
+ code = NewString(t.code);
+ templateName = NewString(t.templateName);
+}
diff --git a/contrib/tools/swig/Source/Modules/lang.cxx b/contrib/tools/swig/Source/Modules/lang.cxx
new file mode 100644
index 00000000000..33a824e1143
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/lang.cxx
@@ -0,0 +1,3768 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * lang.cxx
+ *
+ * Language base class functions. Default C++ handling is also implemented here.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* default mode settings */
+static int directors_allowed = 0;
+static int director_language = 0;
+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;
+
+int Swig_directors_enabled() {
+ return director_language && CPlusPlus && (directors_allowed || director_mode);
+}
+
+void Wrapper_director_mode_set(int flag) {
+ director_mode = flag;
+}
+
+void Wrapper_director_protected_mode_set(int flag) {
+ director_protected_mode = flag;
+}
+
+void Wrapper_all_protected_mode_set(int flag) {
+ all_protected_mode = flag;
+}
+
+void Wrapper_naturalvar_mode_set(int flag) {
+ naturalvar_mode = flag;
+}
+
+extern "C" {
+ int Swig_director_mode() {
+ return director_mode;
+ }
+ int Swig_director_protected_mode() {
+ return director_protected_mode;
+ }
+ int Swig_all_protected_mode() {
+ return all_protected_mode;
+ }
+ void Language_replace_special_variables(String *method, String *tm, Parm *parm) {
+ Language::instance()->replaceSpecialVariables(method, tm, parm);
+ }
+}
+
+/* Some status variables used during parsing */
+static int InClass = 0; /* Parsing C++ or not */
+static String *ClassName = 0; /* This is the real name of the current class */
+static String *EnumClassName = 0; /* Enum class name */
+static String *ClassPrefix = 0; /* Class prefix */
+static String *EnumClassPrefix = 0; /* Prefix for strongly typed enums (including ClassPrefix) */
+static String *NSpace = 0; /* Namespace for the nspace feature */
+static String *ClassType = 0; /* Fully qualified type name to use */
+static String *DirectorClassName = 0; /* Director name of the current class */
+int Abstract = 0;
+int ImportMode = 0;
+int IsVirtual = 0;
+static String *AttributeFunctionGet = 0;
+static String *AttributeFunctionSet = 0;
+static Node *CurrentClass = 0;
+int line_number = 0;
+String *input_file = 0;
+int SmartPointer = 0;
+static Hash *classhash;
+
+extern int ForceExtern;
+extern int AddExtern;
+extern "C" {
+ extern int UseWrapperSuffix;
+}
+
+/* import modes */
+
+#define IMPORT_MODE 1
+
+/* ----------------------------------------------------------------------
+ * Dispatcher::emit_one()
+ *
+ * Dispatch a single node
+ * ---------------------------------------------------------------------- */
+
+int Dispatcher::emit_one(Node *n) {
+ int ret = SWIG_OK;
+
+ char *tag = Char(nodeType(n));
+ if (!tag) {
+ /* Printf(stderr,"SWIG: Fatal internal error. Malformed parse tree
+ node!\n"); */
+ return SWIG_OK;
+ }
+
+ /* Do not proceed if marked with an error */
+
+ if (Getattr(n, "error"))
+ return SWIG_OK;
+
+ /* Look for warnings */
+ String *wrn = Getattr(n, "feature:warnfilter");
+ if (wrn)
+ Swig_warnfilter(wrn, 1);
+
+ /* ============================================================
+ * C/C++ parsing
+ * ============================================================ */
+
+ if (strcmp(tag, "extern") == 0) {
+ ret = externDeclaration(n);
+ } else if (strcmp(tag, "cdecl") == 0) {
+ ret = cDeclaration(n);
+ } else if (strcmp(tag, "enum") == 0) {
+ ret = enumDeclaration(n);
+ } else if (strcmp(tag, "enumitem") == 0) {
+ ret = enumvalueDeclaration(n);
+ } else if (strcmp(tag, "enumforward") == 0) {
+ ret = enumforwardDeclaration(n);
+ } else if (strcmp(tag, "class") == 0) {
+ ret = classDeclaration(n);
+ } else if (strcmp(tag, "classforward") == 0) {
+ ret = classforwardDeclaration(n);
+ } else if (strcmp(tag, "constructor") == 0) {
+ ret = constructorDeclaration(n);
+ } else if (strcmp(tag, "destructor") == 0) {
+ ret = destructorDeclaration(n);
+ } else if (strcmp(tag, "access") == 0) {
+ ret = accessDeclaration(n);
+ } else if (strcmp(tag, "using") == 0) {
+ ret = usingDeclaration(n);
+ } else if (strcmp(tag, "namespace") == 0) {
+ ret = namespaceDeclaration(n);
+ } else if (strcmp(tag, "template") == 0) {
+ ret = templateDeclaration(n);
+ } else if (strcmp(tag, "lambda") == 0) {
+ ret = lambdaDeclaration(n);
+ }
+
+ /* ===============================================================
+ * SWIG directives
+ * =============================================================== */
+
+ else if (strcmp(tag, "top") == 0) {
+ ret = top(n);
+ } else if (strcmp(tag, "extend") == 0) {
+ ret = extendDirective(n);
+ } else if (strcmp(tag, "apply") == 0) {
+ ret = applyDirective(n);
+ } else if (strcmp(tag, "clear") == 0) {
+ ret = clearDirective(n);
+ } else if (strcmp(tag, "constant") == 0) {
+ ret = constantDirective(n);
+ } else if (strcmp(tag, "fragment") == 0) {
+ ret = fragmentDirective(n);
+ } else if (strcmp(tag, "import") == 0) {
+ ret = importDirective(n);
+ } else if (strcmp(tag, "include") == 0) {
+ ret = includeDirective(n);
+ } else if (strcmp(tag, "insert") == 0) {
+ ret = insertDirective(n);
+ } else if (strcmp(tag, "module") == 0) {
+ ret = moduleDirective(n);
+ } else if (strcmp(tag, "native") == 0) {
+ ret = nativeDirective(n);
+ } else if (strcmp(tag, "pragma") == 0) {
+ ret = pragmaDirective(n);
+ } else if (strcmp(tag, "typemap") == 0) {
+ ret = typemapDirective(n);
+ } else if (strcmp(tag, "typemapcopy") == 0) {
+ ret = typemapcopyDirective(n);
+ } else if (strcmp(tag, "typemapitem") == 0) {
+ ret = typemapitemDirective(n);
+ } else if (strcmp(tag, "types") == 0) {
+ ret = typesDirective(n);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized parse tree node type '%s'\n", tag);
+ ret = SWIG_ERROR;
+ }
+ if (wrn)
+ Swig_warnfilter(wrn, 0);
+ return ret;
+}
+
+/* ----------------------------------------------------------------------
+ * Dispatcher::emit_children()
+ *
+ * Emit all children that match the given type. type = 0 means all types.
+ * ---------------------------------------------------------------------- */
+
+int Dispatcher::emit_children(Node *n) {
+ Node *c;
+ char *eo = Char(Getattr(n, "feature:emitonlychildren"));
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ if (eo) {
+ const char *tag = Char(nodeType(c));
+ if (strcmp(tag, "cdecl") == 0) {
+ if (checkAttribute(c, "storage", "typedef"))
+ tag = "typedef";
+ }
+ if (strstr(eo, tag) == 0) {
+ continue;
+ }
+ }
+ emit_one(c);
+ }
+ return SWIG_OK;
+}
+
+
+/* Stubs for dispatcher class. We don't do anything by default---up to derived class
+ to fill in traversal code */
+
+int Dispatcher::defaultHandler(Node *) {
+ return SWIG_OK;
+}
+
+int Dispatcher::extendDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::applyDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::clearDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::constantDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::fragmentDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::importDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::includeDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::insertDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::moduleDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::nativeDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::pragmaDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::typemapDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::typemapitemDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::typemapcopyDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::typesDirective(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::cDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::externDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::enumDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::enumvalueDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::enumforwardDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::classDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::templateDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::lambdaDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::classforwardDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::constructorDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::destructorDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::accessDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::usingDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+int Dispatcher::namespaceDeclaration(Node *n) {
+ return defaultHandler(n);
+}
+
+Dispatcher::AccessMode Dispatcher::accessModeFromString(String *access) {
+ Dispatcher::AccessMode mode = PUBLIC;
+ if (Cmp(access, "public") == 0) {
+ mode = PUBLIC;
+ } else if (Cmp(access, "private") == 0) {
+ mode = PRIVATE;
+ } else if (Cmp(access, "protected") == 0) {
+ mode = PROTECTED;
+ } else {
+ assert(0);
+ }
+ return mode;
+}
+
+
+/* Allocators */
+Language::Language():
+none_comparison(NewString("$arg != 0")),
+director_ctor_code(NewString("")),
+director_prot_ctor_code(0),
+director_multiple_inheritance(1),
+doxygenTranslator(NULL),
+symtabs(NewHash()),
+overloading(0),
+multiinput(0),
+cplus_runtime(0) {
+ symbolAddScope(""); // create top level/global symbol table scope
+ argc_template_string = NewString("argc");
+ argv_template_string = NewString("argv[%d]");
+
+ /* Default director constructor code, passed to Swig_ConstructorToFunction */
+ Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL);
+
+ assert(!this_);
+ this_ = this;
+}
+
+Language::~Language() {
+ Delete(symtabs);
+ Delete(director_ctor_code);
+ Delete(none_comparison);
+ this_ = 0;
+}
+
+ /* -----------------------------------------------------------------------------
+ * directorClassName()
+ * ----------------------------------------------------------------------------- */
+
+ String *Language::directorClassName(Node *n) {
+ String *dirclassname;
+ String *nspace = NewString(Getattr(n, "sym:nspace"));
+ const char *attrib = "director:classname";
+ String *classname = getClassPrefix();
+
+ Replace(nspace, NSPACE_SEPARATOR, "_", DOH_REPLACE_ANY);
+ if (Len(nspace) > 0)
+ dirclassname = NewStringf("SwigDirector_%s_%s", nspace, classname);
+ else
+ dirclassname = NewStringf("SwigDirector_%s", classname);
+ Setattr(n, attrib, dirclassname);
+
+ Delete(nspace);
+ return dirclassname;
+ }
+
+/* ----------------------------------------------------------------------
+ emit_one()
+ ---------------------------------------------------------------------- */
+
+int Language::emit_one(Node *n) {
+ int ret;
+ int oldext;
+ if (!n)
+ return SWIG_OK;
+
+ if (GetFlag(n, "feature:ignore")
+ && !Getattr(n, "feature:onlychildren"))
+ return SWIG_OK;
+
+ oldext = Extend;
+ if (Getattr(n, "feature:extend"))
+ Extend = 1;
+
+ line_number = Getline(n);
+ input_file = Getfile(n);
+
+ /*
+ symtab = Getattr(n,"symtab");
+ if (symtab) {
+ symtab = Swig_symbol_setscope(symtab);
+ }
+ */
+ ret = Dispatcher::emit_one(n);
+ /*
+ if (symtab) {
+ Swig_symbol_setscope(symtab);
+ }
+ */
+ Extend = oldext;
+ return ret;
+}
+
+
+static Parm *nonvoid_parms(Parm *p) {
+ if (p) {
+ SwigType *t = Getattr(p, "type");
+ if (SwigType_type(t) == T_VOID)
+ return 0;
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * cplus_value_type()
+ *
+ * Returns the alternative value type needed in C++ for class value
+ * types. When swig is not sure about using a plain $ltype value,
+ * since the class doesn't have a default constructor, or it can't be
+ * assigned, you will get back 'SwigValueWrapper<(type)>'.
+ *
+ * ----------------------------------------------------------------------------- */
+
+SwigType *cplus_value_type(SwigType *t) {
+ return SwigType_alttype(t, 0);
+}
+
+static Node *first_nontemplate(Node *n) {
+ while (n) {
+ if (Strcmp(nodeType(n), "template") != 0)
+ return n;
+ n = Getattr(n, "sym:nextSibling");
+ }
+ return n;
+}
+
+
+
+/* --------------------------------------------------------------------------
+ * swig_pragma()
+ *
+ * Handle swig pragma directives.
+ * -------------------------------------------------------------------------- */
+
+static void swig_pragma(char *lang, char *name, char *value) {
+ if (strcmp(lang, "swig") == 0) {
+ if (strcmp(name, "attributefunction") == 0) {
+ String *nvalue = NewString(value);
+ char *s = strchr(Char(nvalue), ':');
+ if (!s) {
+ Swig_error(input_file, line_number, "Bad value for attributefunction. Expected \"fmtget:fmtset\".\n");
+ } else {
+ *s = 0;
+ AttributeFunctionGet = NewString(Char(nvalue));
+ AttributeFunctionSet = NewString(s + 1);
+ }
+ Delete(nvalue);
+ } else if (strcmp(name, "noattributefunction") == 0) {
+ AttributeFunctionGet = 0;
+ AttributeFunctionSet = 0;
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------
+ * Language::use_naturalvar_mode()
+ *
+ * Determine whether to use const ref typemaps instead of pointer typemaps
+ * for variable access.
+ * -------------------------------------------------------------------------- */
+int Language::use_naturalvar_mode(Node *n) const {
+ if (Getattr(n, "unnamed"))
+ return 0;
+
+ // The naturalvar feature can be attached to either the variable name or the variable's type
+ // naturalvar on the variable name is more specific and overrides naturalvar on the variable's type
+ String *naturalvar = Getattr(n, "feature:naturalvar");
+ bool explicitly_off = naturalvar && Strcmp(naturalvar, "0") == 0;
+ int nvar = GetFlag(n, "feature:naturalvar");
+
+ if (!explicitly_off && !nvar) {
+ /* look for feature in the class */
+ SwigType *ty = Getattr(n, "type");
+ SwigType *fullty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isclass(fullty)) {
+ SwigType *tys = SwigType_strip_qualifiers(fullty);
+ if (!CPlusPlus) {
+ Replaceall(tys, "struct ", "");
+ Replaceall(tys, "union ", "");
+ Replaceall(tys, "class ", "");
+ }
+ Node *typenode = Swig_symbol_clookup(tys, 0);
+ if (typenode) {
+ naturalvar = Getattr(typenode, "feature:naturalvar");
+ explicitly_off = naturalvar && Strcmp(naturalvar, "0") == 0;
+ nvar = nvar || GetFlag(typenode, "feature:naturalvar");
+ }
+ Delete(tys);
+ }
+ Delete(fullty);
+ }
+ nvar = nvar || naturalvar_mode;
+ return explicitly_off ? 0 : nvar ? CWRAP_NATURAL_VAR : 0;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::top() - Top of parsing tree
+ * ---------------------------------------------------------------------- */
+
+int Language::top(Node *n) {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ if (Getattr(options, "naturalvar")) {
+ naturalvar_mode = 1;
+ }
+ }
+ }
+ classhash = Getattr(n, "classes");
+ return emit_children(n);
+}
+
+/* ----------------------------------------------------------------------
+ * Language::extendDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::extendDirective(Node *n) {
+ save_value<int> oldam(Extend, CWRAP_EXTEND);
+ save_value<AccessMode> oldmode(cplus_mode, PUBLIC);
+ emit_children(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::applyDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::applyDirective(Node *n) {
+
+ Parm *pattern = Getattr(n, "pattern");
+ Node *c = firstChild(n);
+ while (c) {
+ Parm *apattern = Getattr(c, "pattern");
+ if (ParmList_len(pattern) != ParmList_len(apattern)) {
+ Swig_error(input_file, line_number, "Can't apply (%s) to (%s). Number of arguments don't match.\n", ParmList_str(pattern), ParmList_str(apattern));
+ } else {
+ if (!Swig_typemap_apply(pattern, apattern)) {
+ Swig_warning(WARN_TYPEMAP_APPLY_UNDEF, input_file, line_number, "Can't apply (%s). No typemaps are defined.\n", ParmList_str(pattern));
+ }
+ }
+ c = nextSibling(c);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::clearDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::clearDirective(Node *n) {
+ Node *p;
+ for (p = firstChild(n); p; p = nextSibling(p)) {
+ ParmList *pattern = Getattr(p, "pattern");
+ Swig_typemap_clear_apply(pattern);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::constantDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::constantDirective(Node *n) {
+
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ if (!GetFlag(n, "feature:allowexcept")) {
+ UnsetFlag(n, "feature:except");
+ }
+ if (Getattr(n, "feature:exceptvar")) {
+ Setattr(n, "feature:except", Getattr(n, "feature:exceptvar"));
+ }
+
+ if (!ImportMode) {
+ Swig_require("constantDirective", n, "name", "?value", NIL);
+ if (!Getattr(n, "value")) {
+ Setattr(n, "value", Getattr(n, "name"));
+ }
+ this->constantWrapper(n);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+ return SWIG_NOWRAP;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::fragmentDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::fragmentDirective(Node *n) {
+ if (!(Getattr(n, "emitonly") && ImportMode))
+ Swig_fragment_register(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::importDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::importDirective(Node *n) {
+ int oldim = ImportMode;
+ ImportMode = IMPORT_MODE;
+ emit_children(n);
+ ImportMode = oldim;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::includeDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::includeDirective(Node *n) {
+ emit_children(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::insertDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::insertDirective(Node *n) {
+ /* %insert directive */
+ if ((!ImportMode) || Getattr(n, "generated")) {
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+ File *f = 0;
+ if (!section) { /* %{ ... %} */
+ f = Swig_filebyname("header");
+ } else {
+ f = Swig_filebyname(section);
+ }
+ if (f) {
+ Printf(f, "%s\n", code);
+ } else {
+ Swig_error(input_file, line_number, "Unknown target '%s' for %%insert directive.\n", section);
+ }
+ return SWIG_OK;
+ } else {
+ return SWIG_NOWRAP;
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::moduleDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::moduleDirective(Node *n) {
+ (void) n;
+ /* %module directive */
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::nativeDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::nativeDirective(Node *n) {
+ if (!ImportMode) {
+ return nativeWrapper(n);
+ } else {
+ return SWIG_NOWRAP;
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::pragmaDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::pragmaDirective(Node *n) {
+ /* %pragma directive */
+ if (!ImportMode) {
+ String *lan = Getattr(n, "lang");
+ String *name = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+ swig_pragma(Char(lan), Char(name), Char(value));
+ /* pragma(Char(lan),Char(name),Char(value)); */
+ return SWIG_OK;
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typemapDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::typemapDirective(Node *n) {
+ /* %typemap directive */
+ String *method = Getattr(n, "method");
+ String *code = Getattr(n, "code");
+ Parm *kwargs = Getattr(n, "kwargs");
+ Node *items = firstChild(n);
+ static int nameerror = 0;
+
+
+ if (code && (Strstr(code, "$source") || (Strstr(code, "$target")))) {
+ Swig_error(Getfile(n), Getline(n), "Obsolete typemap feature ($source/$target).\n");
+ if (!nameerror) {
+ Swig_error(Getfile(n), Getline(n), "The use of $source and $target in a typemap declaration is no longer supported.\n\
+For typemaps related to argument input (in,ignore,default,arginit,check), replace\n\
+$source by $input and $target by $1. For typemaps related to return values (out,\n\
+argout,ret,except), replace $source by $1 and $target by $result. See the file\n\
+Doc/Manual/Typemaps.html for complete details.\n");
+ nameerror = 1;
+ }
+ }
+
+ if (Strcmp(method, "except") == 0) {
+ Swig_error(Getfile(n), Getline(n), "%%typemap(except) is no longer supported. Use the %%exception directive.\n");
+ }
+
+ if (Strcmp(method, "in") == 0) {
+ Hash *k;
+ k = kwargs;
+ while (k) {
+ if (checkAttribute(k, "name", "numinputs")) {
+ if (!multiinput && (GetInt(k, "value") > 1)) {
+ Swig_error(Getfile(n), Getline(n), "Multiple-input typemaps (numinputs > 1) not supported by this target language module.\n");
+ return SWIG_ERROR;
+ }
+ break;
+ }
+ k = nextSibling(k);
+ }
+ if (!k) {
+ k = NewHash();
+ Setattr(k, "name", "numinputs");
+ Setattr(k, "value", "1");
+ set_nextSibling(k, kwargs);
+ Setattr(n, "kwargs", k);
+ kwargs = k;
+ }
+ }
+
+ if (Strcmp(method, "ignore") == 0) {
+ Swig_error(Getfile(n), Getline(n), "%%typemap(ignore) is no longer supported. Use %%typemap(in,numinputs=0).\n");
+ }
+
+ /* Replace $descriptor() macros */
+
+ if (code) {
+ Setfile(code, Getfile(n));
+ Setline(code, Getline(n));
+ Swig_cparse_replace_descriptor(code);
+ }
+
+ while (items) {
+ Parm *pattern = Getattr(items, "pattern");
+ Parm *parms = Getattr(items, "parms");
+
+ if (code) {
+ Swig_typemap_register(method, pattern, code, parms, kwargs);
+ } else {
+ Swig_typemap_clear(method, pattern);
+ }
+ items = nextSibling(items);
+ }
+ return SWIG_OK;
+
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typemapcopyDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::typemapcopyDirective(Node *n) {
+ String *method = Getattr(n, "method");
+ Parm *pattern = Getattr(n, "pattern");
+ Node *items = firstChild(n);
+ int nsrc = 0;
+ nsrc = ParmList_len(pattern);
+ while (items) {
+ ParmList *npattern = Getattr(items, "pattern");
+ if (nsrc != ParmList_len(npattern)) {
+ Swig_error(input_file, line_number, "Can't copy typemap. Number of types differ.\n");
+ } else {
+ if (Swig_typemap_copy(method, pattern, npattern) < 0) {
+ Swig_error(input_file, line_number, "Can't copy typemap (%s) %s = %s\n", method, ParmList_str(pattern), ParmList_str(npattern));
+ }
+ }
+ items = nextSibling(items);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typesDirective()
+ * ---------------------------------------------------------------------- */
+
+int Language::typesDirective(Node *n) {
+ Parm *parms = Getattr(n, "parms");
+ String *convcode = Getattr(n, "convcode"); /* optional user supplied conversion code for custom casting */
+ while (parms) {
+ SwigType *t = Getattr(parms, "type");
+ String *v = Getattr(parms, "value");
+ if (!v) {
+ SwigType_remember(t);
+ } else {
+ if (SwigType_issimple(t)) {
+ SwigType_inherit(t, v, 0, convcode);
+ }
+ }
+ parms = nextSibling(parms);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::cDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::cDeclaration(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *decl = Getattr(n, "decl");
+ String *storage = Getattr(n, "storage");
+ Node *over;
+ File *f_header = 0;
+ SwigType *ty, *fullty;
+
+ if (Getattr(n, "feature:onlychildren")) {
+ if (GetFlag(n, "feature:ignore")) {
+ return SWIG_NOWRAP;
+ } else {
+ // Found an unignored templated method that has an empty template instantiation (%template())
+ // Ignore it unless it has been %rename'd
+ if (Strncmp(symname, "__dummy_", 8) == 0 && Cmp(storage, "typedef") != 0) {
+ SetFlag(n, "feature:ignore");
+ Swig_warning(WARN_LANG_TEMPLATE_METHOD_IGNORE, input_file, line_number,
+ "%%template() contains no name. Template method ignored: %s\n", Swig_name_decl(n));
+ return SWIG_NOWRAP;
+ }
+ }
+ }
+
+ /* discards nodes following the access control rules */
+ if (cplus_mode != PUBLIC || !is_public(n)) {
+ /* except for friends, they are not affected by access control */
+ int isfriend = (Strstr(storage, "friend") != NULL);
+ if (!isfriend) {
+ /* Check what the director needs. If the method is pure virtual, it is always needed.
+ * Also wrap non-virtual protected members if asked for (allprotected mode). */
+ if (!(Swig_directors_enabled() && ((is_member_director(CurrentClass, n) && need_nonpublic_member(n)) || isNonVirtualProtectedAccess(n)))) {
+ return SWIG_NOWRAP;
+ }
+ // Prevent wrapping protected overloaded director methods more than once -
+ // This bit of code is only needed due to the cDeclaration call in classHandler()
+ String *wrapname = NewStringf("nonpublic_%s%s", symname, Getattr(n, "sym:overname"));
+ if (Getattr(CurrentClass, wrapname)) {
+ Delete(wrapname);
+ return SWIG_NOWRAP;
+ }
+ SetFlag(CurrentClass, wrapname);
+ Delete(wrapname);
+ }
+ }
+
+ if (Cmp(storage, "typedef") == 0) {
+ Swig_save("cDeclaration", n, "type", NIL);
+ SwigType *t = Copy(type);
+ if (t) {
+ SwigType_push(t, decl);
+ Setattr(n, "type", t);
+ typedefHandler(n);
+ }
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* If in import mode, we proceed no further */
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ /* If we're in extend mode and there is code, replace the $descriptor macros */
+ if (Extend) {
+ String *code = Getattr(n, "code");
+ if (code) {
+ Setfile(code, Getfile(n));
+ Setline(code, Getline(n));
+ Swig_cparse_replace_descriptor(code);
+ }
+ }
+
+ /* Overloaded symbol check */
+ over = Swig_symbol_isoverloaded(n);
+ if (!overloading) {
+ if (over)
+ over = first_nontemplate(over);
+ if (over && (over != n)) {
+ Swig_warning(WARN_LANG_OVERLOAD_DECL, input_file, line_number, "Overloaded declaration ignored. %s\n", Swig_name_decl(n));
+ Swig_warning(WARN_LANG_OVERLOAD_DECL, Getfile(over), Getline(over), "Previous declaration is %s\n", Swig_name_decl(over));
+ return SWIG_NOWRAP;
+ }
+ }
+
+ if (!validIdentifier(symname)) {
+ Swig_warning(WARN_LANG_IDENTIFIER, input_file, line_number, "Can't wrap '%s' unless renamed to a valid identifier.\n", SwigType_namestr(symname));
+ return SWIG_NOWRAP;
+ }
+
+ ty = NewString(type);
+ SwigType_push(ty, decl);
+ fullty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isfunction(fullty)) {
+ if (!SwigType_isfunction(ty)) {
+ Delete(ty);
+ ty = fullty;
+ fullty = 0;
+ ParmList *parms = SwigType_function_parms(ty, n);
+ Setattr(n, "parms", parms);
+ }
+ /* Transform the node into a 'function' node and emit */
+ if (!CurrentClass) {
+ f_header = Swig_filebyname("header");
+
+ if (AddExtern) {
+ if (f_header) {
+ if (Swig_storage_isextern(n) || (ForceExtern && !storage)) {
+ /* we don't need the 'extern' part in the C/C++ declaration,
+ and it produces some problems when namespace and SUN
+ Studio is used.
+
+ Printf(f_header,"extern %s", SwigType_str(ty,name));
+
+ In fact generating extern declarations is quite error prone and is
+ no longer the default. Getting it right seems impossible with namespaces
+ and default arguments and when a method is declared with the various Windows
+ calling conventions - SWIG doesn't understand Windows (non standard) calling
+ conventions in the first place, so can't regenerate them.
+ */
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "%s", str);
+ Delete(str);
+ {
+ DOH *t = Getattr(n, "throws");
+ if (t) {
+ Printf(f_header, " throw(");
+ while (t) {
+ Printf(f_header, "%s", Getattr(t, "type"));
+ t = nextSibling(t);
+ if (t)
+ Printf(f_header, ",");
+ }
+ Printf(f_header, ")");
+ }
+ }
+ Printf(f_header, ";\n");
+ } else if (Swig_storage_isexternc(n)) {
+ /* here 'extern "C"' is needed */
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "extern \"C\" %s;\n", str);
+ Delete(str);
+ }
+ }
+ }
+ }
+ /* This needs to check qualifiers */
+ if (SwigType_isqualifier(ty)) {
+ SwigType *qual = SwigType_pop(ty);
+ Setattr(n, "qualifier", qual);
+ Delete(qual);
+ }
+ Delete(SwigType_pop_function(ty));
+ DohIncref(type);
+ Setattr(n, "type", ty);
+
+ functionHandler(n);
+
+ Setattr(n, "type", type);
+ Delete(ty);
+ Delete(type);
+ return SWIG_OK;
+ } else {
+ /* Some kind of variable declaration */
+ String *declaration = Copy(decl);
+ Delattr(n, "decl");
+ if (!CurrentClass) {
+ if (Swig_storage_isextern(n) || ForceExtern) {
+ if (AddExtern) {
+ f_header = Swig_filebyname("header");
+ if (f_header) {
+ String *str = SwigType_str(ty, name);
+ Printf(f_header, "%s %s;\n", Getattr(n, "storage"), str);
+ Delete(str);
+ }
+ }
+ }
+ }
+ DohIncref(type);
+ Setattr(n, "type", ty);
+ variableHandler(n);
+ Setattr(n, "type", type);
+ Setattr(n, "decl", declaration);
+ Delete(ty);
+ Delete(type);
+ Delete(fullty);
+ return SWIG_OK;
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::functionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::functionHandler(Node *n) {
+ String *storage = Getattr(n, "storage");
+ int isfriend = CurrentClass && Strstr(storage, "friend");
+ int isstatic = CurrentClass && Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"));
+ Parm *p = Getattr(n, "parms");
+ if (GetFlag(n, "feature:del")) {
+ /* the method acts like a delete operator, ie, we need to disown the parameter */
+ if (CurrentClass && !isstatic && !isfriend) {
+ SetFlag(n, "feature:self:disown");
+ } else {
+ if (p)
+ SetFlag(p, "wrap:disown");
+ }
+ }
+ if (!CurrentClass) {
+ globalfunctionHandler(n);
+ } else {
+ if (isstatic) {
+ staticmemberfunctionHandler(n);
+ } else if (isfriend) {
+ int oldInClass = InClass;
+ InClass = 0;
+ globalfunctionHandler(n);
+ InClass = oldInClass;
+ } else {
+ // This is a member function, set a flag so the documentation type is correct
+ SetFlag(n, "memberfunction");
+ Node *explicit_n = 0;
+ if (Swig_directors_enabled() && is_member_director(CurrentClass, n) && !extraDirectorProtectedCPPMethodsRequired()) {
+ bool virtual_but_not_pure_virtual = (!(Cmp(storage, "virtual")) && (Cmp(Getattr(n, "value"), "0") != 0));
+ if (virtual_but_not_pure_virtual) {
+ // Add additional wrapper which makes an explicit call to the virtual method (ie not a virtual call)
+ explicit_n = Copy(n);
+ String *new_symname = Copy(Getattr(n, "sym:name"));
+ String *suffix = Getattr(parentNode(n), "sym:name");
+ Printv(new_symname, "SwigExplicit", suffix, NIL);
+ Setattr(explicit_n, "sym:name", new_symname);
+ Delattr(explicit_n, "storage");
+ Delattr(explicit_n, "override");
+ Delattr(explicit_n, "hides");
+ SetFlag(explicit_n, "explicitcall");
+ Setattr(n, "explicitcallnode", explicit_n);
+ }
+ }
+
+ memberfunctionHandler(n);
+
+ if (explicit_n) {
+ memberfunctionHandler(explicit_n);
+ Delattr(explicit_n, "explicitcall");
+ Delete(explicit_n);
+ }
+ }
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::globalfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::globalfunctionHandler(Node *n) {
+
+ Swig_require("globalfunctionHandler", n, "name", "sym:name", "type", "?parms", NIL);
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+
+ /* Check for callback mode */
+ String *cb = GetFlagAttr(n, "feature:callback");
+ if (cb) {
+ String *cbname = Getattr(n, "feature:callback:name");
+ if (!cbname) {
+ cbname = NewStringf(cb, symname);
+ Setattr(n, "feature:callback:name", cbname);
+ }
+
+ callbackfunctionHandler(n);
+ if (Cmp(cbname, symname) == 0) {
+ Delete(cbname);
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ Delete(cbname);
+ }
+ Setattr(n, "parms", nonvoid_parms(parms));
+
+ String *extendname = Getattr(n, "extendname");
+ String *call = Swig_cfunction_call(extendname ? extendname : name, parms);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ String *friendusing = Getattr(n, "friendusing");
+ if (friendusing) {
+ // Add a using directive to avoid having to possibly fully qualify the call to the friend function.
+ // Unconventional for SWIG generation, but the alternative is to implement Argument Dependent Lookup
+ // as friend functions are quirky and not visible, except for ADL. An ADL implementation would be needed
+ // in order to work out when the friend function is visible or not, in order to determine whether to
+ // rely on ADL (with no qualification) or to fully qualify the call to the friend function made
+ // visible via a matching declaration at namespace scope.
+ String *action = NewStringf("%s\n%s", friendusing, cres);
+ Setattr(n, "wrap:action", action);
+ Delete(action);
+ } else {
+ Setattr(n, "wrap:action", cres);
+ }
+ Delete(cres);
+ Delete(call);
+ functionWrapper(n);
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::callbackfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::callbackfunctionHandler(Node *n) {
+ Swig_require("callbackfunctionHandler", n, "name", "*sym:name", "*type", "?value", NIL);
+ String *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *parms = Getattr(n, "parms");
+ String *cbname = Getattr(n, "feature:callback:name");
+ String *calltype = NewStringf("(%s (*)(%s))(%s)", SwigType_str(type, 0), ParmList_str(parms), SwigType_namestr(name));
+ SwigType *cbty = Copy(type);
+ SwigType_add_function(cbty, parms);
+ SwigType_add_pointer(cbty);
+
+ Setattr(n, "sym:name", cbname);
+ Setattr(n, "type", cbty);
+ Setattr(n, "value", calltype);
+
+ Node *ns = symbolLookup(cbname);
+ if (!ns)
+ constantWrapper(n);
+
+ Delete(cbty);
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::memberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::memberfunctionHandler(Node *n) {
+
+ Swig_require("memberfunctionHandler", n, "*name", "*sym:name", "*type", "?parms", "?value", NIL);
+
+ String *storage = Getattr(n, "storage");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ ParmList *parms = Getattr(n, "parms");
+ String *cb = GetFlagAttr(n, "feature:callback");
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ IsVirtual = PURE_VIRTUAL;
+ } else {
+ IsVirtual = PLAIN_VIRTUAL;
+ }
+ } else {
+ IsVirtual = 0;
+ }
+ if (cb) {
+ Node *cbn = NewHash();
+ String *cbname = Getattr(n, "feature:callback:name");
+ if (!cbname) {
+ cbname = NewStringf(cb, symname);
+ }
+
+ SwigType *cbty = Copy(type);
+ SwigType_add_function(cbty, parms);
+ SwigType_add_memberpointer(cbty, ClassName);
+ String *cbvalue = NewStringf("&%s::%s", ClassName, name);
+ Setattr(cbn, "sym:name", cbname);
+ Setattr(cbn, "type", cbty);
+ Setattr(cbn, "value", cbvalue);
+ Setattr(cbn, "name", name);
+ Setfile(cbn, Getfile(n));
+ Setline(cbn, Getline(n));
+
+ memberconstantHandler(cbn);
+ Setattr(n, "feature:callback:name", Swig_name_member(NSpace, ClassPrefix, cbname));
+
+ Delete(cb);
+ Delete(cbn);
+ Delete(cbvalue);
+ Delete(cbty);
+ Delete(cbname);
+ if (Cmp(cbname, symname) == 0) {
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ }
+
+ String *fname = Swig_name_member(NSpace, ClassPrefix, symname);
+ if (Extend && SmartPointer) {
+ if (!Getattr(n, "extendsmartclassname")) {
+ Setattr(n, "extendsmartclassname", Getattr(CurrentClass, "allocate:smartpointerpointeeclassname"));
+ }
+ }
+ // Set up the type for the cast to this class for use when wrapping const director (virtual) methods.
+ // Note: protected director methods or when allprotected mode turned on.
+ String *director_type = 0;
+ if (!is_public(n) && (is_member_director(CurrentClass, n) || GetFlag(n, "explicitcall") || isNonVirtualProtectedAccess(n))) {
+ director_type = Copy(DirectorClassName);
+ String *qualifier = Getattr(n, "qualifier");
+ if (qualifier)
+ SwigType_push(director_type, qualifier);
+ SwigType_add_pointer(director_type);
+ }
+
+ int DirectorExtraCall = 0;
+ if (Swig_directors_enabled() && is_member_director(CurrentClass, n) && !SmartPointer)
+ if (extraDirectorProtectedCPPMethodsRequired())
+ DirectorExtraCall = CWRAP_DIRECTOR_TWO_CALLS;
+
+ if (GetFlag(n, "explicitcall"))
+ DirectorExtraCall = CWRAP_DIRECTOR_ONE_CALL;
+
+ int extendmember = GetFlag(n, "isextendmember") ? Extend : 0;
+ int flags = Getattr(n, "template") ? extendmember | SmartPointer : Extend | SmartPointer | DirectorExtraCall;
+ Swig_MethodToFunction(n, NSpace, ClassType, flags, director_type, is_member_director(CurrentClass, n));
+ Setattr(n, "sym:name", fname);
+ /* Explicitly save low-level and high-level documentation names */
+ Setattr(n, "doc:low:name", fname);
+ Setattr(n, "doc:high:name", symname);
+
+ functionWrapper(n);
+
+ Delete(director_type);
+ Delete(fname);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::staticmemberfunctionHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::staticmemberfunctionHandler(Node *n) {
+
+ Swig_require("staticmemberfunctionHandler", n, "*name", "*sym:name", "*type", NIL);
+ Swig_save("staticmemberfunctionHandler", n, "storage", NIL);
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+ String *cb = GetFlagAttr(n, "feature:callback");
+ String *cname;
+ String *mrename = Swig_name_member(NSpace, ClassPrefix, symname);
+
+ if (!(Extend && GetFlag(n, "isextendmember"))) {
+ Node *sb = Getattr(n, "cplus:staticbase");
+ String *sname = Getattr(sb, "name");
+ if (isNonVirtualProtectedAccess(n))
+ cname = NewStringf("%s::%s", DirectorClassName, name);
+ else
+ cname = NewStringf("%s::%s", sname, name);
+ } else {
+ String *classname_str = SwigType_namestr(ClassName);
+ String *mname = Swig_name_mangle_string(classname_str);
+ cname = Swig_name_member(NSpace, mname, name);
+ Delete(mname);
+ Delete(classname_str);
+
+ String *code = Getattr(n, "code");
+ String *defaultargs = Getattr(n, "defaultargs");
+ String *mangled = Swig_name_mangle_string(mrename);
+ Delete(mrename);
+ mrename = mangled;
+
+ if (code) {
+ // See Swig_MethodToFunction() for the explanation of this code.
+ if (Getattr(n, "sym:overloaded")) {
+ Append(cname, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ } else if (UseWrapperSuffix) {
+ Append(cname, "__SWIG");
+ }
+
+ if (!defaultargs) {
+ /* Hmmm. An added static member. We have to create a little wrapper for this */
+ String *mangled_cname = Swig_name_mangle_string(cname);
+ Swig_add_extension_code(n, mangled_cname, parms, type, code, CPlusPlus, 0);
+ Setattr(n, "extendname", mangled_cname);
+ Delete(mangled_cname);
+ }
+ }
+ }
+
+ Setattr(n, "name", cname);
+ Setattr(n, "sym:name", mrename);
+ /* Explicitly save low-level and high-level documentation names */
+ Setattr(n, "doc:low:name", mrename);
+ Setattr(n, "doc:high:name", symname);
+
+ if (cb) {
+ String *cbname = NewStringf(cb, symname);
+ Setattr(n, "feature:callback:name", Swig_name_member(NSpace, ClassPrefix, cbname));
+ Setattr(n, "feature:callback:staticname", name);
+ }
+ Delattr(n, "storage");
+
+ globalfunctionHandler(n);
+
+ Delete(cname);
+ Delete(mrename);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::variableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::variableHandler(Node *n) {
+
+ /* If not a smart-pointer access or added method. We clear
+ feature:except. There is no way C++ or C would throw
+ an exception merely for accessing a member data.
+
+ Caveat: Some compilers seem to route attribute access through
+ methods which can generate exceptions. The feature:allowexcept
+ allows this. Also, the feature:exceptvar can be used to match
+ only variables.
+ */
+ if (!(Extend | SmartPointer)) {
+ if (!GetFlag(n, "feature:allowexcept")) {
+ UnsetFlag(n, "feature:except");
+ }
+ if (Getattr(n, "feature:exceptvar")) {
+ Setattr(n, "feature:except", Getattr(n, "feature:exceptvar"));
+ }
+ }
+
+ if (!CurrentClass) {
+ globalvariableHandler(n);
+ } else {
+ Swig_save("variableHandler", n, "feature:immutable", NIL);
+ if (SmartPointer) {
+ /* If a smart-pointer and it's a constant access, we have to set immutable */
+ if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
+ SetFlag(n, "feature:immutable");
+ }
+ }
+ if (Swig_storage_isstatic(n) && !(SmartPointer && Getattr(n, "allocate:smartpointeraccess"))) {
+ staticmembervariableHandler(n);
+ } else {
+ membervariableHandler(n);
+ }
+ Swig_restore(n);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::globalvariableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::globalvariableHandler(Node *n) {
+ variableWrapper(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::membervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::membervariableHandler(Node *n) {
+
+ Swig_require("membervariableHandler", n, "*name", "*sym:name", "*type", NIL);
+ Swig_save("membervariableHandler", n, "parms", NIL);
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+
+ if (!AttributeFunctionGet) {
+ String *mname = Swig_name_member(0, ClassPrefix, symname);
+ String *mrename_get = Swig_name_get(NSpace, mname);
+ String *mrename_set = Swig_name_set(NSpace, mname);
+ Delete(mname);
+
+ /* Create a function to set the value of the variable */
+
+ int assignable = !is_immutable(n);
+
+ if (SmartPointer) {
+ if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
+ assignable = 0;
+ }
+ }
+
+ if (assignable) {
+ int make_set_wrapper = 1;
+ String *tm = 0;
+ String *target = 0;
+ if (!Extend) {
+ if (SmartPointer) {
+ if (Swig_storage_isstatic(n)) {
+ Node *sn = Getattr(n, "cplus:staticbase");
+ String *base = Getattr(sn, "name");
+ target = NewStringf("%s::%s", base, name);
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ target = NewStringf("(*%s)->%s", pname, name);
+ Delete(pname);
+ }
+ } else {
+ String *pname = isNonVirtualProtectedAccess(n) ? NewString("darg") : Swig_cparm_name(0, 0);
+ target = NewStringf("%s->%s", pname, name);
+ Delete(pname);
+ }
+
+ // This is an input type typemap lookup and so it should not use Node n
+ // otherwise qualification is done on the parameter name for the setter function
+ Parm *nin = NewParm(type, name, n);
+ tm = Swig_typemap_lookup("memberin", nin, target, 0);
+ Delete(nin);
+ }
+
+ int flags = Extend | SmartPointer | use_naturalvar_mode(n);
+ if (isNonVirtualProtectedAccess(n))
+ flags = flags | CWRAP_ALL_PROTECTED_ACCESS;
+
+ Swig_MembersetToFunction(n, ClassType, flags);
+ Setattr(n, "memberset", "1");
+ if (!Extend) {
+ /* Check for a member in typemap here */
+
+ if (!tm) {
+ if (SwigType_isarray(type)) {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(type, 0));
+ make_set_wrapper = 0;
+ }
+ } else {
+ String *pname0 = Swig_cparm_name(0, 0);
+ String *pname1 = Swig_cparm_name(0, 1);
+ Replace(tm, "$input", pname1, DOH_REPLACE_ANY);
+ Replace(tm, "$self", pname0, DOH_REPLACE_ANY);
+ Setattr(n, "wrap:action", tm);
+ Delete(tm);
+ Delete(pname0);
+ Delete(pname1);
+ }
+ Delete(target);
+ }
+ if (make_set_wrapper) {
+ Setattr(n, "sym:name", mrename_set);
+ functionWrapper(n);
+ } else {
+ SetFlag(n, "feature:immutable");
+ }
+ /* Restore parameters */
+ Setattr(n, "type", type);
+ Setattr(n, "name", name);
+ Setattr(n, "sym:name", symname);
+ Delattr(n, "memberset");
+
+ /* Delete all attached typemaps and typemap attributes */
+ Iterator ki;
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0)
+ Delattr(n, ki.key);
+ }
+ }
+ /* Emit get function */
+ {
+ int flags = Extend | SmartPointer | use_naturalvar_mode(n);
+ if (isNonVirtualProtectedAccess(n))
+ flags = flags | CWRAP_ALL_PROTECTED_ACCESS;
+ Swig_MembergetToFunction(n, ClassType, flags);
+ Setattr(n, "sym:name", mrename_get);
+ Setattr(n, "memberget", "1");
+ functionWrapper(n);
+ Delattr(n, "memberget");
+ }
+ Delete(mrename_get);
+ Delete(mrename_set);
+
+ } else {
+
+ /* This code is used to support the attributefunction directive
+ where member variables are converted automagically to
+ accessor functions */
+
+#if 0
+ Parm *p;
+ String *gname;
+ SwigType *vty;
+ p = NewParm(type, 0, n);
+ gname = NewStringf(AttributeFunctionGet, symname);
+ if (!Extend) {
+ ActionFunc = Copy(Swig_cmemberget_call(name, type));
+ cpp_member_func(Char(gname), Char(gname), type, 0);
+ Delete(ActionFunc);
+ } else {
+ String *cname = Swig_name_get(NSpace, name);
+ cpp_member_func(Char(cname), Char(gname), type, 0);
+ Delete(cname);
+ }
+ Delete(gname);
+ if (!GetFlag(n, "feature:immutable")) {
+ gname = NewStringf(AttributeFunctionSet, symname);
+ vty = NewString("void");
+ if (!Extend) {
+ ActionFunc = Copy(Swig_cmemberset_call(name, type));
+ cpp_member_func(Char(gname), Char(gname), vty, p);
+ Delete(ActionFunc);
+ } else {
+ String *cname = Swig_name_set(NSpace, name);
+ cpp_member_func(Char(cname), Char(gname), vty, p);
+ Delete(cname);
+ }
+ Delete(gname);
+ }
+ ActionFunc = 0;
+#endif
+ }
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::staticmembervariableHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::staticmembervariableHandler(Node *n) {
+ Swig_require("staticmembervariableHandler", n, "*name", "*sym:name", "*type", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *classname = !SmartPointer ? (isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName) : Getattr(CurrentClass, "allocate:smartpointerpointeeclassname");
+
+ if (!value || !Getattr(n, "hasconsttype")) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *cname, *mrename;
+
+ /* Create the variable name */
+ mrename = Swig_name_member(0, ClassPrefix, symname);
+ cname = NewStringf("%s::%s", classname, name);
+
+ Setattr(n, "sym:name", mrename);
+ Setattr(n, "name", cname);
+
+ /* Wrap as an ordinary global variable */
+ variableWrapper(n);
+
+ Delete(mrename);
+ Delete(cname);
+ } else {
+
+ /* This is a C++ static member declaration with an initializer and it's const.
+ Certain C++ compilers optimize this out so that there is no linkage to a
+ memory address. Example:
+
+ class Foo {
+ public:
+ static const int x = 3;
+ };
+
+ Some discussion of this in section 9.4 of the C++ draft standard.
+
+ Also, we have to manage the case:
+
+ class Foo {
+ public:
+ %extend {
+ static const int x = 3;
+ }
+ };
+
+ in which there's no actual Foo::x variable to refer to. In this case,
+ the best we can do is to wrap the given value verbatim.
+ */
+
+
+ String *name = Getattr(n, "name");
+ String *cname = NewStringf("%s::%s", classname, name);
+ if (Extend) {
+ /* the variable is a synthesized one.
+ There's nothing we can do; we just keep the given value */
+ } else {
+ /* we refer to the value as Foo::x */
+ String *value = SwigType_namestr(cname);
+ Setattr(n, "value", value);
+ }
+
+ SwigType *t1 = SwigType_typedef_resolve_all(Getattr(n, "type"));
+ SwigType *t2 = SwigType_strip_qualifiers(t1);
+ Setattr(n, "type", t2);
+ Delete(t1);
+ Delete(t2);
+ SetFlag(n, "wrappedasconstant");
+ memberconstantHandler(n);
+ Delete(cname);
+ }
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::externDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::externDeclaration(Node *n) {
+ return emit_children(n);
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumDeclaration(Node *n) {
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *oldNSpace = NSpace;
+ NSpace = Getattr(n, "sym:nspace");
+
+ String *oldEnumClassPrefix = EnumClassPrefix;
+ if (GetFlag(n, "scopedenum")) {
+ assert(Getattr(n, "sym:name"));
+ assert(Getattr(n, "name"));
+ EnumClassPrefix = ClassPrefix ? NewStringf("%s_", ClassPrefix) : NewString("");
+ Printv(EnumClassPrefix, Getattr(n, "sym:name"), NIL);
+ EnumClassName = Copy(Getattr(n, "name"));
+ }
+ if (!ImportMode) {
+ emit_children(n);
+ }
+
+ if (GetFlag(n, "scopedenum")) {
+ Delete(EnumClassName);
+ EnumClassName = 0;
+ Delete(EnumClassPrefix);
+ EnumClassPrefix = oldEnumClassPrefix;
+ }
+ NSpace = oldNSpace;
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumvalueDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumvalueDeclaration(Node *n) {
+ if (CurrentClass && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "*sym:name", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ String *tmpValue;
+
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ Setattr(n, "value", tmpValue);
+
+ Node *parent = parentNode(n);
+ if (GetFlag(parent, "scopedenum")) {
+ String *symname = Swig_name_member(0, Getattr(parent, "sym:name"), Getattr(n, "sym:name"));
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ if (!CurrentClass || !cparse_cplusplus) {
+ Setattr(n, "name", tmpValue); /* for wrapping of enums in a namespace when emit_action is used */
+ constantWrapper(n);
+ } else {
+ memberconstantHandler(n);
+ }
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::enumforwardDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::enumforwardDeclaration(Node *n) {
+ (void) n;
+ if (GetFlag(n, "enumMissing"))
+ enumDeclaration(n); // Generate an empty enum in target language
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::memberconstantHandler()
+ * ----------------------------------------------------------------------------- */
+
+int Language::memberconstantHandler(Node *n) {
+
+ Swig_require("memberconstantHandler", n, "*name", "*sym:name", "value", NIL);
+
+ if (!GetFlag(n, "feature:allowexcept")) {
+ UnsetFlag(n, "feature:except");
+ }
+ if (Getattr(n, "feature:exceptvar")) {
+ Setattr(n, "feature:except", Getattr(n, "feature:exceptvar"));
+ }
+
+ String *enumvalue_symname = Getattr(n, "enumvalueDeclaration:sym:name"); // Only set if a strongly typed enum
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+
+ String *mrename = Swig_name_member(0, EnumClassPrefix, enumvalue_symname ? enumvalue_symname : symname);
+ Setattr(n, "sym:name", mrename);
+
+ String *new_name = 0;
+ if (Extend)
+ new_name = Copy(value);
+ else if (EnumClassName)
+ new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : EnumClassName, name);
+ else
+ new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName, name);
+ Setattr(n, "name", new_name);
+
+ constantWrapper(n);
+ Delete(mrename);
+ Delete(new_name);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::typedefHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::typedefHandler(Node *n) {
+ /* since this is a recurring issue, we are going to remember the
+ typedef pointer, if already it is not a pointer or reference, as
+ in
+
+ typedef void NT;
+ int func(NT *p);
+
+ see director_basic.i for example.
+ */
+ SwigType *name = Getattr(n, "name");
+ SwigType *decl = Getattr(n, "decl");
+ Setfile(name, Getfile(n));
+ Setline(name, Getline(n));
+ if (!SwigType_ispointer(decl) && !SwigType_isreference(decl)) {
+ SwigType *pname = Copy(name);
+ SwigType_add_pointer(pname);
+ SwigType_remember(pname);
+ Delete(pname);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorMethod()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorMethod(Node *n, Node *parent, String *super) {
+ (void) n;
+ (void) parent;
+ (void) super;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorConstructor()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorConstructor(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorDefaultConstructor()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorDefaultConstructor(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+static String *vtable_method_id(Node *n) {
+ String *nodeType = Getattr(n, "nodeType");
+ int is_destructor = (Cmp(nodeType, "destructor") == 0);
+ if (is_destructor)
+ return 0;
+ String *name = Getattr(n, "name");
+ String *decl = Getattr(n, "decl");
+ String *local_decl = SwigType_typedef_resolve_all(decl);
+ String *tmp = SwigType_pop_function(local_decl);
+ Delete(local_decl);
+ local_decl = tmp;
+ String *method_id = NewStringf("%s|%s", name, local_decl);
+ Delete(local_decl);
+ return method_id;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::unrollOneVirtualMethod()
+ * ---------------------------------------------------------------------- */
+
+void Language::unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
+ if (!checkAttribute(n, "storage", "virtual"))
+ return;
+ if (GetFlag(n, "final"))
+ return;
+
+ String *nodeType = Getattr(n, "nodeType");
+
+ /* we need to add methods(cdecl) and destructor (to check for throw decl) */
+ int is_destructor = (Cmp(nodeType, "destructor") == 0);
+ if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
+ String *decl = Getattr(n, "decl");
+ /* extra check for function type and proper access */
+ if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(n)) || need_nonpublic_member(n))) {
+ String *name = Getattr(n, "name");
+ String *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(n);
+ /* Make sure that the new method overwrites the existing: */
+ int len = Len(vm);
+ const int DO_NOT_REPLACE = -1;
+ int replace = DO_NOT_REPLACE;
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vm, i);
+ String *check_vmid = Getattr(item, "vmid");
+
+ if (Strcmp(method_id, check_vmid) == 0) {
+ replace = i;
+ break;
+ }
+ }
+ /* filling a new method item */
+ String *fqdname = NewStringf("%s::%s", classname, name);
+ Hash *item = NewHash();
+ Setattr(item, "fqdname", fqdname);
+ Node *m = Copy(n);
+
+ /* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
+ SwigType *ty = NewString(Getattr(m, "type"));
+ SwigType_push(ty, decl);
+ if (SwigType_isqualifier(ty)) {
+ Delete(SwigType_pop(ty));
+ }
+ Delete(SwigType_pop_function(ty));
+ Setattr(m, "returntype", ty);
+
+ String *mname = NewStringf("%s::%s", Getattr(parent, "name"), name);
+ /* apply the features of the original method found in the base class */
+ Swig_features_get(Swig_cparse_features(), 0, mname, Getattr(m, "decl"), m);
+ Setattr(item, "methodNode", m);
+ Setattr(item, "vmid", method_id);
+ if (replace == DO_NOT_REPLACE)
+ Append(vm, item);
+ else
+ Setitem(vm, replace, item);
+ Setattr(n, "directorNode", m);
+
+ Delete(mname);
+ }
+ if (is_destructor) {
+ virtual_destructor = 1;
+ }
+ }
+}
+
+/* ----------------------------------------------------------------------
+ * Language::unrollVirtualMethods()
+ * ---------------------------------------------------------------------- */
+int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase) {
+ bool first_base = false;
+ // recurse through all base classes to build the vtable
+ List *bl = Getattr(n, "bases");
+ if (bl) {
+ Iterator bi;
+ for (bi = First(bl); bi.item; bi = Next(bi)) {
+ if (first_base && !director_multiple_inheritance)
+ break;
+ unrollVirtualMethods(bi.item, parent, vm, virtual_destructor);
+ first_base = true;
+ }
+ }
+
+ // recurse through all protected base classes to build the vtable, as needed
+ bl = Getattr(n, "protectedbases");
+ if (bl) {
+ Iterator bi;
+ for (bi = First(bl); bi.item; bi = Next(bi)) {
+ if (first_base && !director_multiple_inheritance)
+ break;
+ unrollVirtualMethods(bi.item, parent, vm, virtual_destructor, 1);
+ first_base = true;
+ }
+ }
+
+ // find the methods that need directors
+ String *classname = Getattr(n, "name");
+ for (Node *ni = firstChild(n); ni; ni = nextSibling(ni)) {
+ /* we only need to check the virtual members */
+ if (Equal(nodeType(ni), "using")) {
+ for (Node *nn = firstChild(ni); nn; nn = Getattr(nn, "sym:nextSibling")) {
+ unrollOneVirtualMethod(classname, nn, parent, vm, virtual_destructor, protectedbase);
+ }
+ }
+ unrollOneVirtualMethod(classname, ni, parent, vm, virtual_destructor, protectedbase);
+ }
+
+ /*
+ We delete all the nodirector methods. This prevents the
+ generation of 'empty' director classes.
+
+ Done once we've collated all the virtual methods into vm.
+ */
+ if (n == parent) {
+ int len = Len(vm);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vm, i);
+ Node *m = Getattr(item, "methodNode");
+ /* retrieve the director features */
+ int mdir = GetFlag(m, "feature:director");
+ int mndir = GetFlag(m, "feature:nodirector");
+ /* 'nodirector' has precedence over 'director' */
+ int dir = (mdir || mndir) ? (mdir && !mndir) : 1;
+ /* check if the method was found only in a base class */
+ Node *p = Getattr(m, "parentNode");
+ if (p != n) {
+ Node *c = Copy(m);
+ Setattr(c, "parentNode", n);
+ int cdir = GetFlag(c, "feature:director");
+ int cndir = GetFlag(c, "feature:nodirector");
+ dir = (cdir || cndir) ? (cdir && !cndir) : dir;
+ Delete(c);
+ }
+ if (dir) {
+ /* be sure the 'nodirector' feature is disabled */
+ if (mndir)
+ Delattr(m, "feature:nodirector");
+ } else {
+ /* or just delete from the vm, since is not a director method */
+ Delitem(vm, i);
+ len--;
+ i--;
+ }
+ }
+ }
+
+ return SWIG_OK;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorDisown()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorDisown(Node *n) {
+ Node *disown = NewHash();
+ String *mrename;
+ String *symname = Getattr(n, "sym:name");
+ mrename = Swig_name_disown(NSpace, symname);
+ String *type = NewString(ClassType);
+ String *name = NewString("self");
+ SwigType_add_pointer(type);
+ Parm *p = NewParm(type, name, n);
+ Delete(name);
+ Delete(type);
+ type = NewString("void");
+ String *action = NewString("");
+ Printv(action, "{\n", "Swig::Director *director = SWIG_DIRECTOR_CAST(arg1);\n", "if (director) director->swig_disown();\n", "}\n", NULL);
+ Setfile(disown, Getfile(n));
+ Setline(disown, Getline(n));
+ Setattr(disown, "wrap:action", action);
+ Setattr(disown, "name", mrename);
+ Setattr(disown, "sym:name", mrename);
+ Setattr(disown, "type", type);
+ Setattr(disown, "parms", p);
+ Delete(action);
+ Delete(mrename);
+ Delete(type);
+ Delete(p);
+
+ functionWrapper(disown);
+ Delete(disown);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorConstructors()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorConstructors(Node *n) {
+ String *nodeType;
+ Node *parent = Swig_methodclass(n);
+ int default_ctor = Getattr(parent, "allocate:default_constructor") ? 1 : 0;
+ int protected_ctor = 0;
+ int constructor = 0;
+
+ /* emit constructors */
+ List *constructors = NewList();
+ for (Node *ni = firstChild(n); ni; ni = nextSibling(ni)) {
+ nodeType = Getattr(ni, "nodeType");
+ if (Equal(nodeType, "constructor")) {
+ Append(constructors, ni);
+ } else if (Equal(nodeType, "using") && GetFlag(ni, "usingctor")) {
+ for (Node *ui = firstChild(ni); ui; ui = nextSibling(ui)) {
+ Append(constructors, ui);
+ }
+ }
+ }
+ for (Iterator it = First(constructors); it.item; it = Next(it)) {
+ Node *ni = it.item;
+ if (GetFlag(ni, "feature:ignore"))
+ continue;
+
+ Parm *parms = Getattr(ni, "parms");
+ if (is_public(ni)) {
+ /* emit public constructor */
+ classDirectorConstructor(ni);
+ constructor = 1;
+ if (default_ctor)
+ default_ctor = !ParmList_numrequired(parms);
+ } else {
+ /* emit protected constructor if needed */
+ if (need_nonpublic_ctor(ni)) {
+ classDirectorConstructor(ni);
+ constructor = 1;
+ protected_ctor = 1;
+ if (default_ctor)
+ default_ctor = !ParmList_numrequired(parms);
+ }
+ }
+ }
+ Delete(constructors);
+
+ /* emit default constructor if needed */
+ if (!constructor) {
+ if (!default_ctor) {
+ /* we get here because the class has no public, protected or
+ default constructor, therefore, the director class can't be
+ created, ie, is kind of abstract. */
+ Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n), "Director class '%s' can't be constructed\n", SwigType_namestr(Getattr(n, "name")));
+ return SWIG_OK;
+ }
+ classDirectorDefaultConstructor(n);
+ default_ctor = 1;
+ }
+ /* this is just to support old java behavior, ie, the default
+ constructor is always emitted, even when protected, and not
+ needed, since there is a public constructor already defined.
+
+ (scottm) This code is needed here to make the director_abstract +
+ test generate compilable code (Example2 in director_abstract.i).
+
+ (mmatus) This is very strange, since swig compiled with gcc3.2.3
+ doesn't need it here....
+ */
+ if (!default_ctor && !protected_ctor) {
+ if (Getattr(parent, "allocate:default_base_constructor")) {
+ classDirectorDefaultConstructor(n);
+ }
+ }
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorMethods()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorMethods(Node *n) {
+ Node *vtable = Getattr(n, "vtable");
+
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ String *method = Getattr(item, "methodNode");
+ String *fqdname = Getattr(item, "fqdname");
+ if (GetFlag(method, "feature:nodirector") || GetFlag(method, "final"))
+ continue;
+
+ String *wrn = Getattr(method, "feature:warnfilter");
+ if (wrn)
+ Swig_warnfilter(wrn, 1);
+
+ String *type = Getattr(method, "nodeType");
+ if (!Cmp(type, "destructor")) {
+ classDirectorDestructor(method);
+ } else {
+ Swig_require("classDirectorMethods", method, "*type", NIL);
+ assert(Getattr(method, "returntype"));
+ Setattr(method, "type", Getattr(method, "returntype"));
+ if (classDirectorMethod(method, n, fqdname) == SWIG_OK)
+ SetFlag(item, "director");
+ Swig_restore(method);
+ }
+ if (wrn)
+ Swig_warnfilter(wrn, 0);
+ }
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorInit()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorInit(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorDestructor()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorDestructor(Node *n) {
+ /*
+ Always emit the virtual destructor in the declaration and in the
+ compilation unit. Being explicit here can't make any damage, and
+ can solve some nasty C++ compiler problems.
+ */
+ File *f_directors = Swig_filebyname("director");
+ File *f_directors_h = Swig_filebyname("director_h");
+ if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() throw() {\n}\n\n", DirectorClassName, DirectorClassName);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() {\n}\n\n", DirectorClassName, DirectorClassName);
+ }
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirectorEnd()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirectorEnd(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDirector()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDirector(Node *n) {
+ Node *module = Getattr(n, "module");
+ String *classtype = Getattr(n, "classtype");
+ Hash *directormap = 0;
+ if (module) {
+ directormap = Getattr(module, "wrap:directormap");
+ if (directormap == 0) {
+ directormap = NewHash();
+ Setattr(module, "wrap:directormap", directormap);
+ }
+ }
+ List *vtable = NewList();
+ int virtual_destructor = 0;
+ unrollVirtualMethods(n, n, vtable, virtual_destructor);
+
+ // Emit all the using base::member statements for non virtual members (allprotected mode)
+ Node *ni;
+ String *using_protected_members_code = NewString("");
+ for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
+ String *nodeType = nodeType(ni);
+ if (Cmp(nodeType, "destructor") == 0 && GetFlag(ni, "final")) {
+ String *classtype = Getattr(n, "classtype");
+ SWIG_WARN_NODE_BEGIN(ni);
+ Swig_warning(WARN_LANG_DIRECTOR_FINAL, input_file, line_number, "Destructor %s is final, %s cannot be a director class.\n", Swig_name_decl(ni), classtype);
+ SWIG_WARN_NODE_END(ni);
+ SetFlag(n, "feature:nodirector");
+ Delete(vtable);
+ Delete(using_protected_members_code);
+ return SWIG_OK;
+ }
+ Node *nn = ni;
+ bool cdeclaration = Equal(nodeType, "cdecl");
+ if (!cdeclaration && Equal(nodeType, "using")) {
+ nn = Getattr(ni, "firstChild");
+ cdeclaration = nn && Equal(nodeType(nn), "cdecl") ? true : false;
+ }
+ if (cdeclaration && !GetFlag(nn, "feature:ignore")) {
+ if (isNonVirtualProtectedAccess(nn)) {
+ Node *overloaded = Getattr(nn, "sym:overloaded");
+ // emit the using base::member statement (but only once if the method is overloaded)
+ if (!overloaded || (overloaded && (overloaded == nn)))
+ Printf(using_protected_members_code, " using %s::%s;\n", SwigType_namestr(ClassName), Getattr(nn, "name"));
+ }
+ }
+ }
+
+ if (virtual_destructor || Len(vtable) > 0) {
+ if (!virtual_destructor) {
+ String *classtype = Getattr(n, "classtype");
+ Swig_warning(WARN_LANG_DIRECTOR_VDESTRUCT, input_file, line_number, "Director base class %s has no virtual destructor.\n", classtype);
+ }
+
+ Setattr(n, "vtable", vtable);
+ if (directormap != 0) {
+ Setattr(directormap, classtype, n);
+ }
+ classDirectorInit(n);
+ classDirectorConstructors(n);
+ classDirectorMethods(n);
+
+ File *f_directors_h = Swig_filebyname("director_h");
+ Printv(f_directors_h, using_protected_members_code, NIL);
+
+ classDirectorEnd(n);
+ }
+ Delete(vtable);
+ Delete(using_protected_members_code);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::classDeclaration(Node *n) {
+ String *ochildren = Getattr(n, "feature:onlychildren");
+ if (ochildren) {
+ Setattr(n, "feature:emitonlychildren", ochildren);
+ emit_children(n);
+ Delattr(n, "feature:emitonlychildren");
+ SetFlag(n, "feature:ignore");
+ return SWIG_NOWRAP;
+ }
+
+ // save class local variables for nested classes support
+ int oldInClass = InClass;
+ String *oldClassType = ClassType;
+ String *oldClassPrefix = ClassPrefix;
+ String *oldEnumClassPrefix = EnumClassPrefix;
+ String *oldClassName = ClassName;
+ String *oldDirectorClassName = DirectorClassName;
+ String *oldNSpace = NSpace;
+ Node *oldCurrentClass = CurrentClass;
+ int dir = 0;
+
+ String *kind = Getattr(n, "kind");
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *unnamed = Getattr(n, "unnamed");
+ String *symname = Getattr(n, "sym:name");
+
+ 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;
+ }
+
+ /* Check symbol name for template. If not renamed. Issue a warning */
+ if (!validIdentifier(symname)) {
+ 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;
+ }
+ for (; outerClass; outerClass = Getattr(outerClass, "nested:outer")) {
+ Push(ClassPrefix, "_");
+ Push(ClassPrefix, Getattr(outerClass, "sym:name"));
+ }
+ EnumClassPrefix = Copy(ClassPrefix);
+ if (strip) {
+ ClassType = Copy(name);
+ } else {
+ ClassType = NewStringf("%s %s", kind, name);
+ }
+ Setattr(n, "classtypeobj", Copy(ClassType));
+ Setattr(n, "classtype", SwigType_namestr(ClassType));
+
+ InClass = 1;
+ CurrentClass = n;
+ NSpace = Getattr(n, "sym:nspace");
+ int oldAbstract = Abstract;
+
+ /* Call classHandler() here */
+ if (!ImportMode) {
+ if (Swig_directors_enabled()) {
+ int ndir = GetFlag(n, "feature:director");
+ int nndir = GetFlag(n, "feature:nodirector");
+ /* 'nodirector' has precedence over 'director' */
+ dir = (ndir || nndir) ? (ndir && !nndir) : 0;
+ }
+
+ if (dir) {
+ DirectorClassName = directorClassName(n);
+ classDirector(n);
+ }
+
+ /* check for abstract after resolving directors */
+ Abstract = abstractClassTest(n);
+ classHandler(n);
+ } else {
+ Abstract = abstractClassTest(n);
+ Language::classHandler(n);
+ }
+
+ Abstract = oldAbstract;
+ cplus_mode = oldAccessMode;
+ NSpace = oldNSpace;
+ InClass = oldInClass;
+ CurrentClass = oldCurrentClass;
+ Delete(ClassType);
+ ClassType = oldClassType;
+ Delete(EnumClassPrefix);
+ EnumClassPrefix = oldEnumClassPrefix;
+ Delete(ClassPrefix);
+ ClassPrefix = oldClassPrefix;
+ Delete(ClassName);
+ ClassName = oldClassName;
+ if (dir) {
+ Delete(DirectorClassName);
+ }
+ DirectorClassName = oldDirectorClassName;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::classHandler(Node *n) {
+ save_value<int> oldExtend(Extend);
+ if (Getattr(n, "template"))
+ Extend = 0;
+ bool hasDirector = Swig_directorclass(n) ? true : false;
+
+ /* Emit all of the class members */
+ emit_children(n);
+
+ /* Look for smart pointer handling */
+ if (Getattr(n, "allocate:smartpointer")) {
+ List *methods = Getattr(n, "allocate:smartpointer");
+ cplus_mode = PUBLIC;
+ SmartPointer = CWRAP_SMART_POINTER;
+ if (Getattr(n, "allocate:smartpointerconst") && Getattr(n, "allocate:smartpointermutable")) {
+ SmartPointer |= CWRAP_SMART_POINTER_OVERLOAD;
+ }
+ Iterator c;
+ for (c = First(methods); c.item; c = Next(c)) {
+ emit_one(c.item);
+ }
+ SmartPointer = 0;
+ }
+
+ cplus_mode = PUBLIC;
+
+ /* emit director disown method */
+ if (hasDirector) {
+ classDirectorDisown(n);
+
+ /* Emit additional protected virtual methods - only needed if the language module
+ * codes logic in the C++ layer instead of the director proxy class method - primarily
+ * to catch public use of protected methods by the scripting languages. */
+ if (dirprot_mode() && extraDirectorProtectedCPPMethodsRequired()) {
+ Node *vtable = Getattr(n, "vtable");
+ String *symname = Getattr(n, "sym:name");
+ save_value<AccessMode> old_mode(cplus_mode);
+ cplus_mode = PROTECTED;
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ Node *method = Getattr(item, "methodNode");
+ SwigType *type = Getattr(method, "nodeType");
+ if (Strcmp(type, "cdecl") != 0)
+ continue;
+ if (GetFlag(method, "feature:ignore"))
+ continue;
+ String *methodname = Getattr(method, "sym:name");
+ String *wrapname = NewStringf("%s_%s", symname, methodname);
+ if (!symbolLookup(wrapname, "") && (!is_public(method))) {
+ Node *m = Copy(method);
+ Setattr(m, "director", "1");
+ Setattr(m, "parentNode", n);
+ /*
+ * There is a bug that needs fixing still...
+ * This area of code is creating methods which have not been overridden in a derived class (director methods that are protected in the base)
+ * If the method is overloaded, then Swig_overload_dispatch() incorrectly generates a call to the base wrapper, _wrap_xxx method
+ * See director_protected_overloaded.i - Possibly sym:overname needs correcting here.
+ Printf(stdout, "new method: %s::%s(%s)\n", Getattr(parentNode(m), "name"), Getattr(m, "name"), ParmList_str_defaultargs(Getattr(m, "parms")));
+ */
+ cDeclaration(m);
+ Delete(m);
+ }
+ Delete(wrapname);
+ }
+ }
+ }
+
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::classforwardDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::classforwardDeclaration(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::constructorDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::constructorDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+
+ if (!symname)
+ return SWIG_NOWRAP;
+ if (!CurrentClass)
+ return SWIG_NOWRAP;
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ if (Extend) {
+ /* extend default constructor can be safely ignored if there is already one */
+ int num_required = ParmList_numrequired(Getattr(n, "parms"));
+ if ((num_required == 0) && Getattr(CurrentClass, "has_default_constructor")) {
+ return SWIG_NOWRAP;
+ }
+ if ((num_required == 1) && Getattr(CurrentClass, "has_copy_constructor")) {
+ String *ccdecl = Getattr(CurrentClass, "copy_constructor_decl");
+ if (ccdecl && (Strcmp(ccdecl, Getattr(n, "decl")) == 0)) {
+ return SWIG_NOWRAP;
+ }
+ }
+ }
+
+ /* clean protected overloaded constructors, in case they are not needed anymore */
+ Node *over = Swig_symbol_isoverloaded(n);
+ if (over && !Getattr(CurrentClass, "sym:cleanconstructor")) {
+ int dirclass = Swig_directorclass(CurrentClass);
+ Node *nn = over;
+ while (nn) {
+ if (!is_public(nn)) {
+ if (!dirclass || !need_nonpublic_ctor(nn)) {
+ SetFlag(nn, "feature:ignore");
+ }
+ }
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ clean_overloaded(over);
+ Setattr(CurrentClass, "sym:cleanconstructor", "1");
+ }
+
+ if (!is_public(n)) {
+ /* check only for director classes */
+ if (!Swig_directorclass(CurrentClass) || !need_nonpublic_ctor(n))
+ return SWIG_NOWRAP;
+ }
+
+ // Name adjustment of constructor when a class has been renamed with %rename
+ Swig_save("constructorDeclaration", n, "sym:name", NIL);
+
+ {
+ String *base = Swig_scopename_last(name);
+ // Note that it is possible for the constructor to have a different name to the class name in
+ // some target languages, where it is wrapped as a factory type function instead of a constructor.
+ if (Equal(base, symname) && !Equal(symname, ClassPrefix)) {
+ // Adjust name, except when the constructor's name comes from a templated constructor,
+ // where the name passed to %template is used instead.
+ if (!Getattr(n, "template"))
+ Setattr(n, "sym:name", ClassPrefix);
+ }
+ Delete(base);
+ }
+
+ /* Only create a constructor if the class is not abstract */
+ if (!Abstract) {
+ Node *over;
+ over = Swig_symbol_isoverloaded(n);
+ if (over)
+ over = first_nontemplate(over);
+ if ((over) && (!overloading)) {
+ /* If the symbol is overloaded. We check to see if it is a copy constructor. If so,
+ we invoke copyconstructorHandler() as a special case. */
+ if (Getattr(n, "copy_constructor") && (!Getattr(CurrentClass, "has_copy_constructor"))) {
+ copyconstructorHandler(n);
+ Setattr(CurrentClass, "has_copy_constructor", "1");
+ } else {
+ if (Getattr(over, "copy_constructor"))
+ over = Getattr(over, "sym:nextSibling");
+ if (over != n) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, input_file, line_number,
+ "Overloaded constructor ignored. %s\n", Swig_name_decl(n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONSTRUCT, Getfile(over), Getline(over),
+ "Previous declaration is %s\n", Swig_name_decl(over));
+ } else {
+ constructorHandler(n);
+ }
+ }
+ } else {
+ String *expected_name = ClassName;
+ 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) && !SwigType_istemplate(expected_name) && !SwigType_istemplate(actual_name)) {
+ // Checking templates is skipped but they ought to be checked... they are just somewhat more tricky to check correctly
+ bool illegal_name = true;
+ if (Extend) {
+ // Check for typedef names used as a constructor name in %extend. This is deprecated except for anonymous
+ // typedef structs which have had their symbol names adjusted to the typedef name in the parser.
+ SwigType *name_resolved = SwigType_typedef_resolve_all(actual_name);
+ SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name);
+
+ if (!CPlusPlus) {
+ if (Strncmp(name_resolved, "struct ", 7) == 0)
+ Replace(name_resolved, "struct ", "", DOH_REPLACE_FIRST);
+ else if (Strncmp(name_resolved, "union ", 6) == 0)
+ Replace(name_resolved, "union ", "", DOH_REPLACE_FIRST);
+ }
+
+ illegal_name = !Equal(name_resolved, expected_name_resolved);
+ if (!illegal_name)
+ Swig_warning(WARN_LANG_EXTEND_CONSTRUCTOR, input_file, line_number, "Use of an illegal constructor name '%s' in %%extend is deprecated, the constructor name should be '%s'.\n",
+ SwigType_str(Swig_scopename_last(actual_name), 0), SwigType_str(Swig_scopename_last(expected_name), 0));
+ Delete(name_resolved);
+ Delete(expected_name_resolved);
+ }
+ if (illegal_name) {
+ Swig_warning(WARN_LANG_RETURN_TYPE, input_file, line_number, "Function %s must have a return type. Ignored.\n", Swig_name_decl(n));
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+ }
+ constructorHandler(n);
+ }
+ }
+
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * get_director_ctor_code()
+ * ---------------------------------------------------------------------- */
+
+static String *get_director_ctor_code(Node *n, String *director_ctor_code, String *director_prot_ctor_code, List *&abstracts) {
+ String *director_ctor = director_ctor_code;
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ Node *pn = Swig_methodclass(n);
+ abstracts = Getattr(pn, "abstracts");
+ if (director_prot_ctor_code) {
+ int is_notabstract = GetFlag(pn, "feature:notabstract");
+ int is_abstract = abstracts && !is_notabstract;
+ if (is_protected(n) || is_abstract) {
+ director_ctor = director_prot_ctor_code;
+ abstracts = Copy(abstracts);
+ Delattr(pn, "abstracts");
+ } else {
+ if (is_notabstract) {
+ abstracts = Copy(abstracts);
+ Delattr(pn, "abstracts");
+ } else {
+ abstracts = 0;
+ }
+ }
+ }
+ }
+ return director_ctor;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Language::constructorHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::constructorHandler(Node *n) {
+ Swig_require("constructorHandler", n, "?name", "*sym:name", "?type", "?parms", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_construct(NSpace, symname);
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ List *abstracts = 0;
+ String *director_ctor = get_director_ctor_code(n, director_ctor_code,
+ director_prot_ctor_code,
+ abstracts);
+ if (!constructor) {
+ /* if not originally a constructor, still handle it as one */
+ Setattr(n, "handled_as_constructor", "1");
+ }
+
+ int extendmember = GetFlag(n, "isextendmember") ? Extend : 0;
+ int flags = Getattr(n, "template") ? extendmember : Extend;
+ Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, flags, DirectorClassName);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ if (abstracts)
+ Setattr(Swig_methodclass(n), "abstracts", abstracts);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::copyconstructorHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::copyconstructorHandler(Node *n) {
+ Swig_require("copyconstructorHandler", n, "?name", "*sym:name", "?type", "?parms", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_copyconstructor(NSpace, symname);
+ List *abstracts = 0;
+ String *director_ctor = get_director_ctor_code(n, director_ctor_code,
+ director_prot_ctor_code,
+ abstracts);
+ Swig_ConstructorToFunction(n, NSpace, ClassType, none_comparison, director_ctor, CPlusPlus, Getattr(n, "template") ? 0 : Extend, DirectorClassName);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ if (abstracts)
+ Setattr(Swig_methodclass(n), "abstracts", abstracts);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::destructorDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::destructorDeclaration(Node *n) {
+
+ if (!CurrentClass)
+ return SWIG_NOWRAP;
+ if (cplus_mode != PUBLIC && !Getattr(CurrentClass, "feature:unref"))
+ return SWIG_NOWRAP;
+ if (ImportMode)
+ return SWIG_NOWRAP;
+
+ Swig_save("destructorDeclaration", n, "name", "sym:name", NIL);
+
+ char *c = GetChar(n, "sym:name");
+ if (c && (*c == '~')) {
+ Setattr(n, "sym:name", c + 1);
+ }
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+
+ if ((Strcmp(name, symname) == 0) || (Strcmp(symname, ClassPrefix) != 0)) {
+ Setattr(n, "sym:name", ClassPrefix);
+ }
+
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(ClassName, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ String *expected_name = NewStringf("~%s", tprefix);
+
+ String *actual_name = Copy(name);
+ if (!Equal(actual_name, expected_name) && !(Getattr(n, "template"))) {
+ bool illegal_name = true;
+ if (Extend) {
+ // Check for typedef names used as a destructor name in %extend. This is deprecated except for anonymous
+ // typedef structs which have had their symbol names adjusted to the typedef name in the parser.
+ Replace(actual_name, "~", "", DOH_REPLACE_FIRST);
+ Replace(expected_name, "~", "", DOH_REPLACE_FIRST);
+ if (Len(nprefix) > 0) {
+ String *old_actual_name = actual_name;
+ String *old_expected_name = expected_name;
+ actual_name = NewStringf("%s::%s", nprefix, actual_name);
+ expected_name = NewStringf("%s::%s", nprefix, expected_name);
+ Delete(old_expected_name);
+ Delete(old_actual_name);
+ }
+ SwigType *name_resolved = SwigType_typedef_resolve_all(actual_name);
+ SwigType *expected_name_resolved = SwigType_typedef_resolve_all(expected_name);
+
+ if (!CPlusPlus) {
+ if (Strncmp(name_resolved, "struct ", 7) == 0)
+ Replace(name_resolved, "struct ", "", DOH_REPLACE_FIRST);
+ else if (Strncmp(name_resolved, "union ", 6) == 0)
+ Replace(name_resolved, "union ", "", DOH_REPLACE_FIRST);
+ }
+
+ illegal_name = !Equal(name_resolved, expected_name_resolved);
+ if (!illegal_name)
+ Swig_warning(WARN_LANG_EXTEND_DESTRUCTOR, input_file, line_number, "Use of an illegal destructor name '%s' in %%extend is deprecated, the destructor name should be '%s'.\n",
+ SwigType_str(Swig_scopename_last(actual_name), 0), SwigType_str(Swig_scopename_last(expected_name), 0));
+ Delete(name_resolved);
+ Delete(expected_name_resolved);
+ }
+
+ if (illegal_name) {
+ Swig_warning(WARN_LANG_ILLEGAL_DESTRUCTOR, input_file, line_number, "Illegal destructor name %s. Ignored.\n", Swig_name_decl(n));
+ Swig_restore(n);
+ Delete(tprefix);
+ Delete(nlast);
+ Delete(nprefix);
+ Delete(expected_name);
+ Delete(actual_name);
+ return SWIG_NOWRAP;
+ }
+ }
+ destructorHandler(n);
+
+ Setattr(CurrentClass, "has_destructor", "1");
+ Swig_restore(n);
+ Delete(tprefix);
+ Delete(nlast);
+ Delete(nprefix);
+ Delete(expected_name);
+ Delete(actual_name);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::destructorHandler()
+ * ---------------------------------------------------------------------- */
+
+int Language::destructorHandler(Node *n) {
+ Swig_require("destructorHandler", n, "?name", "*sym:name", NIL);
+ Swig_save("destructorHandler", n, "type", "parms", NIL);
+
+ String *symname = Getattr(n, "sym:name");
+ String *mrename;
+ char *csymname = Char(symname);
+ if (*csymname == '~')
+ csymname += 1;
+
+ mrename = Swig_name_destroy(NSpace, csymname);
+
+ Swig_DestructorToFunction(n, NSpace, ClassType, CPlusPlus, Extend);
+ Setattr(n, "sym:name", mrename);
+ functionWrapper(n);
+ Delete(mrename);
+ Swig_restore(n);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::accessDeclaration()
+ * ---------------------------------------------------------------------- */
+
+int Language::accessDeclaration(Node *n) {
+ cplus_mode = accessModeFromString(Getattr(n, "kind"));
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::namespaceDeclaration()
+ * ----------------------------------------------------------------------------- */
+
+int Language::namespaceDeclaration(Node *n) {
+ if (Getattr(n, "alias"))
+ return SWIG_OK;
+ if (Getattr(n, "unnamed"))
+ return SWIG_OK;
+ emit_children(n);
+ return SWIG_OK;
+}
+
+int Language::validIdentifier(String *s) {
+ char *c = Char(s);
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '_')))
+ return 0;
+ c++;
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::usingDeclaration()
+ * ----------------------------------------------------------------------------- */
+
+int Language::usingDeclaration(Node *n) {
+ if ((cplus_mode == PUBLIC) || (!is_public(n) && dirprot_mode())) {
+ Node *np = Copy(n);
+ Node *c;
+ for (c = firstChild(np); c; c = nextSibling(c)) {
+ /* it seems for some cases this is needed, like A* A::boo() */
+ if (CurrentClass)
+ Setattr(c, "parentNode", CurrentClass);
+ emit_one(c);
+ }
+ Delete(np);
+ }
+ return SWIG_OK;
+}
+
+/* Stubs. Language modules need to implement these */
+
+/* ----------------------------------------------------------------------
+ * Language::constantWrapper()
+ * ---------------------------------------------------------------------- */
+
+int Language::constantWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *str = SwigType_str(type, name);
+ Printf(stdout, "constantWrapper : %s = %s\n", str, value);
+ Delete(str);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::variableWrapper()
+ * ---------------------------------------------------------------------- */
+
+int Language::variableWrapper(Node *n) {
+ Swig_require("variableWrapper", n, "*name", "*sym:name", "*type", "?parms", "?varset", "?varget", NIL);
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+
+ Delattr(n,"varset");
+ Delattr(n,"varget");
+
+ String *newsymname = 0;
+ if (!CurrentClass && EnumClassPrefix) {
+ newsymname = Swig_name_member(0, EnumClassPrefix, symname);
+ symname = newsymname;
+ }
+
+ /* If no way to set variables. We simply create functions */
+ int assignable = !is_immutable(n);
+ int flags = use_naturalvar_mode(n);
+ if (!GetFlag(n, "wrappedasconstant"))
+ flags = flags | Extend;
+
+ if (assignable) {
+ int make_set_wrapper = 1;
+ String *tm = Swig_typemap_lookup("globalin", n, name, 0);
+
+ Swig_VarsetToFunction(n, flags);
+ String *sname = Swig_name_set(NSpace, symname);
+ Setattr(n, "sym:name", sname);
+ Delete(sname);
+
+ if (!tm) {
+ if (SwigType_isarray(type)) {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(type, 0));
+ make_set_wrapper = 0;
+ }
+ } else {
+ String *pname0 = Swig_cparm_name(0, 0);
+ Replace(tm, "$input", pname0, DOH_REPLACE_ANY);
+ Setattr(n, "wrap:action", tm);
+ Delete(tm);
+ Delete(pname0);
+ }
+ if (make_set_wrapper) {
+ Setattr(n, "varset", "1");
+ functionWrapper(n);
+ } else {
+ SetFlag(n, "feature:immutable");
+ }
+ /* Restore parameters */
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "type", type);
+ Setattr(n, "name", name);
+ Delattr(n, "varset");
+
+ /* Delete all attached typemaps and typemap attributes */
+ Iterator ki;
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(ki.key, "tmap:", 5) == 0)
+ Delattr(n, ki.key);
+ }
+ }
+
+ Swig_VargetToFunction(n, flags);
+ String *gname = Swig_name_get(NSpace, symname);
+ Setattr(n, "sym:name", gname);
+ Delete(gname);
+ Setattr(n, "varget", "1");
+ functionWrapper(n);
+ Delattr(n, "varget");
+ Swig_restore(n);
+ Delete(newsymname);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * Language::functionWrapper()
+ * ---------------------------------------------------------------------- */
+
+int Language::functionWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+
+ Printf(stdout, "functionWrapper : %s\n", SwigType_str(type, NewStringf("%s(%s)", name, ParmList_str_defaultargs(parms))));
+ Printf(stdout, " action : %s\n", Getattr(n, "wrap:action"));
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::nativeWrapper()
+ * ----------------------------------------------------------------------------- */
+
+int Language::nativeWrapper(Node *n) {
+ (void) n;
+ return SWIG_OK;
+}
+
+void Language::main(int argc, char *argv[]) {
+ (void) argc;
+ (void) argv;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::addSymbol()
+ *
+ * Adds a symbol entry into the target language symbol tables.
+ * Returns 1 if the symbol is added successfully.
+ * Prints an error message and returns 0 if a conflict occurs.
+ * The scope is optional for target languages and if supplied must be a fully
+ * qualified scope and the symbol s must not contain any scope qualifiers.
+ * ----------------------------------------------------------------------------- */
+
+int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
+ //Printf( stdout, "addSymbol: %s %s %s:%d\n", s, scope, Getfile(n), Getline(n) );
+ Hash *symbols = symbolScopeLookup(scope);
+ if (!symbols) {
+ symbols = symbolAddScope(scope);
+ } else {
+ Node *c = Getattr(symbols, s);
+ if (c && (c != n)) {
+ if (scope && Len(scope) > 0)
+ Swig_error(input_file, line_number, "'%s' is multiply defined in the generated target language module in scope '%s'.\n", s, scope);
+ else
+ Swig_error(input_file, line_number, "'%s' is multiply defined in the generated target language module.\n", s);
+ Swig_error(Getfile(c), Getline(c), "Previous declaration of '%s'\n", s);
+ return 0;
+ }
+ }
+ Setattr(symbols, s, n);
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::addInterfaceSymbol()
+ *
+ * Adds a symbol entry into the target language symbol tables - for the interface
+ * feature only.
+ * Returns 1 if the symbol is added successfully.
+ * The scope is as per addSymbol.
+ * ----------------------------------------------------------------------------- */
+
+int Language::addInterfaceSymbol(const String *interface_name, Node *n, const_String_or_char_ptr scope) {
+ if (interface_name) {
+ Node *existing_symbol = symbolLookup(interface_name, scope);
+ if (existing_symbol) {
+ String *proxy_class_name = Getattr(n, "sym:name");
+ Swig_error(input_file, line_number, "The interface feature name '%s' for proxy class '%s' is already defined in the generated target language module in scope '%s'.\n",
+ interface_name, proxy_class_name, scope);
+ Swig_error(Getfile(existing_symbol), Getline(existing_symbol), "Previous declaration of '%s'\n", interface_name);
+ return 0;
+ }
+ if (!addSymbol(interface_name, n, scope))
+ return 0;
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolAddScope()
+ *
+ * Creates a scope (symbols Hash) for given name. This method is auxiliary,
+ * you don't have to call it - addSymbol will lazily create scopes automatically.
+ * If scope with given name already exists, then do nothing.
+ * Returns newly created (or already existing) scope.
+ * ----------------------------------------------------------------------------- */
+Hash *Language::symbolAddScope(const_String_or_char_ptr scope/*, Node *n*/) {
+ Hash *symbols = symbolScopeLookup(scope);
+ if (!symbols) {
+ // The order in which the following code is executed is important. In the Language
+ // constructor symbolAddScope("") is called to create a top level scope.
+ // Thus we must first add a symbols hash to symtab and only then add pseudo
+ // symbols to the top-level scope.
+
+ // New scope which has not been added by the target language - lazily created.
+ symbols = NewHash();
+ Setattr(symtabs, scope, symbols);
+
+ // Add the new scope as a symbol in the top level scope.
+ // Alternatively the target language must add it in before attempting to add symbols into the scope.
+ const_String_or_char_ptr top_scope = "";
+ Hash *topscope_symbols = Getattr(symtabs, top_scope);
+
+ // TODO:
+ // Stop using pseudo scopes, the symbol Node containing the new scope should be passed into this function.
+ // This will require explicit calls to symbolScopeLookup() in each language and removing the call from addSymbol().
+ // addSymbol() should then instead assert that the scope exists.
+ // All this just to fix up the file/line numbering of the scopes for error reporting.
+ //Node *symbol = n;
+ Node *symbol = Getattr(topscope_symbols, scope);
+
+ Hash *pseudo_symbol = 0;
+ if (symbol) {
+ pseudo_symbol = symbol;
+ } else {
+ pseudo_symbol = NewHash();
+ Setattr(pseudo_symbol, "sym:scope", "1");
+ }
+ Setattr(topscope_symbols, scope, pseudo_symbol);
+ }
+ return symbols;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolScopeLookup()
+ *
+ * Lookup and returns a symtable (hash) representing given scope. Hash contains
+ * all symbols in this scope.
+ * ----------------------------------------------------------------------------- */
+Hash *Language::symbolScopeLookup(const_String_or_char_ptr scope) {
+ Hash *symbols = Getattr(symtabs, scope ? scope : "");
+ return symbols;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolScopePseudoSymbolLookup()
+ *
+ * For every scope there is a special pseudo-symbol in the top scope (""). It
+ * exists solely to detect name clashes. This pseudo symbol may contain a few properties,
+ * but more could be added. This is also true for the top level scope ("").
+ * It contains a pseudo symbol with name "" (empty). Pseudo symbol contains the
+ * following properties:
+ * sym:scope = "1" - a flag that this is a scope pseudo symbol
+ *
+ * Pseudo symbols are a Hash*, not a Node*.
+ * There is no difference from symbolLookup() method except for signature
+ * and return type.
+ * ----------------------------------------------------------------------------- */
+Hash *Language::symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope)
+{
+ /* Getting top scope */
+ const_String_or_char_ptr top_scope = "";
+ Hash *symbols = Getattr(symtabs, top_scope);
+ return Getattr(symbols, scope);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::dumpSymbols()
+ * ----------------------------------------------------------------------------- */
+
+void Language::dumpSymbols() {
+ Printf(stdout, "LANGUAGE SYMBOLS start =======================================\n");
+
+ Node *table = symtabs;
+ Iterator ki = First(table);
+ while (ki.key) {
+ String *k = ki.key;
+ Printf(stdout, "===================================================\n");
+ Printf(stdout, "%s -\n", k);
+ {
+ Symtab *symtab = Getattr(table, k);
+ Iterator it = First(symtab);
+ while (it.key) {
+ String *symname = it.key;
+ Printf(stdout, " %s\n", symname);
+ //Printf(stdout, " %s (%s:%d)\n", symname, Getfile(it.item), Getline(it.item));
+ it = Next(it);
+ }
+ }
+ ki = Next(ki);
+ }
+
+ Printf(stdout, "LANGUAGE SYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::symbolLookup()
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::symbolLookup(const String *s, const_String_or_char_ptr scope) {
+ Hash *symbols = Getattr(symtabs, scope ? scope : "");
+ if (!symbols) {
+ return NULL;
+ }
+ return Getattr(symbols, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::classLookup()
+ *
+ * Tries to locate a class from a type definition
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::classLookup(const SwigType *s) {
+ static Hash *classtypes = 0;
+
+ Node *n = 0;
+
+ /* Look in hash of cached values */
+ n = classtypes ? Getattr(classtypes, s) : 0;
+ if (!n) {
+ Symtab *stab = 0;
+ SwigType *ty1 = SwigType_typedef_resolve_all(s);
+ SwigType *ty2 = SwigType_strip_qualifiers(ty1);
+
+ String *base = SwigType_base(ty2);
+
+ Replaceall(base, "class ", "");
+ Replaceall(base, "struct ", "");
+ Replaceall(base, "union ", "");
+
+ if (strncmp(Char(base), "::", 2) == 0) {
+ String *oldbase = base;
+ base = NewString(Char(base) + 2);
+ Delete(oldbase);
+ }
+
+ String *prefix = SwigType_prefix(ty2);
+
+ /* Do a symbol table search on the base type */
+ while (!n) {
+ Hash *nstab;
+ n = Swig_symbol_clookup(base, stab);
+ if (!n)
+ break;
+ if (Strcmp(nodeType(n), "class") == 0)
+ break;
+ Node *sibling = n;
+ while (sibling) {
+ sibling = Getattr(sibling, "csym:nextSibling");
+ if (sibling && Strcmp(nodeType(sibling), "class") == 0)
+ break;
+ }
+ if (sibling)
+ break;
+ n = parentNode(n);
+ if (!n)
+ break;
+ nstab = Getattr(n, "sym:symtab");
+ n = 0;
+ if ((!nstab) || (nstab == stab)) {
+ break;
+ }
+ stab = nstab;
+ }
+ if (n) {
+ /* Found a match. Look at the prefix. We only allow
+ the cases where we want a proxy class for the particular type */
+ bool acceptable_prefix =
+ (Len(prefix) == 0) || // simple type (pass by value)
+ (Strcmp(prefix, "p.") == 0) || // pointer
+ (Strcmp(prefix, "r.") == 0) || // reference
+ (Strcmp(prefix, "z.") == 0) || // rvalue reference
+ SwigType_prefix_is_simple_1D_array(prefix); // Simple 1D array (not arrays of pointers/references)
+ // Also accept pointer by const reference, not non-const pointer reference
+ if (!acceptable_prefix && (Strcmp(prefix, "r.p.") == 0)) {
+ Delete(prefix);
+ prefix = SwigType_prefix(ty1);
+ acceptable_prefix = (Strncmp(prefix, "r.q(const", 9) == 0);
+ }
+ if (acceptable_prefix) {
+ SwigType *cs = Copy(s);
+ if (!classtypes)
+ classtypes = NewHash();
+ Setattr(classtypes, cs, n);
+ Delete(cs);
+ } else {
+ n = 0;
+ }
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(ty2);
+ Delete(ty1);
+ }
+ if (n && (GetFlag(n, "feature:ignore") || Getattr(n, "feature:onlychildren"))) {
+ n = 0;
+ }
+
+ return n;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::enumLookup()
+ *
+ * Finds and returns the Node containing the enum declaration for the (enum)
+ * type passed in.
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::enumLookup(SwigType *s) {
+ static Hash *enumtypes = 0;
+
+ Node *n = 0;
+
+ /* Look in hash of cached values */
+ n = enumtypes ? Getattr(enumtypes, s) : 0;
+ if (!n) {
+ Symtab *stab = 0;
+ SwigType *lt = SwigType_ltype(s);
+ SwigType *ty1 = SwigType_typedef_resolve_all(lt);
+ SwigType *ty2 = SwigType_strip_qualifiers(ty1);
+
+ String *base = SwigType_base(ty2);
+
+ Replaceall(base, "enum ", "");
+ String *prefix = SwigType_prefix(ty2);
+
+ if (strncmp(Char(base), "::", 2) == 0) {
+ String *oldbase = base;
+ base = NewString(Char(base) + 2);
+ Delete(oldbase);
+ }
+
+ /* Look for type in symbol table */
+ while (!n) {
+ Hash *nstab;
+ n = Swig_symbol_clookup(base, stab);
+ if (!n)
+ break;
+ if (Equal(nodeType(n), "enum"))
+ break;
+ if (Equal(nodeType(n), "enumforward") && GetFlag(n, "enumMissing"))
+ break;
+ n = parentNode(n);
+ if (!n)
+ break;
+ nstab = Getattr(n, "sym:symtab");
+ n = 0;
+ if ((!nstab) || (nstab == stab)) {
+ break;
+ }
+ stab = nstab;
+ }
+ if (n) {
+ /* Found a match. Look at the prefix. We only allow simple types. */
+ if (Len(prefix) == 0) { /* Simple type */
+ if (!enumtypes)
+ enumtypes = NewHash();
+ Setattr(enumtypes, Copy(s), n);
+ } else {
+ n = 0;
+ }
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(ty2);
+ Delete(ty1);
+ Delete(lt);
+ }
+ if (n && (GetFlag(n, "feature:ignore"))) {
+ n = 0;
+ }
+
+ return n;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_overloading()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_overloading(int val) {
+ overloading = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_multiple_input()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_multiple_input(int val) {
+ multiinput = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::enable_cplus_runtime_mode()
+ * ----------------------------------------------------------------------------- */
+
+void Language::enable_cplus_runtime_mode() {
+ cplus_runtime = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::cplus_runtime_mode()
+ * ----------------------------------------------------------------------------- */
+
+int Language::cplus_runtime_mode() {
+ return cplus_runtime;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::directorLanguage()
+ * ----------------------------------------------------------------------------- */
+
+void Language::directorLanguage(int val) {
+ director_language = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_directors()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_directors(int val) {
+ directors_allowed = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_dirprot()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_dirprot(int val) {
+ director_protected_mode = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::allow_allprotected()
+ * ----------------------------------------------------------------------------- */
+
+void Language::allow_allprotected(int val) {
+ all_protected_mode = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::dirprot_mode()
+ * ----------------------------------------------------------------------------- */
+
+int Language::dirprot_mode() const {
+ return Swig_directors_enabled() ? director_protected_mode : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::need_nonpublic_ctor()
+ * ----------------------------------------------------------------------------- */
+
+int Language::need_nonpublic_ctor(Node *n) {
+ /*
+ detects when a protected constructor is needed, which is always
+ the case if 'dirprot' mode is used. However, if that is not the
+ case, we will try to strictly emit what is minimal to don't break
+ the generated, while preserving compatibility with java, which
+ always try to emit the default constructor.
+
+ rules:
+
+ - when dirprot mode is used, the protected constructors are
+ always needed.
+
+ - the protected default constructor is always needed.
+
+ - if dirprot mode is not used, the protected constructors will be
+ needed only if:
+
+ - there is no any public constructor in the class, and
+ - there is no protected default constructor
+
+ In that case, all the declared protected constructors are
+ needed since we don't know which one to pick up.
+
+ Note: given all the complications here, I am always in favor to
+ always enable 'dirprot', since is the C++ idea of protected
+ members, and use %ignore for the method you don't want to add in
+ the director class.
+ */
+ if (Swig_directors_enabled()) {
+ if (is_protected(n)) {
+ if (dirprot_mode()) {
+ /* when using dirprot mode, the protected constructors are
+ always needed */
+ return 1;
+ } else {
+ int is_default_ctor = !ParmList_numrequired(Getattr(n, "parms"));
+ if (is_default_ctor) {
+ /* the default protected constructor is always needed, for java compatibility */
+ return 1;
+ } else {
+ /* check if there is a public constructor */
+ Node *parent = Swig_methodclass(n);
+ int public_ctor = Getattr(parent, "allocate:default_constructor")
+ || Getattr(parent, "allocate:public_constructor");
+ if (!public_ctor) {
+ /* if not, the protected constructor will be needed only
+ if there is no protected default constructor declared */
+ int no_prot_default_ctor = !Getattr(parent, "allocate:default_base_constructor");
+ return no_prot_default_ctor;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::need_nonpublic_member()
+ * ----------------------------------------------------------------------------- */
+int Language::need_nonpublic_member(Node *n) {
+ if (Swig_directors_enabled() && DirectorClassName) {
+ if (is_protected(n)) {
+ if (dirprot_mode()) {
+ /* when using dirprot mode, the protected members are always needed. */
+ return 1;
+ } else {
+ /* if the method is pure virtual, we need it. */
+ int pure_virtual = (Cmp(Getattr(n, "value"), "0") == 0);
+ return pure_virtual;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Language::is_smart_pointer()
+ * ----------------------------------------------------------------------------- */
+
+int Language::is_smart_pointer() const {
+ return SmartPointer;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::makeParameterName()
+ *
+ * Inputs:
+ * n - Node
+ * p - parameter node
+ * arg_num - parameter argument number
+ * setter - set this flag when wrapping variables
+ * Return:
+ * arg - a unique parameter name
+ * ----------------------------------------------------------------------------- */
+String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
+
+ String *arg = 0;
+ String *pn = Getattr(p, "name");
+
+ // Check if parameter name is a duplicate.
+ int count = 0;
+ Parm *first_duplicate_parm = 0;
+ ParmList *plist = Getattr(n, "parms");
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0)) {
+ if (!first_duplicate_parm)
+ first_duplicate_parm = plist;
+ count++;
+ }
+ plist = nextSibling(plist);
+ }
+
+ // If the parameter has no name at all or has a non-unique name, replace it with "argN".
+ // On the assumption that p is pointer/element in plist, only replace the 2nd and subsequent duplicates
+ if (!pn || (count > 1 && p != first_duplicate_parm)) {
+ arg = NewStringf("arg%d", arg_num);
+ } else {
+ // Otherwise, try to use the original C name, but modify it if necessary to avoid conflicting with the language keywords.
+ arg = Swig_name_make(p, 0, pn, 0, 0);
+ }
+
+ if (setter && Cmp(arg, "self") != 0) {
+ // Some languages (C#) insist on calling the input variable "value" while
+ // others (D, Java) could, in principle, use something different but this
+ // would require more work, and so we just use "value" for them too.
+ // For setters the parameter name sometimes includes C++ scope resolution which needs removing.
+ Delete(arg);
+ arg = NewString("value");
+ }
+
+ return arg;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::isNonVirtualProtectedAccess(Node *n) const {
+ // Ideally is_non_virtual_protected_access() would contain all this logic, see
+ // comments therein about vtable.
+ return DirectorClassName && is_non_virtual_protected_access(n);
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::extraDirectorProtectedCPPMethodsRequired()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::extraDirectorProtectedCPPMethodsRequired() const {
+ return true;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::nestedClassesSupport()
+ * ----------------------------------------------------------------------------- */
+
+Language::NestedClassSupport Language::nestedClassesSupport() const {
+ return NCS_Unknown;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::kwargsSupport()
+ * ----------------------------------------------------------------------------- */
+
+bool Language::kwargsSupport() const {
+ return false;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::is_wrapping_class()
+ * ----------------------------------------------------------------------------- */
+
+int Language::is_wrapping_class() const {
+ return InClass;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getCurrentClass()
+ * ----------------------------------------------------------------------------- */
+
+Node *Language::getCurrentClass() const {
+ return CurrentClass;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getNSpace()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getNSpace() const {
+ return NSpace;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassName()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassName() const {
+ return ClassName;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassPrefix()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassPrefix() const {
+ return ClassPrefix;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getEnumClassPrefix()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getEnumClassPrefix() const {
+ return EnumClassPrefix;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::getClassType()
+ * ----------------------------------------------------------------------------- */
+
+String *Language::getClassType() const {
+ return ClassType;
+}
+
+/* -----------------------------------------------------------------------------
+ * Dispatcher::abstractClassTest()
+ * ----------------------------------------------------------------------------- */
+//#define SWIG_DEBUG
+int Dispatcher::abstractClassTest(Node *n) {
+ /* check for non public operator new */
+ if (GetFlag(n, "feature:notabstract"))
+ return 0;
+ if (Getattr(n, "allocate:nonew"))
+ return 1;
+
+ // A class cannot be instantiated if one of its bases has a private destructor
+ // Note that if the above does not hold the class can be instantiated if its own destructor is private
+ List *bases = Getattr(n, "bases");
+ if (bases) {
+ for (int i = 0; i < Len(bases); i++) {
+ Node *b = Getitem(bases, i);
+ if (GetFlag(b, "allocate:private_destructor"))
+ return 1;
+ }
+ }
+
+ /* now check for the rest */
+ List *abstracts = Getattr(n, "abstracts");
+ if (!abstracts)
+ return 0;
+ int labs = Len(abstracts);
+#ifdef SWIG_DEBUG
+ List *allbases = Getattr(n, "allbases");
+ Printf(stderr, "testing %s %d %d\n", Getattr(n, "name"), labs, Len(allbases));
+#endif
+ if (!labs)
+ return 0; /*strange, but need to be fixed */
+ if (abstracts && !Swig_directors_enabled())
+ return 1;
+ if (!GetFlag(n, "feature:director"))
+ return 1;
+
+ Node *dirabstract = 0;
+ Node *vtable = Getattr(n, "vtable");
+ if (vtable) {
+#ifdef SWIG_DEBUG
+ Printf(stderr, "vtable %s %d %d\n", Getattr(n, "name"), Len(vtable), labs);
+#endif
+ for (int i = 0; i < labs; i++) {
+ Node *ni = Getitem(abstracts, i);
+ String *method_id = vtable_method_id(ni);
+ if (!method_id)
+ continue;
+ bool exists_item = false;
+ int len = Len(vtable);
+ for (int i = 0; i < len; i++) {
+ Node *item = Getitem(vtable, i);
+ String *check_item = Getattr(item, "vmid");
+ if (Strcmp(method_id, check_item) == 0) {
+ exists_item = true;
+ break;
+ }
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "method %s %d\n", method_id, exists_item ? 1 : 0);
+#endif
+ Delete(method_id);
+ if (!exists_item) {
+ dirabstract = ni;
+ break;
+ }
+ }
+ if (dirabstract) {
+ if (is_public(dirabstract)) {
+ Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n),
+ "Director class '%s' is abstract, abstract method '%s' is not accessible, maybe due to multiple inheritance or 'nodirector' feature\n",
+ SwigType_namestr(Getattr(n, "name")), Getattr(dirabstract, "name"));
+ } else {
+ Swig_warning(WARN_LANG_DIRECTOR_ABSTRACT, Getfile(n), Getline(n),
+ "Director class '%s' is abstract, abstract method '%s' is private\n", SwigType_namestr(Getattr(n, "name")), Getattr(dirabstract, "name"));
+ }
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+ return 0;
+}
+
+void Language::setSubclassInstanceCheck(String *nc) {
+ none_comparison = nc;
+}
+
+void Language::setOverloadResolutionTemplates(String *argc, String *argv) {
+ Delete(argc_template_string);
+ argc_template_string = Copy(argc);
+ Delete(argv_template_string);
+ argv_template_string = Copy(argv);
+}
+
+int Language::is_immutable(Node *n) {
+ return GetFlag(n, "feature:immutable");
+}
+
+String *Language::runtimeCode() {
+ return NewString("");
+}
+
+String *Language::defaultExternalRuntimeFilename() {
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Language::replaceSpecialVariables()
+ *
+ * Language modules should implement this if special variables are to be handled
+ * correctly in the $typemap(...) special variable macro.
+ * method - typemap method name
+ * tm - string containing typemap contents
+ * parm - a parameter describing the typemap type to be handled
+ * ----------------------------------------------------------------------------- */
+void Language::replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ (void)tm;
+ (void)parm;
+}
+
+Language *Language::instance() {
+ return this_;
+}
+
+Hash *Language::getClassHash() const {
+ return classhash;
+}
+
diff --git a/contrib/tools/swig/Source/Modules/lua.cxx b/contrib/tools/swig/Source/Modules/lua.cxx
new file mode 100644
index 00000000000..10e24e01ffa
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/lua.cxx
@@ -0,0 +1,2239 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * lua.cxx
+ *
+ * Lua language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+/* NEW LANGUAGE NOTE:
+ * ver001
+ this is simply a copy of tcl8.cxx, which has been renamed
+ * ver002
+ all non essential code commented out, program now does virtually nothing
+ it prints to stderr the list of functions to wrap, but does not create
+ the XXX_wrap.c file
+ * ver003
+ added back top(), still prints the list of fns to stderr
+ but now creates a rather empty XXX_wrap.c with some basic boilerplate code
+ * ver004
+ very basic version of functionWrapper()
+ also uncommented usage_string() to keep compiler happy
+ this will start producing proper looking code soon (I hope)
+ produced the wrapper code, but without any type conversion (in or out)
+ generates a few warning because of no wrappering
+ does not generate SWIG_init()
+ reason for this is that lua.swg is empty
+ we will need to add code into this to make it work
+ * ver005/6
+ massive rework, basing work on the pike module instead of tcl
+ (pike module it only 1/3 of the size)(though not as complete)
+ * ver007
+ added simple type checking
+ * ver008
+ INPUT, OUTPUT, INOUT typemaps handled (though not all types yet)
+ * ver009
+ class support: ok for basic types, but methods still TDB
+ (code is VERY messed up & needs to be cleaned)
+ * ver010
+ Added support for embedded Lua. Try swig -lua -help for more information
+*/
+
+#include "swigmod.h"
+#include "cparse.h"
+
+/**** Diagnostics:
+ With the #define REPORT(), you can change the amount of diagnostics given
+ This helps me search the parse tree & figure out what is going on inside SWIG
+ (because it's not clear or documented)
+*/
+#define REPORT(T,D) // no info:
+//#define REPORT(T,D) {Printf(stdout,T"\n");} // only title
+//#define REPORT(T,D) {Printf(stdout,T" %p\n",n);} // title & pointer
+//#define REPORT(T,D) {Printf(stdout,T"\n");display_mapping(D);} // the works
+//#define REPORT(T,D) {Printf(stdout,T"\n");if(D)Swig_print_node(D);} // the works
+
+void display_mapping(DOH *d) {
+ if (d == 0 || !DohIsMapping(d))
+ return;
+ for (Iterator it = First(d); it.item; it = Next(it)) {
+ if (DohIsString(it.item))
+ Printf(stdout, " %s = %s\n", it.key, it.item);
+ else if (DohIsMapping(it.item))
+ Printf(stdout, " %s = <mapping>\n", it.key);
+ else if (DohIsSequence(it.item))
+ Printf(stdout, " %s = <sequence>\n", it.key);
+ else
+ Printf(stdout, " %s = <unknown>\n", it.key);
+ }
+}
+
+extern "C"
+{
+ static int compareByLen(const DOH *f, const DOH *s) {
+ return Len(s) - Len(f);
+ }
+}
+
+
+/* NEW LANGUAGE NOTE:***********************************************
+ most of the default options are handled by SWIG
+ you can add new ones here
+ (though for now I have not bothered)
+NEW LANGUAGE NOTE:END ************************************************/
+static const char *usage = "\
+Lua Options (available with -lua)\n\
+ -elua - Generates LTR compatible wrappers for smaller devices running elua\n\
+ -eluac - LTR compatible wrappers in \"crass compress\" mode for elua\n\
+ -elua-emulate - Emulates behaviour of eLua. Useful only for testing.\n\
+ Incompatible with -elua/-eluac options.\n\
+ -nomoduleglobal - Do not register the module name as a global variable \n\
+ but return the module table from calls to require.\n\
+ -no-old-metatable-bindings\n\
+ - Disable support for old-style bindings name generation, some\n\
+ old-style members scheme etc.\n\
+ -squash-bases - Squashes symbols from all inheritance tree of a given class\n\
+ into itself. Emulates pre-SWIG3.0 inheritance. Insignificantly\n\
+ speeds things up, but increases memory consumption.\n\
+\n";
+
+static int nomoduleglobal = 0;
+static int elua_ltr = 0;
+static int eluac_ltr = 0;
+static int elua_emulate = 0;
+static int squash_bases = 0;
+/* The new metatable bindings were introduced in SWIG 3.0.0.
+ * old_metatable_bindings in v2:
+ * 1. static methods will be put into the scope their respective class
+ * belongs to as well as into the class scope itself. (only for classes without %nspace given)
+ * 2. The layout in elua mode is somewhat different
+ */
+static int old_metatable_bindings = 1;
+static int old_compatible_names = 1; // This flag can temporarily disable backward compatible names generation if old_metatable_bindings is enabled
+
+/* NEW LANGUAGE NOTE:***********************************************
+ To add a new language, you need to derive your class from
+ Language and the overload various virtual functions
+ (more on this as I figure it out)
+NEW LANGUAGE NOTE:END ************************************************/
+
+class LUA:public Language {
+private:
+
+ File *f_begin;
+ File *f_runtime;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_initbeforefunc;
+ String *s_luacode; // luacode to be called during init
+ String *module; //name of the module
+
+ // Parameters for current class. NIL if not parsing class
+ int have_constructor;
+ int have_destructor;
+ String *destructor_action;
+ // This variable holds the name of the current class in Lua. Usually it is
+ // the same as C++ class name, but rename directives can change it.
+ String *proxy_class_name;
+ // This is a so called fully qualified symname - the above proxy class name
+ // prepended with class namespace. If class Lua name is the same as class C++ name,
+ // then it is basically C++ fully qualified name with colons replaced with dots.
+ String *full_proxy_class_name;
+ // All static methods and/or variables are treated as if they were in the
+ // special C++ namespace $(classname).SwigStatic. This is internal mechanism only
+ // and is not visible to user in any manner. This variable holds the name
+ // of such pseudo-namespace a.k.a the result of above expression evaluation
+ String *class_static_nspace;
+ // This variable holds the name of generated C function that acts as a constructor
+ // for the currently parsed class.
+ String *constructor_name;
+
+ // Many wrappers forward calls to each other, for example staticmembervariableHandler
+ // forwards calls to variableHandler, which, in turn, makes to call to functionWrapper.
+ // In order to access information about whether it is a static member of class or just
+ // a plain old variable, the current array is kept and used as a 'log' of the call stack.
+ enum TState {
+ NO_CPP,
+ VARIABLE,
+ GLOBAL_FUNC,
+ GLOBAL_VAR,
+ MEMBER_FUNC,
+ CONSTRUCTOR,
+ DESTRUCTOR,
+ MEMBER_VAR,
+ STATIC_FUNC,
+ STATIC_VAR,
+ STATIC_CONST, // enums and things like static const int x = 5;
+ ENUM_CONST, // This is only needed for backward compatibility in C mode
+
+ STATES_COUNT
+ };
+ bool current[STATES_COUNT];
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * LUA()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+
+ LUA():
+ f_begin(0),
+ f_runtime(0),
+ f_header(0),
+ f_wrappers(0),
+ f_init(0),
+ f_initbeforefunc(0),
+ s_luacode(0),
+ module(0),
+ have_constructor(0),
+ have_destructor(0),
+ destructor_action(0),
+ proxy_class_name(0),
+ full_proxy_class_name(0),
+ class_static_nspace(0),
+ constructor_name(0) {
+ for (int i = 0; i < STATES_COUNT; i++)
+ current[i] = false;
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is called to initialise the system & read any command line args
+ most of this is boilerplate code, except the command line args
+ which depends upon what args your code supports
+ NEW LANGUAGE NOTE:END *********************************************** */
+
+ /* ---------------------------------------------------------------------
+ * main()
+ *
+ * Parse command line options and initializes variables.
+ * --------------------------------------------------------------------- */
+
+ virtual void main(int argc, char *argv[]) {
+
+ /* Set location of SWIG library */
+ SWIG_library_directory("lua");
+
+ /* Look for certain command line options */
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) { // usage flags
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-nomoduleglobal") == 0) {
+ nomoduleglobal = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-elua") == 0) {
+ elua_ltr = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-eluac") == 0) {
+ eluac_ltr = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-no-old-metatable-bindings") == 0) {
+ Swig_mark_arg(i);
+ old_metatable_bindings = 0;
+ } else if (strcmp(argv[i], "-squash-bases") == 0) {
+ Swig_mark_arg(i);
+ squash_bases = 1;
+ } else if (strcmp(argv[i], "-elua-emulate") == 0) {
+ Swig_mark_arg(i);
+ elua_emulate = 1;
+ }
+ }
+ }
+
+ if (elua_emulate && (eluac_ltr || elua_ltr )) {
+ Printf(stderr, "Cannot have -elua-emulate with either -eluac or -elua\n");
+ Swig_arg_error();
+ }
+
+ // Set elua_ltr if elua_emulate is requested
+ if(elua_emulate)
+ elua_ltr = 1;
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is the boilerplate code, setting a few #defines
+ and which lib directory to use
+ the SWIG_library_directory() is also boilerplate code
+ but it always seems to be the first line of code
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGLUA 1", 0);
+
+ /* Set language-specific configuration file */
+ SWIG_config_file("lua.swg");
+
+ /* Enable overloaded methods support */
+ allow_overloading();
+ }
+
+
+
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ After calling main, SWIG parses the code to wrap (I believe)
+ then calls top()
+ in this is more boilerplate code to set everything up
+ and a call to Language::top()
+ which begins the code generations by calling the member fns
+ after all that is more boilerplate code to close all down
+ (overall there is virtually nothing here that needs to be edited
+ just use as is)
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+ /* Get the module name */
+ module = Getattr(n, "name");
+
+ /* Get the output file name */
+ String *outfile = Getattr(n, "outfile");
+
+ /* Open the output file */
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_initbeforefunc = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
+
+
+ s_luacode = NewString("");
+ Swig_register_filebyname("luacode", s_luacode);
+
+ current[NO_CPP] = true;
+
+ /* Standard stuff for the SWIG runtime section */
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "LUA");
+
+ emitLuaFlavor(f_runtime);
+
+ if (nomoduleglobal) {
+ Printf(f_runtime, "#define SWIG_LUA_NO_MODULE_GLOBAL\n");
+ } else {
+ Printf(f_runtime, "#define SWIG_LUA_MODULE_GLOBAL\n");
+ }
+ if (squash_bases)
+ Printf(f_runtime, "#define SWIG_LUA_SQUASH_BASES\n");
+
+ // if (NoInclude) {
+ // Printf(f_runtime, "#define SWIG_NOINCLUDE\n");
+ // }
+
+ Printf(f_runtime, "\n");
+
+ //String *init_name = NewStringf("%(title)s_Init", module);
+ //Printf(f_header, "#define SWIG_init %s\n", init_name);
+ //Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+ /* SWIG_import is a special function name for importing within Lua5.1 */
+ //Printf(f_header, "#define SWIG_import luaopen_%s\n\n", module);
+ Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+ Printf(f_header, "#define SWIG_init luaopen_%s\n", module);
+ Printf(f_header, "#define SWIG_init_user luaopen_%s_user\n\n", module);
+ Printf(f_header, "#define SWIG_LUACODE luaopen_%s_luacode\n", module);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ /* %init code inclusion, effectively in the SWIG_init function */
+ Printf(f_init, "void SWIG_init_user(lua_State* L)\n{\n");
+ Language::top(n);
+ Printf(f_init, "/* exec Lua code if applicable */\nSWIG_Lua_dostring(L,SWIG_LUACODE);\n");
+ Printf(f_init, "}\n");
+
+ // Done. Close up the module & write to the wrappers
+ closeNamespaces(f_wrappers);
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ this basically combines several of the strings together
+ and then writes it all to a file
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_wrappers, f_begin);
+ Dump(f_initbeforefunc, f_begin);
+ /* for the Lua code it needs to be properly escaped to be added into the C/C++ code */
+ escapeCode(s_luacode);
+ Printf(f_begin, "const char* SWIG_LUACODE=\n \"%s\";\n\n", s_luacode);
+ Wrapper_pretty_print(f_init, f_begin);
+ /* Close all of the files */
+ Delete(s_luacode);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_initbeforefunc);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ /* Done */
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * cDeclaration()
+ * It copies sym:name to lua:name to preserve its original value
+ * ------------------------------------------------------------ */
+
+ virtual int cDeclaration(Node *n) {
+ // class 'Language' is messing with symname in a really heavy way.
+ // Although documentation states that sym:name is a name in
+ // the target language space, it is not true. sym:name and
+ // its derivatives are used in various places, including
+ // behind-the-scene C code generation. The best way is not to
+ // touch it at all.
+ // But we need to know what was the name of function/variable
+ // etc that user desired, that's why we store correct symname
+ // as lua:name
+ String *symname = Getattr(n, "sym:name");
+ if (symname)
+ Setattr(n, "lua:name", symname);
+ return Language::cDeclaration(n);
+ }
+ virtual int constructorDeclaration(Node *n) {
+ Setattr(n, "lua:name", Getattr(n, "sym:name"));
+ return Language::constructorDeclaration(n);
+ }
+ virtual int destructorDeclaration(Node *n) {
+ Setattr(n, "lua:name", Getattr(n, "sym:name"));
+ return Language::destructorDeclaration(n);
+ }
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is it!
+ you get this one right, and most of your work is done
+ but it's going to take some file to get it working right
+ quite a bit of this is generally boilerplate code
+ (or stuff I don't understand)
+ that which matters will have extra added comments
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Create a function declaration and register it with the interpreter.
+ * --------------------------------------------------------------------- */
+
+ /* -----------------------------------------------------------------------
+ * registerMethod()
+ *
+ * Determines wrap name of a method, its scope etc and calls
+ * registerMethod overload with correct arguments
+ * Overloaded variant adds method to the "methods" array of specified lua scope/class
+ * ---------------------------------------------------------------------- */
+
+ void registerMethod(Node *n, bool overwrite = false, String *overwriteLuaScope = 0) {
+ String *symname = Getattr(n, "sym:name");
+ assert(symname);
+
+ if (Getattr(n, "sym:nextSibling"))
+ return;
+
+ // Lua scope. It is not symbol NSpace, it is the actual key to retrieve getCArraysHash.
+ String *luaScope = luaCurrentSymbolNSpace();
+ if (overwrite)
+ luaScope = overwriteLuaScope;
+
+ String *wrapname = 0;
+ String *mrename;
+ if (current[NO_CPP] || !getCurrentClass()) {
+ mrename = symname;
+ } else {
+ assert(!current[NO_CPP]);
+ if (current[STATIC_FUNC] || current[MEMBER_FUNC]) {
+ mrename = Swig_name_member(getNSpace(), getClassPrefix(), symname);
+ } else {
+ mrename = symname;
+ }
+ }
+ wrapname = Swig_name_wrapper(mrename);
+ registerMethod(n, wrapname, luaScope);
+ }
+
+ /* -----------------------------------------------------------------------
+ * registerMethod()
+ *
+ * Add method to the "methods" C array of given namespace/class
+ * ---------------------------------------------------------------------- */
+
+ void registerMethod(Node *n, String* wname, String *luaScope) {
+ assert(n);
+ Hash *nspaceHash = getCArraysHash(luaScope);
+ String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
+ String *lua_name = Getattr(n, "lua:name");
+ if (elua_ltr || eluac_ltr)
+ Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL);
+ else
+ Printv(s_ns_methods_tab, tab4, "{ \"", lua_name, "\", ", wname, "},\n", NIL);
+ // Add to the metatable if method starts with '__'
+ const char * tn = Char(lua_name);
+ if (tn[0]=='_' && tn[1] == '_' && !eluac_ltr) {
+ String *metatable_tab = Getattr(nspaceHash, "metatable");
+ assert(metatable_tab);
+ if (elua_ltr)
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"", lua_name, "\")", ", LFUNCVAL(", wname, ")", "},\n", NIL);
+ else
+ Printv(metatable_tab, tab4, "{ \"", lua_name, "\", ", wname, "},\n", NIL);
+ }
+ }
+
+ virtual int functionWrapper(Node *n) {
+ REPORT("functionWrapper", n);
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *lua_name = Getattr(n, "lua:name");
+ assert(lua_name);
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+ String *tm;
+ int i;
+ //Printf(stdout,"functionWrapper %s %s %d\n",name,iname,current);
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!luaAddSymbol(lua_name, n)) {
+ return SWIG_ERROR;
+ }
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ the wrapper object holds all the wrapper code
+ we need to add a couple of local variables
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Wrapper *f = NewWrapper();
+ Wrapper_add_local(f, "SWIG_arg", "int SWIG_arg = 0");
+
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ if (current[CONSTRUCTOR]) {
+ if (constructor_name != 0)
+ Delete(constructor_name);
+ constructor_name = Copy(wname);
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ the format of a lua fn is:
+ static int wrap_XXX(lua_State* L){...}
+ this line adds this into the wrapper code
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
+ // SWIG_fail in lua leads to a call to lua_error() which calls longjmp()
+ // which means the destructors of any live function-local C++ objects won't
+ // get run. To avoid this happening, we wrap almost everything in the
+ // function in a block, and end that right before lua_error() at which
+ // point those destructors will get called.
+ if (CPlusPlus) Append(f->def, "\n{");
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ this prints the list of args, eg for a C fn
+ int gcd(int x,int y);
+ it will print
+ int arg1;
+ int arg2;
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Write code to extract function parameters. */
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of required and total arguments */
+ int num_arguments = emit_num_arguments(l);
+ int num_required = emit_num_required(l);
+ int varargs = emit_isvarargs(l);
+
+ // Check if we have to ignore arguments that are passed by LUA.
+ // Needed for unary minus, where lua passes two arguments and
+ // we have to ignore the second.
+
+ int args_to_ignore = 0;
+ if (Getattr(n, "lua:ignore_args")) {
+ args_to_ignore = GetInt(n, "lua:ignore_args");
+ }
+
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ from here on in, it gets rather hairy
+ this is the code to convert from the scripting language to C/C++
+ some of the stuff will refer to the typemaps code written in your swig file
+ (lua.swg), and some is done in the code here
+ I suppose you could do all the conversion in C, but it would be a nightmare to do
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Generate code for argument marshalling */
+ // String *description = NewString("");
+ /* NEW LANGUAGE NOTE:***********************************************
+ argument_check is a new feature I added to check types of arguments:
+ eg for int gcd(int,int)
+ I want to check that arg1 & arg2 really are integers
+ NEW LANGUAGE NOTE:END *********************************************** */
+ String *argument_check = NewString("");
+ String *argument_parse = NewString("");
+ String *checkfn = NULL;
+ char source[64];
+ Printf(argument_check, "SWIG_check_num_args(\"%s\",%d,%d)\n", Swig_name_str(n), num_required + args_to_ignore, num_arguments + args_to_ignore);
+
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ /* Look for an input typemap */
+ sprintf(source, "%d", i + 1);
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ /* NEW LANGUAGE NOTE:***********************************************
+ look for a 'checkfn' typemap
+ this an additional parameter added to the in typemap
+ if found the type will be tested for
+ this will result in code either in the
+ argument_check or argument_parse string
+ NEW LANGUAGE NOTE:END *********************************************** */
+ if ((checkfn = Getattr(p, "tmap:in:checkfn"))) {
+ if (i < num_required) {
+ Printf(argument_check, "if(!%s(L,%s))", checkfn, source);
+ } else {
+ Printf(argument_check, "if(lua_gettop(L)>=%s && !%s(L,%s))", source, checkfn, source);
+ }
+ Printf(argument_check, " SWIG_fail_arg(\"%s\",%s,\"%s\");\n", Swig_name_str(n), source, SwigType_str(pt, 0));
+ }
+ /* NEW LANGUAGE NOTE:***********************************************
+ lua states the number of arguments passed to a function using the fn
+ lua_gettop()
+ we can use this to deal with default arguments
+ NEW LANGUAGE NOTE:END *********************************************** */
+ if (i < num_required) {
+ Printf(argument_parse, "%s\n", tm);
+ } else {
+ Printf(argument_parse, "if(lua_gettop(L)>=%s){%s}\n", source, tm);
+ }
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ /* NEW LANGUAGE NOTE:***********************************************
+ // why is this code not called when I don't have a typemap?
+ // instead of giving a warning, no code is generated
+ NEW LANGUAGE NOTE:END *********************************************** */
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ break;
+ }
+ }
+
+ // add all argcheck code
+ Printv(f->code, argument_check, argument_parse, NIL);
+
+ /* Check for trailing varargs */
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", "varargs");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ String *cleanup = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ String *outarg = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ // // managing the number of returning variables
+ // if (numoutputs=Getattr(p,"tmap:argout:numoutputs")){
+ // int i=GetInt(p,"tmap:argout:numoutputs");
+ // printf("got argout:numoutputs of %d\n",i);
+ // returnval+=GetInt(p,"tmap:argout:numoutputs");
+ // }
+ // else returnval++;
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Remember C name of the wrapping function
+ Setattr(n, "wrap:name", wname);
+
+ /* Emit the function call */
+ String *actioncode = emit_action(n);
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ FIXME:
+ returns 1 if there is a void return type
+ this is because there is a typemap for void
+ NEW LANGUAGE NOTE:END *********************************************** */
+ // Return value if necessary
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ // managing the number of returning variables
+ // if (numoutputs=Getattr(tm,"numoutputs")){
+ // int i=GetInt(tm,"numoutputs");
+ // printf("return numoutputs %d\n",i);
+ // returnval+=GetInt(tm,"numoutputs");
+ // }
+ // else returnval++;
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "1");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printf(f->code, "%s\n", tm);
+ // returnval++;
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), name);
+ }
+ emit_return_variable(n, returntype, f);
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+
+
+ /* Close the function */
+ Printv(f->code, "return SWIG_arg;\n", NIL);
+ // add the failure cleanup code:
+ Printv(f->code, "\nfail: SWIGUNUSED;\n", "$cleanup", NIL);
+ if (CPlusPlus) Append(f->code, "}\n");
+ Printv(f->code, "lua_error(L);\n", NIL);
+ // lua_error() calls longjmp() but we need a dummy return to avoid compiler
+ // warnings.
+ Printv(f->code, "return 0;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+ Replaceall(f->code, "$result", Swig_cresult_name());
+
+ /* Dump the function out */
+ /* in Lua we will not emit the destructor as a wrapper function,
+ Lua will automatically call the destructor when the object is free'd
+ However: you cannot just skip this function as it will not emit
+ any custom destructor (using %extend), as you need to call emit_action()
+ Therefore we go though the whole function,
+ but do not write the code into the wrapper
+ */
+ if (!current[DESTRUCTOR]) {
+ Wrapper_print(f, f_wrappers);
+ }
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ register the function in SWIG
+ different language mappings seem to use different ideas
+ NEW LANGUAGE NOTE:END *********************************************** */
+ /* Now register the function with the interpreter. */
+ int result = SWIG_OK;
+ if (Getattr(n, "sym:overloaded")) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ result = dispatchFunction(n);
+ }
+ }
+
+ Delete(argument_check);
+ Delete(argument_parse);
+
+ Delete(cleanup);
+ Delete(outarg);
+ // Delete(description);
+ DelWrapper(f);
+
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ *
+ * Emit overloading dispatch function
+ * ------------------------------------------------------------ */
+
+ /* NEW LANGUAGE NOTE:***********************************************
+ This is an extra function used for overloading of functions
+ it checks the args & then calls the relevant fn
+ most of the real work in again typemaps:
+ look for %typecheck(SWIG_TYPECHECK_*) in the .swg file
+ NEW LANGUAGE NOTE:END *********************************************** */
+ int dispatchFunction(Node *n) {
+ //REPORT("dispatchFunction", n);
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewString("");
+ String *dispatch = Swig_overload_dispatch(n, "return %s(L);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *lua_name = Getattr(n, "lua:name");
+ assert(lua_name);
+ String *wname = Swig_name_wrapper(symname);
+
+ //Printf(stdout,"Swig_overload_dispatch %s %s '%s' %d\n",symname,wname,dispatch,maxargs);
+
+ if (!luaAddSymbol(lua_name, n)) {
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ return SWIG_ERROR;
+ }
+
+ Printv(f->def, "static int ", wname, "(lua_State* L) {", NIL);
+ Wrapper_add_local(f, "argc", "int argc");
+ Printf(tmp, "int argv[%d]={1", maxargs + 1);
+ for (int i = 1; i <= maxargs; i++) {
+ Printf(tmp, ",%d", i + 1);
+ }
+ Printf(tmp, "}");
+ Wrapper_add_local(f, "argv", tmp);
+ Printf(f->code, "argc = lua_gettop(L);\n");
+
+ Replaceall(dispatch, "$args", "self,args");
+ Printv(f->code, dispatch, "\n", NIL);
+
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(f->code, "SWIG_Lua_pusherrstring(L,\"Wrong arguments for overloaded function '%s'\\n\"\n"
+ "\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
+ Delete(protoTypes);
+
+ Printf(f->code, "lua_error(L);return 0;\n");
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+
+ // Remember C name of the wrapping function
+ Setattr(n, "wrap:name", wname);
+
+ if (current[CONSTRUCTOR]) {
+ if (constructor_name != 0)
+ Delete(constructor_name);
+ constructor_name = Copy(wname);
+ }
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * Add variable to "attributes" C arrays of given namespace or class.
+ * Input is node. Based on the state of "current" array it determines
+ * the name of the getter function, setter function etc and calls
+ * registerVariable overload with necessary params.
+ * Lua scope could be overwritten. (Used only for backward compatibility)
+ * ------------------------------------------------------------ */
+
+ void registerVariable(Node *n, bool overwrite = false, String *overwriteLuaScope = 0) {
+ int assignable = !is_immutable(n);
+ String *symname = Getattr(n, "sym:name");
+ assert(symname);
+
+ // Lua scope. It is not symbol NSpace, it is the actual key to retrieve getCArraysHash.
+ String *luaScope = luaCurrentSymbolNSpace();
+ if (overwrite)
+ luaScope = overwriteLuaScope;
+
+ // Getter and setter
+ String *getName = 0;
+ String *setName = 0;
+ String *mrename = 0;
+ if (current[NO_CPP] || !getCurrentClass()) {
+ // Global variable
+ getName = Swig_name_get(getNSpace(), symname);
+ if (assignable)
+ setName = Swig_name_set(getNSpace(), symname);
+ } else {
+ assert(!current[NO_CPP]);
+ if (current[STATIC_VAR] ) {
+ mrename = Swig_name_member(getNSpace(), getClassPrefix(), symname);
+ getName = Swig_name_get(0, mrename);
+ if (assignable)
+ setName = Swig_name_set(0, mrename);
+ } else if (current[MEMBER_VAR]) {
+ mrename = Swig_name_member(0, getClassPrefix(), symname);
+ getName = Swig_name_get(getNSpace(), mrename);
+ if (assignable)
+ setName = Swig_name_set(getNSpace(), mrename);
+ } else {
+ assert(false);
+ }
+ }
+
+ getName = Swig_name_wrapper(getName);
+ if (setName)
+ setName = Swig_name_wrapper(setName);
+ registerVariable(luaScope, n, getName, setName);
+ }
+
+ /* ------------------------------------------------------------
+ * registerVariable()
+ *
+ * Add variable to the "attributes" (or "get"/"set" in
+ * case of elua_ltr) C arrays of given namespace or class
+ * ------------------------------------------------------------ */
+
+ void registerVariable(String *lua_nspace_or_class_name, Node *n, String *getName, String *setName) {
+ String *unassignable = NewString("SWIG_Lua_set_immutable");
+ if (setName == 0 || GetFlag(n, "feature:immutable")) {
+ setName = unassignable;
+ }
+ Hash *nspaceHash = getCArraysHash(lua_nspace_or_class_name);
+ String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
+ String *s_ns_var_tab = Getattr(nspaceHash, "attributes");
+ String *lua_name = Getattr(n, "lua:name");
+ if (elua_ltr) {
+ String *s_ns_dot_get = Getattr(nspaceHash, "get");
+ String *s_ns_dot_set = Getattr(nspaceHash, "set");
+ Printf(s_ns_dot_get, "%s{LSTRKEY(\"%s\"), LFUNCVAL(%s)},\n", tab4, lua_name, getName);
+ Printf(s_ns_dot_set, "%s{LSTRKEY(\"%s\"), LFUNCVAL(%s)},\n", tab4, lua_name, setName);
+ } else if (eluac_ltr) {
+ Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "_get", "\")", ", LFUNCVAL(", getName, ")", "},\n", NIL);
+ Printv(s_ns_methods_tab, tab4, "{LSTRKEY(\"", lua_name, "_set", "\")", ", LFUNCVAL(", setName, ")", "},\n", NIL);
+ } else {
+ Printf(s_ns_var_tab, "%s{ \"%s\", %s, %s },\n", tab4, lua_name, getName, setName);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ /* NEW LANGUAGE NOTE:***********************************************
+ Language::variableWrapper(n) will generate two wrapper fns
+ Foo_get & Foo_set by calling functionWrapper()
+ so we will just add these into the variable lists
+ ideally we should not have registered these as functions,
+ only WRT this variable will look into this later.
+ NEW LANGUAGE NOTE:END *********************************************** */
+ // REPORT("variableWrapper", n);
+ String *lua_name = Getattr(n, "lua:name");
+ assert(lua_name);
+ (void)lua_name;
+ current[VARIABLE] = true;
+ // let SWIG generate the wrappers
+ int result = Language::variableWrapper(n);
+
+ // It is impossible to use registerVariable, because sym:name of the Node is currently
+ // in an undefined state - the callees of this function may have modified it.
+ // registerVariable should be used from respective callees.*
+ current[VARIABLE] = false;
+ return result;
+ }
+
+
+ /* ------------------------------------------------------------
+ * Add constant to appropriate C array. constantRecord is an array record.
+ * Actually, in current implementation it is resolved consttab typemap
+ * ------------------------------------------------------------ */
+
+ void registerConstant(String *nspace, String *constantRecord) {
+ Hash *nspaceHash = getCArraysHash(nspace);
+ String *s_const_tab = 0;
+ if (eluac_ltr || elua_ltr)
+ // In elua everything goes to "methods" tab
+ s_const_tab = Getattr(nspaceHash, "methods");
+ else
+ s_const_tab = Getattr(nspaceHash, "constants");
+
+ assert(s_const_tab);
+ Printf(s_const_tab, " %s,\n", constantRecord);
+
+ if ((eluac_ltr || elua_ltr) && old_metatable_bindings) {
+ s_const_tab = Getattr(nspaceHash, "constants");
+ assert(s_const_tab);
+ Printf(s_const_tab, " %s,\n", constantRecord);
+ }
+
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ REPORT("constantWrapper", n);
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *lua_name = Getattr(n, "lua:name");
+ if (lua_name == 0)
+ lua_name = iname;
+ String *nsname = Copy(iname);
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *tm;
+ String *lua_name_v2 = 0;
+ String *tm_v2 = 0;
+ String *iname_v2 = 0;
+ Node *n_v2 = 0;
+
+ if (!luaAddSymbol(lua_name, n))
+ return SWIG_ERROR;
+
+ Swig_save("lua_constantMember", n, "sym:name", NIL);
+ Setattr(n, "sym:name", lua_name);
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ registerConstant(luaCurrentSymbolNSpace(), tm);
+ } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Delete(nsname);
+ nsname = 0;
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ Swig_restore(n);
+ return SWIG_NOWRAP;
+ }
+
+ bool make_v2_compatible = old_metatable_bindings && getCurrentClass() && old_compatible_names;
+
+ if (make_v2_compatible) {
+ // Don't do anything for enums in C mode - they are already
+ // wrapped correctly
+ if (CPlusPlus || !current[ENUM_CONST]) {
+ lua_name_v2 = Swig_name_member(0, proxy_class_name, lua_name);
+ iname_v2 = Swig_name_member(0, proxy_class_name, iname);
+ n_v2 = Copy(n);
+ if (!luaAddSymbol(iname_v2, n, getNSpace())) {
+ Swig_restore(n);
+ return SWIG_ERROR;
+ }
+
+ Setattr(n_v2, "sym:name", lua_name_v2);
+ tm_v2 = Swig_typemap_lookup("consttab", n_v2, name, 0);
+ if (tm_v2) {
+ Replaceall(tm_v2, "$value", value);
+ Replaceall(tm_v2, "$nsname", nsname);
+ registerConstant(getNSpace(), tm_v2);
+ } else {
+ tm_v2 = Swig_typemap_lookup("constcode", n_v2, name, 0);
+ if (!tm_v2) {
+ // This can't be.
+ assert(false);
+ Swig_restore(n);
+ return SWIG_ERROR;
+ }
+ Replaceall(tm_v2, "$value", value);
+ Replaceall(tm_v2, "$nsname", nsname);
+ Printf(f_init, "%s\n", tm_v2);
+ }
+ Delete(n_v2);
+ }
+ }
+
+ Swig_restore(n);
+ Delete(nsname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ // REPORT("nativeWrapper", n);
+ String *symname = Getattr(n, "sym:name");
+ String *wrapname = Getattr(n, "wrap:name");
+ if (!luaAddSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ Hash *nspaceHash = getCArraysHash(getNSpace());
+ String *s_ns_methods_tab = Getattr(nspaceHash, "methods");
+ Printv(s_ns_methods_tab, tab4, "{ \"", symname, "\",", wrapname, "},\n", NIL);
+ // return Language::nativeWrapper(n); // this does nothing...
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ current[STATIC_CONST] = true;
+ current[ENUM_CONST] = true;
+ // There is some slightly specific behaviour with enums. Basically,
+ // their NSpace may be tracked separately. The code below tries to work around
+ // this issue to some degree.
+ // The idea is the same as in classHandler - to drop old names generation if
+ // enum is in class in namespace.
+ const int old_compatible_names_saved = old_compatible_names;
+ if (getNSpace() || ( Getattr(n, "sym:nspace") != 0 && Len(Getattr(n, "sym:nspace")) > 0 ) ) {
+ old_compatible_names = 0;
+ }
+ int result = Language::enumDeclaration(n);
+ current[STATIC_CONST] = false;
+ current[ENUM_CONST] = false;
+ old_compatible_names = old_compatible_names_saved;
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", "*sym:name", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ String *tmpValue;
+ Node *parent = parentNode(n);
+
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ Setattr(n, "value", tmpValue);
+
+ Setattr(n, "name", tmpValue); /* for wrapping of enums in a namespace when emit_action is used */
+
+ if (GetFlag(parent, "scopedenum")) {
+ symname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ int result = constantWrapper(n);
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * Helper function that adds record to appropriate C arrays
+ * ------------------------------------------------------------ */
+
+ void registerClass(String *scope, String *wrap_class) {
+ assert(wrap_class);
+ Hash *nspaceHash = getCArraysHash(scope);
+ String *ns_classes = Getattr(nspaceHash, "classes");
+ Printv(ns_classes, "&", wrap_class, ",\n", NIL);
+ if (elua_ltr || eluac_ltr) {
+ String *ns_methods = Getattr(nspaceHash, "methods");
+ Hash *class_hash = getCArraysHash(class_static_nspace);
+ assert(class_hash);
+ String *cls_methods = Getattr(class_hash, "methods:name");
+ assert(cls_methods);
+ Printv(ns_methods, tab4, "{LSTRKEY(\"", proxy_class_name, "\")", ", LROVAL(", cls_methods, ")", "},\n", NIL);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ //REPORT("classHandler", n);
+
+ String *mangled_full_proxy_class_name = 0;
+ String *destructor_name = 0;
+ String *nspace = getNSpace();
+
+ constructor_name = 0;
+ have_constructor = 0;
+ have_destructor = 0;
+ destructor_action = 0;
+ assert(class_static_nspace == 0);
+ assert(full_proxy_class_name == 0);
+ assert(proxy_class_name == 0);
+
+ current[NO_CPP] = false;
+
+ proxy_class_name = Getattr(n, "sym:name");
+ // We have to enforce nspace here, because technically we are already
+ // inside class parsing (getCurrentClass != 0), but we should register
+ // class in its parent namespace
+ if (!luaAddSymbol(proxy_class_name, n, nspace))
+ return SWIG_ERROR;
+
+ if (nspace == 0)
+ full_proxy_class_name = NewStringf("%s", proxy_class_name);
+ else
+ full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
+
+ assert(full_proxy_class_name);
+ mangled_full_proxy_class_name = Swig_name_mangle_string(full_proxy_class_name);
+
+ SwigType *t = Copy(Getattr(n, "name"));
+ SwigType *fr_t = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
+ SwigType *t_tmp = 0;
+ t_tmp = SwigType_typedef_qualified(fr_t); // Temporary variable
+ Delete(fr_t);
+ fr_t = SwigType_strip_qualifiers(t_tmp);
+ String *mangled_fr_t = 0;
+ mangled_fr_t = SwigType_manglestr(fr_t);
+ // not sure exactly how this works,
+ // but tcl has a static hashtable of all classes emitted and then only emits code for them once.
+ // this fixes issues in test suites: template_default2 & template_specialization
+
+ // * if i understand correctly, this is a bug.
+ // * consider effect on template_specialization_defarg
+
+ static Hash *emitted = NewHash();
+ if (GetFlag(emitted, mangled_fr_t)) {
+ full_proxy_class_name = 0;
+ proxy_class_name = 0;
+ return SWIG_NOWRAP;
+ }
+ SetFlag(emitted, mangled_fr_t);
+
+ // We treat class T as both 'class' and 'namespace'. All static members, attributes
+ // and constants are considered part of namespace T, all members - part of the 'class'
+ // Now, here is a trick. Static methods, attributes and non-static methods and attributes
+ // are described with same structures - swig_lua_attribute/swig_lua_method. Instead of calling
+ // getCArraysHash(class name) to initialize things for static methods/attributes and then
+ // manually doing same initialization for non-static methods, we call getCArraysHash 2 times:
+ // 1) With name "class name" + "." + "SwigStatic" to initialize static things
+ // 2) With "class name" to initialize non-static things
+ Hash *instance_cls = getCArraysHash(full_proxy_class_name, false);
+ assert(instance_cls);
+ String *s_attr_tab_name = Getattr(instance_cls, "attributes:name");
+ String *s_methods_tab_name = Getattr(instance_cls, "methods:name");
+ SetFlag(instance_cls, "lua:no_namespaces");
+ SetFlag(instance_cls, "lua:no_classes");
+ SetFlag(instance_cls, "lua:class_instance");
+
+ /* There is no use for "constants", "classes" and "namespaces" arrays.
+ * All constants are considered part of static part of class.
+ */
+
+ class_static_nspace = NewStringf("%s%sSwigStatic", full_proxy_class_name, NSPACE_SEPARATOR);
+ Hash *static_cls = getCArraysHash(class_static_nspace, false);
+ assert(static_cls);
+ SetFlag(static_cls, "lua:no_namespaces");
+ SetFlag(static_cls, "lua:class_static");
+
+ // Notifying instance_cls and static_cls hashes about each other
+ Setattr(instance_cls, "lua:class_instance:static_hash", static_cls);
+ Setattr(static_cls, "lua:class_static:instance_hash", instance_cls);
+
+ const int old_compatible_names_saved = old_compatible_names;
+ // If class has %nspace enabled, then generation of backward compatible names
+ // should be disabled
+ if (getNSpace()) {
+ old_compatible_names = 0;
+ }
+
+ /* There is no use for "classes" and "namespaces" arrays. Subclasses are not supported
+ * by SWIG and namespaces couldn't be nested inside classes (C++ Standard)
+ */
+ // Generate normal wrappers
+ Language::classHandler(n);
+
+ old_compatible_names = old_compatible_names_saved;
+
+ SwigType_add_pointer(t);
+
+ // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
+ String *wrap_class_name = Swig_name_wrapper(NewStringf("class_%s", mangled_full_proxy_class_name));
+ String *wrap_class = NewStringf("&%s", wrap_class_name);
+ SwigType_remember_clientdata(t, wrap_class);
+
+ String *rt = Copy(getClassType());
+ SwigType_add_pointer(rt);
+
+ // Adding class to appropriate namespace
+ registerClass(nspace, wrap_class_name);
+ Hash *nspaceHash = getCArraysHash(nspace);
+
+ // Register the class structure with the type checker
+ // Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_full_proxy_class_name);
+
+ // emit a function to be called to delete the object
+ if (have_destructor) {
+ destructor_name = NewStringf("swig_delete_%s", mangled_full_proxy_class_name);
+ Printv(f_wrappers, "static void ", destructor_name, "(void *obj) {\n", NIL);
+ if (destructor_action) {
+ Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ Printv(f_wrappers, destructor_action, "\n", NIL);
+ } else {
+ if (CPlusPlus) {
+ Printv(f_wrappers, " delete (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ } else {
+ Printv(f_wrappers, " free((char *) obj);\n", NIL);
+ }
+ }
+ Printf(f_wrappers, "}\n");
+ }
+ // Wrap constructor wrapper into one more proxy function. It will be used as class namespace __call method, thus
+ // allowing both
+ // Module.ClassName.StaticMethod to access static method/variable/constant
+ // Module.ClassName() to create new object
+ if (have_constructor) {
+ assert(constructor_name);
+ String *constructor_proxy_name = NewStringf("_proxy_%s", constructor_name);
+ Printv(f_wrappers, "static int ", constructor_proxy_name, "(lua_State *L) {\n", NIL);
+ Printv(f_wrappers,
+ tab4, "assert(lua_istable(L,1));\n",
+ tab4, "lua_pushcfunction(L,", constructor_name, ");\n",
+ tab4, "assert(!lua_isnil(L,-1));\n",
+ tab4, "lua_replace(L,1); /* replace our table with real constructor */\n",
+ tab4, "lua_call(L,lua_gettop(L)-1,1);\n",
+ tab4, "return 1;\n}\n", NIL);
+ Delete(constructor_name);
+ constructor_name = constructor_proxy_name;
+ if (elua_ltr) {
+ String *static_cls_metatable_tab = Getattr(static_cls, "metatable");
+ assert(static_cls_metatable_tab);
+ Printf(static_cls_metatable_tab, " {LSTRKEY(\"__call\"), LFUNCVAL(%s)},\n", constructor_name);
+ } else if (eluac_ltr) {
+ String *ns_methods_tab = Getattr(nspaceHash, "methods");
+ assert(ns_methods_tab);
+ Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "new_", proxy_class_name, "\")", ", LFUNCVAL(", constructor_name, ")", "},\n", NIL);
+ }
+ }
+ if (have_destructor) {
+ if (eluac_ltr) {
+ String *ns_methods_tab = Getattr(nspaceHash, "methods");
+ assert(ns_methods_tab);
+ Printv(ns_methods_tab, tab4, "{LSTRKEY(\"", "free_", mangled_full_proxy_class_name, "\")", ", LFUNCVAL(", destructor_name, ")", "},\n", NIL);
+ }
+ }
+
+ closeCArraysHash(full_proxy_class_name, f_wrappers);
+ closeCArraysHash(class_static_nspace, f_wrappers);
+
+
+ // Handle inheritance
+ // note: with the idea of class hierarchies spread over multiple modules
+ // cf test-suite: imports.i
+ // it is not possible to just add the pointers to the base classes to the code
+ // (as sometimes these classes are not present)
+ // therefore we instead hold the name of the base class and a null pointer
+ // at runtime: we can query the swig type manager & see if the class exists
+ // if so, we can get the pointer to the base class & replace the null pointer
+ // if the type does not exist, then we cannot...
+ String *base_class = NewString("");
+ String *base_class_names = NewString("");
+
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
+ b = Next(b);
+ continue;
+ }
+ // stores a null pointer & the name
+ Printf(base_class, "0,");
+ Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
+
+ b = Next(b);
+ }
+ }
+ // First, print class static part
+ printCArraysDefinition(class_static_nspace, proxy_class_name, f_wrappers);
+
+ assert(mangled_full_proxy_class_name);
+ assert(base_class);
+ assert(base_class_names);
+ assert(proxy_class_name);
+ assert(full_proxy_class_name);
+
+ // Then print class instance part
+ Printv(f_wrappers, "static swig_lua_class *swig_", mangled_full_proxy_class_name, "_bases[] = {", base_class, "0};\n", NIL);
+ Delete(base_class);
+ Printv(f_wrappers, "static const char *swig_", mangled_full_proxy_class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Delete(base_class_names);
+
+ Printv(f_wrappers, "static swig_lua_class _wrap_class_", mangled_full_proxy_class_name, " = { \"", proxy_class_name, "\", \"", full_proxy_class_name, "\", &SWIGTYPE",
+ SwigType_manglestr(t), ",", NIL);
+
+ if (have_constructor) {
+ Printv(f_wrappers, constructor_name, NIL);
+ Delete(constructor_name);
+ constructor_name = 0;
+ } else {
+ Printf(f_wrappers, "0");
+ }
+
+ if (have_destructor) {
+ Printv(f_wrappers, ", ", destructor_name, NIL);
+ } else {
+ Printf(f_wrappers, ",0");
+ }
+ Printf(f_wrappers, ", %s, %s, &%s", s_methods_tab_name, s_attr_tab_name, Getattr(static_cls, "cname"));
+
+ if (!eluac_ltr) {
+ Printf(f_wrappers, ", %s", Getattr(instance_cls,"metatable:name"));
+ }
+ else
+ Printf(f_wrappers, ", 0");
+
+ Printf(f_wrappers, ", swig_%s_bases, swig_%s_base_names };\n\n", mangled_full_proxy_class_name, mangled_full_proxy_class_name);
+
+ current[NO_CPP] = true;
+ Delete(class_static_nspace);
+ class_static_nspace = 0;
+ Delete(mangled_full_proxy_class_name);
+ mangled_full_proxy_class_name = 0;
+ Delete(destructor_name);
+ destructor_name = 0;
+ Delete(full_proxy_class_name);
+ full_proxy_class_name = 0;
+ proxy_class_name = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *symname = GetChar(n, "sym:name");
+ //Printf(stdout,"memberfunctionHandler %s %s\n",name,iname);
+
+ // Special case unary minus: LUA passes two parameters for the
+ // wrapper function while we want only one. Tell our
+ // functionWrapper to ignore a parameter.
+
+ if (Cmp(symname, "__unm") == 0) {
+ //Printf(stdout, "unary minus: ignore one argument\n");
+ SetInt(n, "lua:ignore_args", 1);
+ }
+
+ current[MEMBER_FUNC] = true;
+ Language::memberfunctionHandler(n);
+
+ registerMethod(n);
+ current[MEMBER_FUNC] = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ // REPORT("membervariableHandler",n);
+ current[MEMBER_VAR] = true;
+ Language::membervariableHandler(n);
+ registerVariable(n);
+ current[MEMBER_VAR] = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ *
+ * Method for adding C++ member constructor
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ // REPORT("constructorHandler", n);
+ current[CONSTRUCTOR] = true;
+ Language::constructorHandler(n);
+ current[CONSTRUCTOR] = false;
+ //constructor_name = NewString(Getattr(n, "sym:name"));
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ REPORT("destructorHandler", n);
+ current[DESTRUCTOR] = true;
+ Language::destructorHandler(n);
+ current[DESTRUCTOR] = false;
+ have_destructor = 1;
+ destructor_action = Getattr(n, "wrap:action");
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * globalfunctionHandler()
+ *
+ * It can be called:
+ * 1. Usual C/C++ global function.
+ * 2. During class parsing for functions declared/defined as friend
+ * 3. During class parsing from staticmemberfunctionHandler
+ * ---------------------------------------------------------------------- */
+
+ virtual int globalfunctionHandler(Node *n) {
+ bool oldVal = current[NO_CPP];
+ if (!current[STATIC_FUNC]) // If static function, don't switch to NO_CPP
+ current[NO_CPP] = true;
+ const int result = Language::globalfunctionHandler(n);
+
+ if (!current[STATIC_FUNC]) // Register only if not called from static function handler
+ registerMethod(n);
+ current[NO_CPP] = oldVal;
+ return result;
+ }
+
+ /* ----------------------------------------------------------------------
+ * globalvariableHandler()
+ *
+ * Sets "current" array correctly
+ * ---------------------------------------------------------------------- */
+
+ virtual int globalvariableHandler(Node *n) {
+ bool oldVal = current[NO_CPP];
+ current[GLOBAL_VAR] = true;
+ current[NO_CPP] = true;
+
+ const int result = Language::globalvariableHandler(n);
+ registerVariable(n);
+
+ current[GLOBAL_VAR] = false;
+ current[NO_CPP] = oldVal;
+ return result;
+ }
+
+
+ /* -----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Wrap a static C++ function
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ REPORT("staticmemberfunctionHandler", n);
+ current[STATIC_FUNC] = true;
+
+ const int result = Language::staticmemberfunctionHandler(n);
+ registerMethod(n);
+
+ if (old_metatable_bindings && result == SWIG_OK && old_compatible_names) {
+ Swig_require("lua_staticmemberfunctionHandler", n, "*lua:name", NIL);
+ String *lua_name = Getattr(n, "lua:name");
+ // Although this function uses Swig_name_member, it actually generates the Lua name,
+ // not the C++ name. This is because an earlier version used such a scheme for static function
+ // name generation and we have to maintain backward compatibility.
+ String *compat_name = Swig_name_member(0, proxy_class_name, lua_name);
+ Setattr(n, "lua:name", compat_name);
+ registerMethod(n, true, getNSpace());
+ Delete(compat_name);
+ Swig_restore(n);
+ }
+
+ current[STATIC_FUNC] = false;;
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ *
+ * Create a C++ constant
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ REPORT("memberconstantHandler", n);
+ int result = Language::memberconstantHandler(n);
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ REPORT("staticmembervariableHandler", n);
+ current[STATIC_VAR] = true;
+ //String *symname = Getattr(n, "sym:name");
+ int result = Language::staticmembervariableHandler(n);
+ if (!GetFlag(n, "wrappedasconstant")) {
+ registerVariable(n);
+ }
+
+ if (result == SWIG_OK) {
+ // This will add static member variable to the class namespace with name ClassName_VarName
+ if (old_metatable_bindings && old_compatible_names) {
+ Swig_save("lua_staticmembervariableHandler", n, "lua:name", NIL);
+ String *lua_name = Getattr(n, "lua:name");
+ // Although this function uses Swig_name_member, it actually generates the Lua name,
+ // not the C++ name. This is because an earlier version used such a scheme for static function
+ // name generation and we have to maintain backward compatibility.
+ String *v2_name = Swig_name_member(NIL, proxy_class_name, lua_name);
+ if (!GetFlag(n, "wrappedasconstant")) {
+ Setattr(n, "lua:name", v2_name);
+ // Registering static var in the class parent nspace
+ registerVariable(n, true, getNSpace());
+ }
+ // If static member variable was wrapped as a constant, then
+ // constant wrapper has already performed all actions necessary for old_metatable_bindings
+ Delete(v2_name);
+ Swig_restore(n);
+ }
+ }
+ current[STATIC_VAR] = false;
+
+ return result;
+ }
+
+
+ /* ---------------------------------------------------------------------
+ * external runtime generation
+ * --------------------------------------------------------------------- */
+
+ /* This is to support the usage
+ SWIG -external-runtime <filename>
+ The code consists of two functions:
+ String *runtimeCode() // returns a large string with all the runtimes in
+ String *defaultExternalRuntimeFilename() // returns the default filename
+ I am writing a generic solution, even though SWIG-Lua only has one file right now...
+ */
+ String *runtimeCode() {
+ String *s = NewString("");
+ const char *filenames[] = { "luarun.swg", 0 }; // must be 0 terminated
+
+ emitLuaFlavor(s);
+
+ String *sfile = 0;
+ for (int i = 0; filenames[i] != 0; i++) {
+ sfile = Swig_include_sys(filenames[i]);
+ if (!sfile) {
+ Printf(stderr, "*** Unable to open '%s'\n", filenames[i]);
+ } else {
+ Append(s, sfile);
+ Delete(sfile);
+ }
+ }
+
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigluarun.h");
+ }
+
+ /* ---------------------------------------------------------------------
+ * helpers
+ * --------------------------------------------------------------------- */
+
+ void emitLuaFlavor(String *s) {
+ if (elua_emulate) {
+ Printf(s, "/*This is only emulation!*/\n");
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n");
+ Printf(s, "#define SWIG_LUA_ELUA_EMULATE\n");
+ } else if (elua_ltr)
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUA\n");
+ else if (eluac_ltr)
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_ELUAC\n");
+ else
+ Printf(s, "#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_LUA\n");
+ }
+
+
+ /* -----------------------------------------------------------------------------
+ * escapeCode()
+ *
+ * This is to convert the string of Lua code into a proper string, which can then be
+ * emitted into the C/C++ code.
+ * Basically it is a lot of search & replacing of odd sequences
+ * ---------------------------------------------------------------------------- */
+
+ void escapeCode(String *str) {
+ //Printf(f_runtime,"/* original luacode:[[[\n%s\n]]]\n*/\n",str);
+ Chop(str); // trim
+ Replace(str, "\\", "\\\\", DOH_REPLACE_ANY); // \ to \\ (this must be done first)
+ Replace(str, "\"", "\\\"", DOH_REPLACE_ANY); // " to \"
+ Replace(str, "\n", "\\n\"\n \"", DOH_REPLACE_ANY); // \n to \n"\n" (ie quoting every line)
+ //Printf(f_runtime,"/* hacked luacode:[[[\n%s\n]]]\n*/\n",str);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * rawGetCArraysHash(String *name)
+ *
+ * A small helper to hide implementation of how CArrays hashes are stored
+ * ---------------------------------------------------------------------------- */
+
+ Hash *rawGetCArraysHash(const_String_or_char_ptr name) {
+ Hash *scope = symbolScopeLookup( name ? name : "" );
+ if(!scope)
+ return 0;
+
+ Hash *carrays_hash = Getattr(scope, "lua:cdata");
+ return carrays_hash;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * getCArraysHash()
+ *
+ * Each namespace can be described with a hash that stores C arrays
+ * where members of the namespace should be added. All these hashes are stored
+ * inside the symbols table, in pseudo-symbol for every namespace.
+ * nspace could be NULL (NSPACE_TODO), that means functions and variables and classes
+ * that are not in any namespace (this is default for SWIG unless %nspace feature is used).
+ * You can later set some attributes that will affect behaviour of functions that use this hash:
+ * "lua:no_namespaces" will disable "namespaces" array.
+ * "lua:no_classes" will disable "classes" array.
+ * For every component ("attributes", "methods", etc) there are subcomponents:
+ * XXX:name - name of the C array that stores data for component
+ * XXX:decl - statement with forward declaration of this array;
+ * Namespace could be automatically registered to its parent if 'reg' == true. This can only be
+ * done during the first call (a.k.a when nspace is created).
+ * ---------------------------------------------------------------------------- */
+
+ Hash *getCArraysHash(String *nspace, bool reg = true) {
+ Hash *scope = symbolScopeLookup(nspace ? nspace : "");
+ if(!scope) {
+ symbolAddScope( nspace ? nspace : "" );
+ scope = symbolScopeLookup(nspace ? nspace : "");
+ assert(scope);
+ }
+ Hash *carrays_hash = Getattr(scope, "lua:cdata");
+ if (carrays_hash != 0)
+ return carrays_hash;
+ carrays_hash = NewHash();
+ String *mangled_name = 0;
+ if (nspace == 0 || Len(nspace) == 0)
+ mangled_name = NewString("SwigModule");
+ else
+ mangled_name = Swig_name_mangle_string(nspace);
+ String *cname = NewStringf("swig_%s", mangled_name);
+
+ Setattr(carrays_hash, "cname", cname);
+
+ String *attr_tab = NewString("");
+ String *attr_tab_name = NewStringf("swig_%s_attributes", mangled_name);
+ String *attr_tab_decl = NewString("");
+ Printv(attr_tab, "static swig_lua_attribute ", NIL);
+ Printv(attr_tab, attr_tab_name, "[]", NIL);
+ Printv(attr_tab_decl, attr_tab, ";\n", NIL);
+ Printv(attr_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "attributes", attr_tab);
+ Setattr(carrays_hash, "attributes:name", attr_tab_name);
+ Setattr(carrays_hash, "attributes:decl", attr_tab_decl);
+
+ String *methods_tab = NewString("");
+ String *methods_tab_name = NewStringf("swig_%s_methods", mangled_name);
+ String *methods_tab_decl = NewString("");
+ if (elua_ltr || eluac_ltr) // In this case methods array also acts as namespace rotable
+ Printf(methods_tab, "const LUA_REG_TYPE ");
+ else
+ Printf(methods_tab, "static swig_lua_method ");
+ Printv(methods_tab, methods_tab_name, "[]", NIL);
+ Printv(methods_tab_decl, methods_tab, ";\n", NIL);
+ Printv(methods_tab, "= {\n", NIL);
+ Setattr(carrays_hash, "methods", methods_tab);
+ Setattr(carrays_hash, "methods:name", methods_tab_name);
+ Setattr(carrays_hash, "methods:decl", methods_tab_decl);
+
+ String *const_tab = NewString("");
+ String *const_tab_name = NewStringf("swig_%s_constants", mangled_name);
+ String *const_tab_decl = NewString("");
+ if (elua_ltr || eluac_ltr) // In this case const array holds rotable with namespace constants
+ Printf(const_tab, "const LUA_REG_TYPE ");
+ else
+ Printf(const_tab, "static swig_lua_const_info ");
+ Printv(const_tab, const_tab_name, "[]", NIL);
+ Printv(const_tab_decl, const_tab, ";", NIL);
+ Printv(const_tab, "= {\n", NIL);
+ Setattr(carrays_hash, "constants", const_tab);
+ Setattr(carrays_hash, "constants:name", const_tab_name);
+ Setattr(carrays_hash, "constants:decl", const_tab_decl);
+
+ String *classes_tab = NewString("");
+ String *classes_tab_name = NewStringf("swig_%s_classes", mangled_name);
+ String *classes_tab_decl = NewString("");
+ Printf(classes_tab, "static swig_lua_class* ");
+ Printv(classes_tab, classes_tab_name, "[]", NIL);
+ Printv(classes_tab_decl, classes_tab, ";", NIL);
+ Printv(classes_tab, "= {\n", NIL);
+ Setattr(carrays_hash, "classes", classes_tab);
+ Setattr(carrays_hash, "classes:name", classes_tab_name);
+ Setattr(carrays_hash, "classes:decl", classes_tab_decl);
+
+ String *namespaces_tab = NewString("");
+ String *namespaces_tab_name = NewStringf("swig_%s_namespaces", mangled_name);
+ String *namespaces_tab_decl = NewString("");
+ Printf(namespaces_tab, "static swig_lua_namespace* ");
+ Printv(namespaces_tab, namespaces_tab_name, "[]", NIL);
+ Printv(namespaces_tab_decl, namespaces_tab, ";", NIL);
+ Printv(namespaces_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "namespaces", namespaces_tab);
+ Setattr(carrays_hash, "namespaces:name", namespaces_tab_name);
+ Setattr(carrays_hash, "namespaces:decl", namespaces_tab_decl);
+
+ if (elua_ltr) {
+ String *get_tab = NewString("");
+ String *get_tab_name = NewStringf("swig_%s_get", mangled_name);
+ String *get_tab_decl = NewString("");
+ Printv(get_tab, "const LUA_REG_TYPE ", get_tab_name, "[]", NIL);
+ Printv(get_tab_decl, get_tab, ";", NIL);
+ Printv(get_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "get", get_tab);
+ Setattr(carrays_hash, "get:name", get_tab_name);
+ Setattr(carrays_hash, "get:decl", get_tab_decl);
+
+ String *set_tab = NewString("");
+ String *set_tab_name = NewStringf("swig_%s_set", mangled_name);
+ String *set_tab_decl = NewString("");
+ Printv(set_tab, "const LUA_REG_TYPE ", set_tab_name, "[]", NIL);
+ Printv(set_tab_decl, set_tab, ";", NIL);
+ Printv(set_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "set", set_tab);
+ Setattr(carrays_hash, "set:name", set_tab_name);
+ Setattr(carrays_hash, "set:decl", set_tab_decl);
+
+ }
+ if (!eluac_ltr) {
+ String *metatable_tab = NewString("");
+ String *metatable_tab_name = NewStringf("swig_%s_meta", mangled_name);
+ String *metatable_tab_decl = NewString("");
+ if (elua_ltr) // In this case const array holds rotable with namespace constants
+ Printf(metatable_tab, "const LUA_REG_TYPE ");
+ else
+ Printf(metatable_tab, "static swig_lua_method ");
+ Printv(metatable_tab, metatable_tab_name, "[]", NIL);
+ Printv(metatable_tab_decl, metatable_tab, ";", NIL);
+ Printv(metatable_tab, " = {\n", NIL);
+ Setattr(carrays_hash, "metatable", metatable_tab);
+ Setattr(carrays_hash, "metatable:name", metatable_tab_name);
+ Setattr(carrays_hash, "metatable:decl", metatable_tab_decl);
+ }
+
+ Setattr(scope, "lua:cdata", carrays_hash);
+ assert(rawGetCArraysHash(nspace));
+
+ if (reg && nspace != 0 && Len(nspace) != 0 && GetFlag(carrays_hash, "lua:no_reg") == 0) {
+ // Split names into components
+ List *components = Split(nspace, '.', -1);
+ String *parent_path = NewString("");
+ int len = Len(components);
+ String *name = Copy(Getitem(components, len - 1));
+ for (int i = 0; i < len - 1; i++) {
+ if (i > 0)
+ Printv(parent_path, NSPACE_SEPARATOR, NIL);
+ String *item = Getitem(components, i);
+ Printv(parent_path, item, NIL);
+ }
+ Hash *parent = getCArraysHash(parent_path, true);
+ String *namespaces_tab = Getattr(parent, "namespaces");
+ Printv(namespaces_tab, "&", cname, ",\n", NIL);
+ if (elua_ltr || eluac_ltr) {
+ String *methods_tab = Getattr(parent, "methods");
+ Printv(methods_tab, tab4, "{LSTRKEY(\"", name, "\")", ", LROVAL(", methods_tab_name, ")", "},\n", NIL);
+ }
+ Setattr(carrays_hash, "name", name);
+
+ Delete(components);
+ Delete(parent_path);
+ } else if (!reg) // This namespace shouldn't be registered. Lets remember it.
+ SetFlag(carrays_hash, "lua:no_reg");
+
+ Delete(mangled_name);
+ mangled_name = 0;
+ return carrays_hash;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * closeCArraysHash()
+ *
+ * Functions add end markers {0,0,...,0} to all arrays, prints them to
+ * output and marks hash as closed (lua:closed). Consequent attempts to
+ * close the same hash will result in an error.
+ * closeCArraysHash DOES NOT print structure that describes namespace, it only
+ * prints array. You can use printCArraysDefinition to print structure.
+ * if "lua:no_namespaces" is set, then array for "namespaces" won't be printed
+ * if "lua:no_classes" is set, then array for "classes" won't be printed
+ * ----------------------------------------------------------------------------- */
+
+ void closeCArraysHash(String *nspace, File *output) {
+ Hash *carrays_hash = rawGetCArraysHash(nspace);
+ assert(carrays_hash);
+ assert(GetFlag(carrays_hash, "lua:closed") == 0);
+
+ SetFlag(carrays_hash, "lua:closed");
+
+ // Do arrays describe class instance part or class static part
+ const int is_instance = GetFlag(carrays_hash, "lua:class_instance");
+
+
+ String *attr_tab = Getattr(carrays_hash, "attributes");
+ Printf(attr_tab, " {0,0,0}\n};\n");
+ Printv(output, attr_tab, NIL);
+
+ String *const_tab = Getattr(carrays_hash, "constants");
+ String *const_tab_name = Getattr(carrays_hash, "constants:name");
+ if (elua_ltr || eluac_ltr)
+ Printv(const_tab, tab4, "{LNILKEY, LNILVAL}\n", "};\n", NIL);
+ else
+ Printf(const_tab, " {0,0,0,0,0,0}\n};\n");
+
+ // For the sake of compiling with -Wall -Werror we print constants
+ // only when necessary
+ int need_constants = 0;
+ if ( (elua_ltr || eluac_ltr) && (old_metatable_bindings) )
+ need_constants = 1;
+ else if (!is_instance) // static part need constants tab
+ need_constants = 1;
+
+ if (need_constants)
+ Printv(output, const_tab, NIL);
+
+ if (elua_ltr) {
+ // Put forward declaration of metatable array
+ Printv(output, "extern ", Getattr(carrays_hash, "metatable:decl"), "\n", NIL);
+ }
+ String *methods_tab = Getattr(carrays_hash, "methods");
+ String *metatable_tab_name = Getattr(carrays_hash, "metatable:name");
+ if (elua_ltr || eluac_ltr) {
+ if (old_metatable_bindings)
+ Printv(methods_tab, tab4, "{LSTRKEY(\"const\"), LROVAL(", const_tab_name, ")},\n", NIL);
+ if (elua_ltr) {
+ Printv(methods_tab, tab4, "{LSTRKEY(\"__metatable\"), LROVAL(", metatable_tab_name, ")},\n", NIL);
+ }
+
+ Printv(methods_tab, tab4, "{LSTRKEY(\"__disown\"), LFUNCVAL(SWIG_Lua_class_disown)},\n", NIL);
+ Printv(methods_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ } else
+ Printf(methods_tab, " {0,0}\n};\n");
+ Printv(output, methods_tab, NIL);
+
+ if (!GetFlag(carrays_hash, "lua:no_classes")) {
+ String *classes_tab = Getattr(carrays_hash, "classes");
+ Printf(classes_tab, " 0\n};\n");
+ Printv(output, classes_tab, NIL);
+ }
+
+ if (!GetFlag(carrays_hash, "lua:no_namespaces")) {
+ String *namespaces_tab = Getattr(carrays_hash, "namespaces");
+ Printf(namespaces_tab, " 0\n};\n");
+ Printv(output, namespaces_tab, NIL);
+ }
+ if (elua_ltr) {
+ String *get_tab = Getattr(carrays_hash, "get");
+ String *set_tab = Getattr(carrays_hash, "set");
+ Printv(get_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ Printv(set_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ Printv(output, get_tab, NIL);
+ Printv(output, set_tab, NIL);
+ }
+
+ // Heuristic whether we need to print metatable or not.
+ // For the sake of compiling with -Wall -Werror we don't print
+ // metatable for static part.
+ int need_metatable = 0;
+ if (eluac_ltr)
+ need_metatable = 0;
+ else if(!is_instance)
+ need_metatable = 0;
+ else
+ need_metatable = 1;
+
+ if (need_metatable) {
+ String *metatable_tab = Getattr(carrays_hash, "metatable");
+ assert(metatable_tab);
+ if (elua_ltr) {
+ String *get_tab_name = Getattr(carrays_hash, "get:name");
+ String *set_tab_name = Getattr(carrays_hash, "set:name");
+
+ if (GetFlag(carrays_hash, "lua:class_instance")) {
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_class_get)},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_class_set)},\n", NIL);
+ } else {
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__index\"), LFUNCVAL(SWIG_Lua_namespace_get)},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__newindex\"), LFUNCVAL(SWIG_Lua_namespace_set)},\n", NIL);
+ }
+
+ Printv(metatable_tab, tab4, "{LSTRKEY(\"__gc\"), LFUNCVAL(SWIG_Lua_class_destruct)},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".get\"), LROVAL(", get_tab_name, ")},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".set\"), LROVAL(", set_tab_name, ")},\n", NIL);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".fn\"), LROVAL(", Getattr(carrays_hash, "methods:name"), ")},\n", NIL);
+
+ if (GetFlag(carrays_hash, "lua:class_instance")) {
+ String *static_cls = Getattr(carrays_hash, "lua:class_instance:static_hash");
+ assert(static_cls);
+ // static_cls is swig_lua_namespace. This structure can't be used with eLua(LTR)
+ // Instead a structure describing its methods is used
+ String *static_cls_cname = Getattr(static_cls, "methods:name");
+ assert(static_cls_cname);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".static\"), LROVAL(", static_cls_cname, ")},\n", NIL);
+ // Put forward declaration of this array
+ Printv(output, "extern ", Getattr(static_cls, "methods:decl"), "\n", NIL);
+ } else if (GetFlag(carrays_hash, "lua:class_static")) {
+ Hash *instance_cls = Getattr(carrays_hash, "lua:class_static:instance_hash");
+ assert(instance_cls);
+ String *instance_cls_metatable_name = Getattr(instance_cls, "metatable:name");
+ assert(instance_cls_metatable_name);
+ Printv(metatable_tab, tab4, "{LSTRKEY(\".instance\"), LROVAL(", instance_cls_metatable_name, ")},\n", NIL);
+ }
+
+ Printv(metatable_tab, tab4, "{LNILKEY, LNILVAL}\n};\n", NIL);
+ } else {
+ Printf(metatable_tab, " {0,0}\n};\n");
+ }
+
+ Printv(output, metatable_tab, NIL);
+ }
+
+ Printv(output, "\n", NIL);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * closeNamespaces()
+ *
+ * Recursively close all non-closed namespaces. Prints data to dataOutput.
+ * ----------------------------------------------------------------------------- */
+
+ void closeNamespaces(File *dataOutput) {
+ // Special handling for empty module.
+ if (symbolScopeLookup("") == 0 || rawGetCArraysHash("") == 0) {
+ // Module is empty. Create hash for global scope in order to have swig_SwigModule
+ // variable in resulting file
+ getCArraysHash(0);
+ }
+ // Because we can't directly access 'symtabs', instead we access
+ // top-level scope and look on all scope pseudo-symbols in it.
+ Hash *top_scope = symbolScopeLookup("");
+ assert(top_scope);
+ Iterator ki = First(top_scope);
+ List *to_close = NewList();
+ while (ki.key) {
+ assert(ki.item);
+ if (Getattr(ki.item, "sym:scope")) {
+ // We have a pseudo symbol. Lets get actual scope for this pseudo symbol
+ Hash *carrays_hash = rawGetCArraysHash(ki.key);
+ assert(carrays_hash);
+ if (GetFlag(carrays_hash, "lua:closed") == 0)
+ Append(to_close, ki.key);
+ }
+ ki = Next(ki);
+ }
+ SortList(to_close, &compareByLen);
+ int len = Len(to_close);
+ for (int i = 0; i < len; i++) {
+ String *key = Getitem(to_close, i);
+ closeCArraysHash(key, dataOutput);
+ Hash *carrays_hash = rawGetCArraysHash(key);
+ String *name = 0; // name - name of the namespace as it should be visible in Lua
+ if (Len(key) == 0) // This is global module
+ name = module;
+ else
+ name = Getattr(carrays_hash, "name");
+ assert(name);
+ printCArraysDefinition(key, name, dataOutput);
+ }
+ Delete(to_close);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * printCArraysDefinition()
+ *
+ * This function prints to output a definition of namespace in form
+ * swig_lua_namespace $cname = { attr_array, methods_array, ... , namespaces_array };
+ * You can call this function as many times as is necessary.
+ * 'name' is a user-visible name that this namespace will have in Lua. It shouldn't
+ * be a fully qualified name, just its own name.
+ * ----------------------------------------------------------------------------- */
+
+ void printCArraysDefinition(String *nspace, String *name, File *output) {
+ Hash *carrays_hash = getCArraysHash(nspace, false);
+
+ String *cname = Getattr(carrays_hash, "cname"); // cname - name of the C structure that describes namespace
+ assert(cname);
+ Printv(output, "static swig_lua_namespace ", cname, " = ", NIL);
+
+ String *null_string = NewString("0");
+ String *attr_tab_name = Getattr(carrays_hash, "attributes:name");
+ String *methods_tab_name = Getattr(carrays_hash, "methods:name");
+ String *const_tab_name = Getattr(carrays_hash, "constants:name");
+ String *classes_tab_name = Getattr(carrays_hash, "classes:name");
+ String *namespaces_tab_name = Getattr(carrays_hash, "namespaces:name");
+ bool has_classes = GetFlag(carrays_hash, "lua:no_classes") == 0;
+ bool has_namespaces = GetFlag(carrays_hash, "lua:no_namespaces") == 0;
+
+ Printv(output, "{\n",
+ tab4, "\"", name, "\",\n",
+ tab4, methods_tab_name, ",\n",
+ tab4, attr_tab_name, ",\n",
+ tab4, const_tab_name, ",\n",
+ tab4, (has_classes) ? classes_tab_name : null_string, ",\n",
+ tab4, (has_namespaces) ? namespaces_tab_name : null_string, "\n};\n", NIL);
+ Delete(null_string);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * luaCurrentSymbolNSpace()
+ *
+ * This function determines actual namespace/scope where any symbol at the
+ * current moment should be placed. It looks at the 'current' array
+ * and depending on where are we - static class member/function,
+ * instance class member/function or just global functions decides
+ * where symbol should be put.
+ * The namespace/scope doesn't depend from symbol, only from 'current'
+ * ----------------------------------------------------------------------------- */
+
+ String *luaCurrentSymbolNSpace() {
+ String *scope = 0;
+ // If outside class, than NSpace is used.
+ // If inside class, but current[NO_CPP], then this is friend function. It belongs to NSpace
+ if (!getCurrentClass() || current[NO_CPP]) {
+ scope = getNSpace();
+ } else if (current[ENUM_CONST] && !CPlusPlus ) {
+ // Enums in C mode go to NSpace
+ scope = getNSpace();
+ } else {
+ // If inside class, then either class static namespace or class fully qualified name is used
+ assert(!current[NO_CPP]);
+ if (current[STATIC_FUNC] || current[STATIC_VAR] || current[STATIC_CONST]) {
+ scope = class_static_nspace;
+ } else if (current[MEMBER_VAR] || current[CONSTRUCTOR] || current[DESTRUCTOR]
+ || current[MEMBER_FUNC]) {
+ scope = full_proxy_class_name;
+ } else { // Friend functions are handled this way
+ scope = class_static_nspace;
+ }
+ assert(scope);
+ }
+ return scope;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * luaAddSymbol()
+ *
+ * Our implementation of addSymbol. Determines scope correctly, then
+ * forwards to Language::addSymbol
+ * ----------------------------------------------------------------------------- */
+
+ int luaAddSymbol(const String *s, const Node *n) {
+ String *scope = luaCurrentSymbolNSpace();
+ return luaAddSymbol(s, n, scope);
+ }
+
+ /* -----------------------------------------------------------------------------
+ * luaAddSymbol()
+ *
+ * Overload. Enforces given scope. Actually, it simply forwards call to Language::addSymbol
+ * ----------------------------------------------------------------------------- */
+
+ int luaAddSymbol(const String *s, const Node *n, const_String_or_char_ptr scope) {
+ int result = Language::addSymbol(s, n, scope);
+ if (!result)
+ Printf(stderr, "addSymbol(%s to scope %s) failed\n", s, scope);
+ return result;
+ }
+
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_lua() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+extern "C" Language *swig_lua(void) {
+ return new LUA();
+}
diff --git a/contrib/tools/swig/Source/Modules/main.cxx b/contrib/tools/swig/Source/Modules/main.cxx
new file mode 100644
index 00000000000..f68b609c903
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/main.cxx
@@ -0,0 +1,1400 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * main.cxx
+ *
+ * Main entry point to the SWIG core.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigconfig.h"
+
+#if defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "swigmod.h"
+
+#include "swigwarn.h"
+#include "cparse.h"
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h> // for INT_MAX
+
+// Global variables
+
+static Language *lang = 0; // Language method
+int CPlusPlus = 0;
+int Extend = 0; // Extend flag
+int ForceExtern = 0; // Force extern mode
+int Verbose = 0;
+int AddExtern = 0;
+int NoExcept = 0;
+extern "C" {
+ int UseWrapperSuffix = 0; // If 1, append suffix to non-overloaded functions too.
+}
+
+/* Suppress warning messages for private inheritance, etc by default.
+ These are enabled by command line option -Wextra.
+
+ WARN_PARSE_PRIVATE_INHERIT 309
+ WARN_PARSE_BUILTIN_NAME 321
+ WARN_PARSE_REDUNDANT 322
+ WARN_TYPE_ABSTRACT 403
+ WARN_TYPE_RVALUE_REF_QUALIFIER_IGNORED 405
+ WARN_LANG_OVERLOAD_CONST 512
+ */
+#define EXTRA_WARNINGS "309,403,405,512,321,322"
+
+extern "C" {
+ extern String *ModuleName;
+ extern int ignore_nested_classes;
+ extern int kwargs_supported;
+}
+
+/* usage string split into multiple parts otherwise string is too big for some compilers */
+/* naming conventions for commandline options - no underscores, no capital letters, join words together
+ * except when using a common prefix, then use '-' to separate, eg the debug-xxx options */
+static const char *usage1 = "\
+\nGeneral Options\n\
+ -addextern - Add extra extern declarations\n\
+ -c++ - Enable C++ processing\n\
+ -co <file> - Check <file> out of the SWIG library\n\
+ -copyctor - Automatically generate copy constructors wherever possible\n\
+ -cpperraswarn - Treat the preprocessor #error statement as #warning (default)\n\
+ -cppext <ext> - Change file extension of generated C++ files to <ext>\n\
+ (default is cxx)\n\
+ -copyright - Display copyright notices\n\
+ -debug-classes - Display information about the classes found in the interface\n\
+ -debug-module <n>- Display module parse tree at stages 1-4, <n> is a csv list of stages\n\
+ -debug-symtabs - Display symbol tables information\n\
+ -debug-symbols - Display target language symbols in the symbol tables\n\
+ -debug-csymbols - Display C symbols in the symbol tables\n\
+ -debug-lsymbols - Display target language layer symbols\n\
+ -debug-quiet - Display less parse tree node debug info when using other -debug options\n\
+ -debug-tags - Display information about the tags found in the interface\n\
+ -debug-template - Display information for debugging templates\n\
+ -debug-top <n> - Display entire parse tree at stages 1-4, <n> is a csv list of stages\n\
+ -debug-typedef - Display information about the types and typedefs in the interface\n\
+ -debug-typemap - Display typemap debugging information\n\
+ -debug-tmsearch - Display typemap search debugging information\n\
+ -debug-tmused - Display typemaps used debugging information\n\
+ -directors - Turn on director mode for all the classes, mainly for testing\n\
+ -dirprot - Turn on wrapping of protected members for director classes (default)\n\
+ -D<symbol>[=<value>] - Define symbol <symbol> (for conditional compilation)\n\
+";
+
+static const char *usage2 = "\
+ -E - Preprocess only, does not generate wrapper code\n\
+ -external-runtime [file] - Export the SWIG runtime stack\n\
+ -fakeversion <v>- Make SWIG fake the program version number to <v>\n\
+ -fcompact - Compile in compact mode\n\
+ -features <list>- Set global features, where <list> is a comma separated list of\n\
+ features, eg -features directors,autodoc=1\n\
+ If no explicit value is given to the feature, a default of 1 is used\n\
+ -fastdispatch - Enable fast dispatch mode to produce faster overload dispatcher code\n\
+ -Fmicrosoft - Display error/warning messages in Microsoft format\n\
+ -Fstandard - Display error/warning messages in commonly used format\n\
+ -fvirtual - Compile in virtual elimination mode\n\
+ -help - Display help\n\
+ -I- - Don't search the current directory\n\
+ -I<dir> - Look for SWIG files in directory <dir>\n\
+ -ignoremissing - Ignore missing include files\n\
+ -importall - Follow all #include statements as imports\n\
+ -includeall - Follow all #include statements\n\
+ -l<ifile> - Include SWIG library file <ifile>\n\
+";
+
+static const char *usage3 = "\
+ -macroerrors - Report errors inside macros\n\
+ -M - List all dependencies\n\
+ -MD - Is equivalent to `-M -MF <file>', except `-E' is not implied\n\
+ -MF <file> - Generate dependencies into <file> and continue generating wrappers\n\
+ -MM - List dependencies, but omit files in SWIG library\n\
+ -MMD - Like `-MD', but omit files in SWIG library\n\
+ -module <name> - Set module name to <name>\n\
+ -MP - Generate phony targets for all dependencies\n\
+ -MT <target> - Set the target of the rule emitted by dependency generation\n\
+ -nocontract - Turn off contract checking\n\
+ -nocpperraswarn - Do not treat the preprocessor #error statement as #warning\n\
+ -nodefaultctor - Do not generate implicit default constructors\n\
+ -nodefaultdtor - Do not generate implicit default destructors\n\
+ -nodirprot - Do not wrap director protected members\n\
+ -noexcept - Do not wrap exception specifiers\n\
+ -nofastdispatch - Disable fast dispatch mode (default)\n\
+ -nopreprocess - Skip the preprocessor step\n\
+ -notemplatereduce - Disable reduction of the typedefs in templates\n\
+";
+
+static const char *usage4 = "\
+ -O - Enable the optimization options:\n\
+ -fastdispatch -fvirtual\n\
+ -o <outfile> - Set name of C/C++ output file to <outfile>\n\
+ -oh <headfile> - Set name of C++ output header file for directors to <headfile>\n\
+ -outcurrentdir - Set default output dir to current dir instead of input file's path\n\
+ -outdir <dir> - Set language specific files output directory to <dir>\n\
+ -pcreversion - Display PCRE2 version information\n\
+ -small - Compile in virtual elimination and compact mode\n\
+ -std=<standard> - Set the C or C++ language <standard> for inputs\n\
+ -swiglib - Report location of SWIG library and exit\n\
+ -templatereduce - Reduce all the typedefs in templates\n\
+ -U<symbol> - Undefine symbol <symbol>\n\
+ -v - Run in verbose mode\n\
+ -version - Display SWIG version number\n\
+ -Wall - Remove all warning suppression, also implies -Wextra\n\
+ -Wallkw - Enable keyword warnings for all the supported languages\n\
+ -Werror - Treat warnings as errors\n\
+ -Wextra - Adds the following additional warnings: " EXTRA_WARNINGS "\n\
+ -w<list> - Suppress/add warning messages, eg -w401,+321 - see Warnings.html\n\
+ -xmlout <file> - Write XML version of the parse tree to <file> after normal processing\n\
+\n\
+Options can also be defined using the SWIG_FEATURES environment variable, for example:\n\
+\n\
+ $ SWIG_FEATURES=\"-Wall\"\n\
+ $ export SWIG_FEATURES\n\
+ $ swig -python interface.i\n\
+\n\
+is equivalent to:\n\
+\n\
+ $ swig -Wall -python interface.i\n\
+\n\
+Arguments may also be passed in a file, separated by whitespace. For example:\n\
+\n\
+ $ echo \"-Wall -python interface.i\" > args.txt\n\
+ $ swig @args.txt\n\
+\n";
+
+// Local variables
+static String *LangSubDir = 0; // Target language library subdirectory
+static String *SwigLib = 0; // Library directory
+static String *SwigLibWinUnix = 0; // Extra library directory on Windows
+static int freeze = 0;
+static String *lang_config = 0;
+static const char *hpp_extension = "h";
+static const char *cpp_extension = "cxx";
+static const char *depends_extension = "d";
+static String *outdir = 0;
+static String *xmlout = 0;
+static int outcurrentdir = 0;
+static int help = 0;
+static int checkout = 0;
+static int cpp_only = 0;
+static int no_cpp = 0;
+static String *outfile_name = 0;
+static String *outfile_name_h = 0;
+static int tm_debug = 0;
+static int dump_symtabs = 0;
+static int dump_symbols = 0;
+static int dump_csymbols = 0;
+static int dump_lang_symbols = 0;
+static int dump_tags = 0;
+static int dump_module = 0;
+static int dump_top = 0;
+static int dump_typedef = 0;
+static int dump_classes = 0;
+static int werror = 0;
+static int depend = 0;
+static int depend_only = 0;
+static int depend_phony = 0;
+static int memory_debug = 0;
+static int allkw = 0;
+static DOH *cpps = 0;
+static String *dependencies_file = 0;
+static String *dependencies_target = 0;
+static int external_runtime = 0;
+static String *external_runtime_name = 0;
+enum { STAGE1=1, STAGE2=2, STAGE3=4, STAGE4=8, STAGEOVERFLOW=16 };
+static List *libfiles = 0;
+static List *all_output_files = 0;
+static const char *stdcpp_define = NULL;
+static const char *stdc_define = NULL;
+
+/* -----------------------------------------------------------------------------
+ * check_extension()
+ *
+ * Checks the extension of a file to see if we should emit extern declarations.
+ * ----------------------------------------------------------------------------- */
+
+static bool check_extension(String *filename) {
+ bool wanted = false;
+ const char *name = Char(filename);
+ if (!name)
+ return 0;
+ String *extension = Swig_file_extension(name);
+ const char *c = Char(extension);
+ if ((strcmp(c, ".c") == 0) ||
+ (strcmp(c, ".C") == 0) || (strcmp(c, ".cc") == 0) || (strcmp(c, ".cxx") == 0) || (strcmp(c, ".c++") == 0) || (strcmp(c, ".cpp") == 0)) {
+ wanted = true;
+ }
+ Delete(extension);
+ return wanted;
+}
+
+/* -----------------------------------------------------------------------------
+ * decode_numbers_list()
+ *
+ * Decode comma separated list into a binary number of the inputs or'd together
+ * eg list="1,4" will return (2^0 || 2^3) = 0x1001
+ * ----------------------------------------------------------------------------- */
+
+static unsigned int decode_numbers_list(String *numlist) {
+ unsigned int decoded_number = 0;
+ if (numlist) {
+ List *numbers = Split(numlist, ',', INT_MAX);
+ if (numbers && Len(numbers) > 0) {
+ for (Iterator it = First(numbers); it.item; it = Next(it)) {
+ String *numstring = it.item;
+ // TODO: check that it is a number
+ int number = atoi(Char(numstring));
+ if (number > 0 && number <= 16) {
+ decoded_number |= (1 << (number-1));
+ }
+ }
+ }
+ }
+ return decoded_number;
+}
+
+/* -----------------------------------------------------------------------------
+ * Sets the output directory for language specific (proxy) files from the
+ * C wrapper file if not set and corrects the directory name and adds a trailing
+ * file separator if necessary.
+ * ----------------------------------------------------------------------------- */
+
+static void configure_outdir(const String *c_wrapper_outfile) {
+
+ // Use the C wrapper file's directory if the output directory has not been set by user
+ if (!outdir || Len(outdir) == 0)
+ outdir = Swig_file_dirname(c_wrapper_outfile);
+
+ Swig_filename_correct(outdir);
+
+ // Add trailing file delimiter if not present in output directory name
+ if (Len(outdir) > 0) {
+ const char *outd = Char(outdir);
+ if (strcmp(outd + strlen(outd) - strlen(SWIG_FILE_DELIMITER), SWIG_FILE_DELIMITER) != 0)
+ Printv(outdir, SWIG_FILE_DELIMITER, NIL);
+ }
+}
+
+/* This function sets the name of the configuration file */
+void SWIG_config_file(const_String_or_char_ptr filename) {
+ lang_config = NewString(filename);
+}
+
+/* Sets the target language subdirectory name */
+void SWIG_library_directory(const char *subdirectory) {
+ LangSubDir = NewString(subdirectory);
+}
+
+// Returns the directory for generating language specific files (non C/C++ files)
+const String *SWIG_output_directory() {
+ assert(outdir);
+ return outdir;
+}
+
+void SWIG_config_cppext(const char *ext) {
+ cpp_extension = ext;
+}
+
+List *SWIG_output_files() {
+ assert(all_output_files);
+ return all_output_files;
+}
+
+static void SWIG_setfeature(const char *cfeature, const char *cvalue) {
+ Hash *features_hash = Swig_cparse_features();
+ String *name = NewString("");
+ String *fname = NewString(cfeature);
+ String *fvalue = NewString(cvalue);
+ Swig_feature_set(features_hash, name, 0, fname, fvalue, 0);
+ Delete(name);
+ Delete(fname);
+ Delete(fvalue);
+}
+
+
+static void SWIG_setfeatures(const char *c) {
+ char feature[64];
+ char *fb = feature;
+ char *fe = fb + 63;
+ Hash *features_hash = Swig_cparse_features();
+ String *name = NewString("");
+ /* Printf(stderr,"all features %s\n", c); */
+ while (*c) {
+ char *f = fb;
+ String *fname = NewString("feature:");
+ String *fvalue = NewString("");
+ while ((f != fe) && *c != '=' && *c != ',' && *c) {
+ *(f++) = *(c++);
+ }
+ *f = 0;
+ Printf(fname, "%s", feature);
+ if (*c && *(c++) == '=') {
+ char value[64];
+ char *v = value;
+ char *ve = v + 63;
+ while ((v != ve) && *c != ',' && *c && !isspace(*c)) {
+ *(v++) = *(c++);
+ }
+ *v = 0;
+ Printf(fvalue, "%s", value);
+ } else {
+ Printf(fvalue, "1");
+ }
+ /* Printf(stderr,"%s %s\n", fname, fvalue); */
+ Swig_feature_set(features_hash, name, 0, fname, fvalue, 0);
+ Delete(fname);
+ Delete(fvalue);
+ }
+ Delete(name);
+}
+
+/* This function handles the -external-runtime command option */
+static void SWIG_dump_runtime() {
+ String *outfile;
+ File *runtime;
+ String *s;
+
+ outfile = external_runtime_name;
+ if (!outfile) {
+ outfile = lang->defaultExternalRuntimeFilename();
+ if (!outfile) {
+ Printf(stderr, "*** Please provide a filename for the external runtime\n");
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ runtime = NewFile(outfile, "w", SWIG_output_files());
+ if (!runtime) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ Swig_banner(runtime);
+ Printf(runtime, "\n");
+
+ s = Swig_include_sys("swigcompat.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swigcompat.swg'\n");
+ Delete(runtime);
+ Exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("swiglabels.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swiglabels.swg'\n");
+ Delete(runtime);
+ Exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("swigerrors.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swigerrors.swg'\n");
+ Delete(runtime);
+ Exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("swigrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'swigrun.swg'\n");
+ Delete(runtime);
+ Exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = lang->runtimeCode();
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ s = Swig_include_sys("runtime.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'runtime.swg'\n");
+ Delete(runtime);
+ Exit(EXIT_FAILURE);
+ }
+ Printf(runtime, "%s", s);
+ Delete(s);
+
+ Delete(runtime);
+ Exit(EXIT_SUCCESS);
+}
+
+static void getoptions(int argc, char *argv[]) {
+ int i;
+ // Get options
+ for (i = 1; i < argc; i++) {
+ if (argv[i] && !Swig_check_marked(i)) {
+ if (strncmp(argv[i], "-I-", 3) == 0) {
+ // Don't push/pop directories
+ Swig_set_push_dir(0);
+ Swig_mark_arg(i);
+ } else if (strncmp(argv[i], "-I", 2) == 0) {
+ // Add a new directory search path
+ Swig_add_directory((String_or_char*)(argv[i] + 2));
+ Swig_mark_arg(i);
+ } else if (strncmp(argv[i], "-D", 2) == 0) {
+ String *d = NewString(argv[i] + 2);
+ if (Replace(d, "=", " ", DOH_REPLACE_FIRST) == 0) {
+ // Match C preprocessor behaviour whereby -DFOO sets FOO=1.
+ Append(d, " 1");
+ }
+ // Create a symbol
+ Preprocessor_define(d, 0);
+ Delete(d);
+ Swig_mark_arg(i);
+ } else if (strncmp(argv[i], "-U", 2) == 0) {
+ Preprocessor_undef(argv[i] + 2);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-E") == 0) {
+ cpp_only = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nopreprocess") == 0) {
+ no_cpp = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-verbose") == 0) || (strcmp(argv[i], "-v") == 0)) {
+ Verbose = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-c++") == 0) {
+ CPlusPlus = 1;
+ 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 (strncmp(argv[i], "-std=c", 6) == 0) {
+ const char *std = argv[i] + 6;
+ if (strncmp(std, "++", 2) == 0) {
+ std += 2;
+ if (strcmp(std, "98") == 0 || strcmp(std, "03") == 0) {
+ stdcpp_define = "__cplusplus 199711L";
+ } else if (strcmp(std, "11") == 0) {
+ stdcpp_define = "__cplusplus 201103L";
+ } else if (strcmp(std, "14") == 0) {
+ stdcpp_define = "__cplusplus 201402L";
+ } else if (strcmp(std, "17") == 0) {
+ stdcpp_define = "__cplusplus 201703L";
+ } else if (strcmp(std, "20") == 0) {
+ stdcpp_define = "__cplusplus 202002L";
+ } else if (strcmp(std, "23") == 0) {
+ stdcpp_define = "__cplusplus 202302L";
+ } else {
+ Printf(stderr, "Unrecognised C++ standard version in option '%s'\n", argv[i]);
+ Exit(EXIT_FAILURE);
+ }
+ } else {
+ if (strcmp(std, "89") == 0 || strcmp(std, "90") == 0) {
+ stdc_define = NULL;
+ } else if (strcmp(std, "95") == 0) {
+ stdc_define = "__STDC_VERSION__ 199409L";
+ } else if (strcmp(std, "99") == 0) {
+ stdc_define = "__STDC_VERSION__ 199901L";
+ } else if (strcmp(std, "11") == 0) {
+ stdc_define = "__STDC_VERSION__ 201112L";
+ } else if (strcmp(std, "17") == 0 || strcmp(std, "18") == 0) {
+ // Both GCC and clang accept -std=c18 as well as -std=c17.
+ stdc_define = "__STDC_VERSION__ 201710L";
+ } else if (strcmp(std, "23") == 0) {
+ stdc_define = "__STDC_VERSION__ 202311L";
+ } else {
+ Printf(stderr, "Unrecognised C standard version in option '%s'\n", argv[i]);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fcompact") == 0) {
+ Wrapper_compact_print_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fvirtual") == 0) {
+ Wrapper_virtual_elimination_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastdispatch") == 0) {
+ Wrapper_fast_dispatch_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nofastdispatch") == 0) {
+ Wrapper_fast_dispatch_mode_set(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-naturalvar") == 0) {
+ Wrapper_naturalvar_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-directors") == 0) {
+ SWIG_setfeature("feature:director", "1");
+ Wrapper_director_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dirprot") == 0) {
+ Wrapper_director_protected_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nodirprot") == 0) {
+ Wrapper_director_protected_mode_set(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-pcreversion") == 0) {
+ String *version = Swig_pcre_version();
+ Printf(stdout, "%s\n", version);
+ Delete(version);
+ Swig_mark_arg(i);
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-small") == 0) {
+ Wrapper_compact_print_mode_set(1);
+ Wrapper_virtual_elimination_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-external-runtime") == 0) {
+ external_runtime = 1;
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ external_runtime_name = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ i++;
+ }
+ } else if ((strcmp(argv[i], "-nodefaultctor") == 0)) {
+ SWIG_setfeature("feature:nodefaultctor", "1");
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-nodefaultdtor") == 0)) {
+ SWIG_setfeature("feature:nodefaultdtor", "1");
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-copyctor") == 0)) {
+ SWIG_setfeature("feature:copyctor", "1");
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noexcept") == 0) {
+ NoExcept = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-addextern") == 0) {
+ AddExtern = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-template") == 0) {
+ Swig_cparse_debug_templates(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-templatereduce") == 0) {
+ SWIG_cparse_template_reduce(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-notemplatereduce") == 0) {
+ SWIG_cparse_template_reduce(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-macroerrors") == 0) {
+ Swig_cparse_follow_locators(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-swiglib") == 0) {
+ Printf(stdout, "%s\n", SwigLib);
+ if (SwigLibWinUnix)
+ Printf(stdout, "%s\n", SwigLibWinUnix);
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-o") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outfile_name = NewString(argv[i + 1]);
+ Swig_filename_correct(outfile_name);
+ if (!outfile_name_h || !dependencies_file) {
+ char *ext = strrchr(Char(outfile_name), '.');
+ String *basename = ext ? NewStringWithSize(Char(outfile_name), (int)(Char(ext) - Char(outfile_name))) : NewString(outfile_name);
+ if (!dependencies_file) {
+ dependencies_file = NewStringf("%s.%s", basename, depends_extension);
+ }
+ if (!outfile_name_h) {
+ Printf(basename, ".%s", hpp_extension);
+ outfile_name_h = NewString(basename);
+ }
+ Delete(basename);
+ }
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-oh") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outfile_name_h = NewString(argv[i + 1]);
+ Swig_filename_correct(outfile_name_h);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-fakeversion") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ Swig_set_fakeversion(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-version") == 0 || strcmp(argv[1], "--version") == 0) {
+ fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
+ fprintf(stdout, "\nCompiled with %s [%s]\n", SWIG_CXX, SWIG_PLATFORM);
+ fprintf(stdout, "\nConfigured options: %cpcre\n",
+#ifdef HAVE_PCRE
+ '+'
+#else
+ '-'
+#endif
+ );
+ fprintf(stdout, "\nPlease see %s for reporting bugs and further information\n", PACKAGE_BUGREPORT);
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-copyright") == 0) {
+ fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
+ fprintf(stdout, "Copyright (c) 1995-1998\n");
+ fprintf(stdout, "University of Utah and the Regents of the University of California\n");
+ fprintf(stdout, "Copyright (c) 1998-2005\n");
+ fprintf(stdout, "University of Chicago\n");
+ fprintf(stdout, "Copyright (c) 2005-2006\n");
+ fprintf(stdout, "Arizona Board of Regents (University of Arizona)\n");
+ Exit(EXIT_SUCCESS);
+ } else if (strncmp(argv[i], "-l", 2) == 0) {
+ // Add a new directory search path
+ Append(libfiles, argv[i] + 2);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-co") == 0) {
+ checkout = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-features") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ SWIG_setfeatures(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-freeze") == 0) {
+ freeze = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-includeall") == 0) {
+ Preprocessor_include_all(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-importall") == 0) {
+ Preprocessor_import_all(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-ignoremissing") == 0) {
+ Preprocessor_ignore_missing(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cpperraswarn") == 0) {
+ Preprocessor_error_as_warning(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocpperraswarn") == 0) {
+ Preprocessor_error_as_warning(0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppext") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ SWIG_config_cppext(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-debug-typemap") == 0) {
+ tm_debug = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-tmsearch") == 0) {
+ Swig_typemap_search_debug_set();
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-tmused") == 0) {
+ Swig_typemap_used_debug_set();
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-module") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ ModuleName = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-M") == 0) {
+ depend = 1;
+ depend_only = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MM") == 0) {
+ depend = 2;
+ depend_only = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MF") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ dependencies_file = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-MD") == 0) {
+ depend = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MMD") == 0) {
+ depend = 2;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MP") == 0) {
+ depend_phony = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-MT") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ if (!dependencies_target)
+ dependencies_target = NewString(argv[i + 1]);
+ else
+ Printf(dependencies_target, " %s", argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-outdir") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ outdir = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-outcurrentdir") == 0) {
+ Swig_mark_arg(i);
+ outcurrentdir = 1;
+ } else if (strcmp(argv[i], "-Wall") == 0) {
+ Swig_mark_arg(i);
+ Swig_warnall();
+ } else if (strcmp(argv[i], "-Wallkw") == 0) {
+ allkw = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Werror") == 0) {
+ werror = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Wextra") == 0) {
+ Swig_mark_arg(i);
+ Swig_warnfilter(EXTRA_WARNINGS, 0);
+ } else if (strncmp(argv[i], "-w", 2) == 0) {
+ Swig_mark_arg(i);
+ Swig_warnfilter(argv[i] + 2, 1);
+ } else if (strcmp(argv[i], "-debug-quiet") == 0) {
+ Swig_print_quiet(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-symtabs") == 0) {
+ dump_symtabs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-symbols") == 0) {
+ dump_symbols = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-csymbols") == 0) {
+ dump_csymbols = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-lsymbols") == 0) {
+ dump_lang_symbols = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-tags") == 0) {
+ dump_tags = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-top") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ String *dump_list = NewString(argv[i + 1]);
+ dump_top = decode_numbers_list(dump_list);
+ if (dump_top < STAGE1 || dump_top >= STAGEOVERFLOW)
+ Swig_arg_error();
+ else
+ Swig_mark_arg(i + 1);
+ Delete(dump_list);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-debug-module") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ String *dump_list = NewString(argv[i + 1]);
+ dump_module = decode_numbers_list(dump_list);
+ if (dump_module < STAGE1 || dump_module >= STAGEOVERFLOW)
+ Swig_arg_error();
+ else
+ Swig_mark_arg(i + 1);
+ Delete(dump_list);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-xmlout") == 0) {
+ Swig_mark_arg(i);
+ if (argv[i + 1]) {
+ xmlout = NewString(argv[i + 1]);
+ Swig_mark_arg(i + 1);
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-nocontract") == 0) {
+ Swig_mark_arg(i);
+ Swig_contract_mode_set(0);
+ } else if (strcmp(argv[i], "-debug-typedef") == 0) {
+ dump_typedef = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-classes") == 0) {
+ dump_classes = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-memory") == 0) {
+ memory_debug = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Fstandard") == 0) {
+ Swig_error_msg_format(EMF_STANDARD);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-Fmicrosoft") == 0) {
+ Swig_error_msg_format(EMF_MICROSOFT);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-O") == 0) {
+ Wrapper_virtual_elimination_mode_set(1);
+ Wrapper_fast_dispatch_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage1, stdout);
+ fputs(usage2, stdout);
+ fputs(usage3, stdout);
+ fputs(usage4, stdout);
+ Swig_mark_arg(i);
+ help = 1;
+ }
+ }
+ }
+}
+
+static void SWIG_exit_handler(int status);
+
+int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm) {
+ char *c;
+
+ /* Set function for Exit() to call. */
+ SetExitHandler(SWIG_exit_handler);
+
+ /* Initialize the SWIG core */
+ Swig_init();
+
+ // Default warning suppression
+ Swig_warnfilter(EXTRA_WARNINGS, 1);
+
+ // Initialize the preprocessor
+ Preprocessor_init();
+
+ // Set lang to a dummy value if no target language was specified so we
+ // can process options enough to handle -version, etc.
+ lang = tlm ? tlm->fac() : new Language;
+
+ Swig_contract_mode_set(1);
+
+ /* Turn off directors mode */
+ Wrapper_director_mode_set(0);
+ Wrapper_director_protected_mode_set(1);
+
+ // Inform the parser if the nested classes should be ignored unless explicitly told otherwise via feature:flatnested
+ ignore_nested_classes = lang->nestedClassesSupport() == Language::NCS_Unknown ? 1 : 0;
+
+ kwargs_supported = lang->kwargsSupport() ? 1 : 0;
+
+ // Create Library search directories
+
+ // Check for SWIG_LIB environment variable
+ c = getenv("SWIG_LIB");
+ if (c == (char *) 0 || *c == 0) {
+#if defined(_WIN32)
+ char buf[MAX_PATH];
+ char *p;
+ if (!(GetModuleFileName(0, buf, MAX_PATH) == 0 || (p = strrchr(buf, '\\')) == 0)) {
+ *(p + 1) = '\0';
+ SwigLib = NewStringf("%sLib", buf); // Native windows installation path
+ } else {
+ SwigLib = NewStringf(""); // Unexpected error
+ }
+ if (Len(SWIG_LIB_WIN_UNIX) > 0)
+ SwigLibWinUnix = NewString(SWIG_LIB_WIN_UNIX); // Unix installation path using a drive letter (for msys/mingw)
+#else
+ SwigLib = NewString(SWIG_LIB);
+#endif
+ } else {
+ SwigLib = NewString(c);
+ }
+
+ libfiles = NewList();
+ all_output_files = NewList();
+
+ getoptions(argc, argv);
+
+ // Parse language dependent options
+ lang->main(argc, argv);
+
+ if (help) {
+ Printf(stdout, "\nNote: 'swig -<lang> -help' displays options for a specific target language.\n\n");
+ Exit(EXIT_SUCCESS); // Exit if we're in help mode
+ }
+
+ // Check all of the options to make sure we're cool.
+ // 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");
+ Exit(EXIT_FAILURE);
+ }
+
+ // Set up some default symbols (available in both SWIG interface files
+ // and C files). Define all predefined symbols after option parsing so
+ // that attempts to use `-U` to undefine them are consistently handled.
+
+ Preprocessor_define("SWIG 1", 0);
+ Preprocessor_define("__STDC__ 1", 0);
+
+ if (CPlusPlus) {
+ // Default to C++98.
+ if (!stdcpp_define) stdcpp_define = "__cplusplus 199711L";
+ Preprocessor_define(stdcpp_define, 0);
+ } else {
+ if (stdcpp_define) {
+ Printf(stderr, "Option -std=c++XX was used without -c++\n");
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!CPlusPlus) {
+ // Default to C90 which didn't define __STDC_VERSION__.
+ if (stdc_define) {
+ Preprocessor_define(stdc_define, 0);
+ }
+ } else {
+ if (stdc_define) {
+ Printf(stderr, "Option -std=cXX was used with -c++\n");
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ String *vers = Swig_package_version_hex();
+ Preprocessor_define(vers, 0);
+ Delete(vers);
+
+ // Add language dependent directory to the search path
+ {
+ String *rl = NewString("");
+ Printf(rl, ".%sswig_lib%s%s", SWIG_FILE_DELIMITER, SWIG_FILE_DELIMITER, LangSubDir);
+ Swig_add_directory(rl);
+ if (SwigLibWinUnix) {
+ rl = NewString("");
+ Printf(rl, "%s%s%s", SwigLibWinUnix, SWIG_FILE_DELIMITER, LangSubDir);
+ Swig_add_directory(rl);
+ }
+ rl = NewString("");
+ Printf(rl, "%s%s%s", SwigLib, SWIG_FILE_DELIMITER, LangSubDir);
+ Swig_add_directory(rl);
+ }
+
+ Swig_add_directory((String *) "." SWIG_FILE_DELIMITER "swig_lib");
+ if (SwigLibWinUnix)
+ Swig_add_directory((String *) SwigLibWinUnix);
+ Swig_add_directory(SwigLib);
+
+ if (Verbose) {
+ Printf(stdout, "Language subdirectory: %s\n", LangSubDir);
+ Printf(stdout, "Search paths:\n");
+ List *sp = Swig_search_path();
+ Iterator s;
+ for (s = First(sp); s.item; s = Next(s)) {
+ Printf(stdout, " %s\n", s.item);
+ }
+ }
+ // handle the -external-runtime argument
+ if (external_runtime)
+ SWIG_dump_runtime();
+
+ // If we made it this far, looks good. go for it....
+
+ input_file = NewString(argv[argc - 1]);
+ Swig_filename_correct(input_file);
+
+ // If the user has requested to check out a file, handle that
+ if (checkout) {
+ DOH *s;
+ String *outfile = input_file;
+ if (outfile_name)
+ outfile = outfile_name;
+
+ if (Verbose)
+ Printf(stdout, "Handling checkout...\n");
+
+ s = Swig_include(input_file);
+ if (!s) {
+ Printf(stderr, "Unable to locate '%s' in the SWIG library.\n", input_file);
+ } else {
+ FILE *f = Swig_open(outfile);
+ if (f) {
+ fclose(f);
+ Printf(stderr, "File '%s' already exists. Checkout aborted.\n", outfile);
+ } else {
+ File *f_outfile = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_outfile) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ } else {
+ if (Verbose)
+ Printf(stdout, "'%s' checked out from the SWIG library.\n", outfile);
+ Printv(f_outfile, s, NIL);
+ Delete(f_outfile);
+ }
+ }
+ }
+ } else {
+ // Run the preprocessor
+ if (Verbose)
+ Printf(stdout, "Preprocessing...\n");
+
+ {
+ int i;
+ String *fs = NewString("");
+ FILE *df = Swig_open(input_file);
+ if (!df) {
+ char *cfile = Char(input_file);
+ if (cfile && cfile[0] == '-') {
+ Printf(stderr, "Unable to find option or file '%s', ", input_file);
+ Printf(stderr, "Use 'swig -help' for more information.\n");
+ } else {
+ Printf(stderr, "Unable to find file '%s'.\n", input_file);
+ }
+ Exit(EXIT_FAILURE);
+ }
+
+ if (!tlm) {
+ Printf(stderr, "No target language specified.\n");
+ Printf(stderr, "Use 'swig -help' for more information.\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ if (!no_cpp) {
+ fclose(df);
+ Printf(fs, "%%include <swig.swg>\n");
+ if (allkw) {
+ Printf(fs, "%%include <allkw.swg>\n");
+ }
+ if (lang_config) {
+ Printf(fs, "\n%%include <%s>\n", lang_config);
+ }
+ Printf(fs, "%%include(maininput=\"%s\") \"%s\"\n", Swig_filename_escape(input_file), Swig_filename_escape(Swig_last_file()));
+ for (i = 0; i < Len(libfiles); i++) {
+ Printf(fs, "\n%%include \"%s\"\n", Swig_filename_escape(Getitem(libfiles, i)));
+ }
+ Seek(fs, 0, SEEK_SET);
+ cpps = Preprocessor_parse(fs);
+ Delete(fs);
+ } else {
+ cpps = Swig_read_file(df);
+ fclose(df);
+ }
+ if (Swig_error_count()) {
+ Exit(EXIT_FAILURE);
+ }
+ if (cpp_only) {
+ Printf(stdout, "%s", cpps);
+ Exit(EXIT_SUCCESS);
+ }
+ if (depend) {
+ if (!no_cpp) {
+ String *outfile;
+ File *f_dependencies_file = 0;
+
+ String *inputfile_filename = outcurrentdir ? Swig_file_filename(input_file): Copy(input_file);
+ String *basename = Swig_file_basename(inputfile_filename);
+ if (!outfile_name) {
+ if (CPlusPlus || lang->cplus_runtime_mode()) {
+ outfile = NewStringf("%s_wrap.%s", basename, cpp_extension);
+ } else {
+ outfile = NewStringf("%s_wrap.c", basename);
+ }
+ } else {
+ outfile = NewString(outfile_name);
+ }
+ if (dependencies_file && Len(dependencies_file) != 0) {
+ f_dependencies_file = NewFile(dependencies_file, "w", SWIG_output_files());
+ if (!f_dependencies_file) {
+ FileErrorDisplay(dependencies_file);
+ Exit(EXIT_FAILURE);
+ }
+ } else if (!depend_only) {
+ String *filename = NewStringf("%s_wrap.%s", basename, depends_extension);
+ f_dependencies_file = NewFile(filename, "w", SWIG_output_files());
+ if (!f_dependencies_file) {
+ FileErrorDisplay(filename);
+ Exit(EXIT_FAILURE);
+ }
+ } else
+ f_dependencies_file = stdout;
+ if (dependencies_target) {
+ Printf(f_dependencies_file, "%s: ", Swig_filename_escape_space(dependencies_target));
+ } else {
+ Printf(f_dependencies_file, "%s: ", Swig_filename_escape_space(outfile));
+ }
+ List *files = Preprocessor_depend();
+ List *phony_targets = NewList();
+ for (int i = 0; i < Len(files); i++) {
+ int use_file = 1;
+ if (depend == 2) {
+ if ((Strncmp(Getitem(files, i), SwigLib, Len(SwigLib)) == 0) || (SwigLibWinUnix && (Strncmp(Getitem(files, i), SwigLibWinUnix, Len(SwigLibWinUnix)) == 0)))
+ use_file = 0;
+ }
+ if (use_file) {
+ Printf(f_dependencies_file, "\\\n %s ", Swig_filename_escape_space(Getitem(files, i)));
+ if (depend_phony)
+ Append(phony_targets, Getitem(files, i));
+ }
+ }
+ Printf(f_dependencies_file, "\n");
+ if (depend_phony) {
+ for (int i = 0; i < Len(phony_targets); i++) {
+ Printf(f_dependencies_file, "\n%s:\n", Swig_filename_escape_space(Getitem(phony_targets, i)));
+ }
+ }
+
+ if (f_dependencies_file != stdout)
+ Delete(f_dependencies_file);
+ if (depend_only)
+ Exit(EXIT_SUCCESS);
+ Delete(inputfile_filename);
+ Delete(basename);
+ Delete(phony_targets);
+ } else {
+ Printf(stderr, "Cannot generate dependencies with -nopreprocess\n");
+ // Actually we could but it would be inefficient when just generating dependencies, as it would be done after Swig_cparse
+ Exit(EXIT_FAILURE);
+ }
+ }
+ Seek(cpps, 0, SEEK_SET);
+ }
+
+ /* Register a null file with the file handler */
+ Swig_register_filebyname("null", NewString(""));
+
+ // Pass control over to the specific language interpreter
+ if (Verbose) {
+ fprintf(stdout, "Starting language-specific parse...\n");
+ fflush(stdout);
+ }
+
+ Node *top = Swig_cparse(cpps);
+
+ if (dump_top & STAGE1) {
+ Printf(stdout, "debug-top stage 1\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE1) {
+ 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);
+ }
+ Swig_extend_unused_check();
+
+ if (Verbose) {
+ Printf(stdout, "Processing types...\n");
+ }
+ Swig_process_types(top);
+
+ if (dump_top & STAGE2) {
+ Printf(stdout, "debug-top stage 2\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE2) {
+ Printf(stdout, "debug-module stage 2\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+
+ if (Verbose) {
+ Printf(stdout, "C++ analysis...\n");
+ }
+ 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);
+ }
+ if (top && (dump_module & STAGE3)) {
+ Printf(stdout, "debug-module stage 3\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+
+ if (Verbose) {
+ Printf(stdout, "Generating wrappers...\n");
+ }
+
+ if (top && dump_classes) {
+ Hash *classes = Getattr(top, "classes");
+ if (classes) {
+ Printf(stdout, "Classes\n");
+ Printf(stdout, "------------\n");
+ Iterator ki;
+ for (ki = First(classes); ki.key; ki = Next(ki)) {
+ Printf(stdout, "%s\n", ki.key);
+ }
+ }
+ }
+
+ if (dump_typedef) {
+ SwigType_print_scope();
+ }
+
+ if (dump_symtabs) {
+ Swig_symbol_print_tables(Swig_symbol_global_scope());
+ Swig_symbol_print_tables_summary();
+ }
+
+ if (dump_symbols) {
+ Swig_symbol_print_symbols();
+ }
+
+ if (dump_csymbols) {
+ Swig_symbol_print_csymbols();
+ }
+
+ if (dump_tags) {
+ Swig_print_tags(top, 0);
+ }
+ if (top) {
+ if (!Getattr(top, "name")) {
+ Printf(stderr, "No module name specified using %%module or -module.\n");
+ Exit(EXIT_FAILURE);
+ } else {
+ /* Set some filename information on the object */
+ String *infile = scanner_get_main_input_file();
+ if (!infile) {
+ Printf(stderr, "Missing input file in preprocessed output.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Setattr(top, "infile", infile); // Note: if nopreprocess then infile is the original input file, otherwise input_file
+ Setattr(top, "inputfile", input_file);
+
+ String *infile_filename = outcurrentdir ? Swig_file_filename(infile): Copy(infile);
+ String *basename = Swig_file_basename(infile_filename);
+ if (!outfile_name) {
+ if (CPlusPlus || lang->cplus_runtime_mode()) {
+ Setattr(top, "outfile", NewStringf("%s_wrap.%s", basename, cpp_extension));
+ } else {
+ Setattr(top, "outfile", NewStringf("%s_wrap.c", basename));
+ }
+ } else {
+ Setattr(top, "outfile", outfile_name);
+ }
+ if (!outfile_name_h) {
+ Setattr(top, "outfile_h", NewStringf("%s_wrap.%s", basename, hpp_extension));
+ } else {
+ Setattr(top, "outfile_h", outfile_name_h);
+ }
+ configure_outdir(Getattr(top, "outfile"));
+ if (Swig_contract_mode_get()) {
+ Swig_contracts(top);
+ }
+
+ // Check the extension for a c/c++ file. If so, we're going to declare everything we see as "extern"
+ ForceExtern = check_extension(input_file);
+
+ if (tlm->status == Experimental) {
+ Swig_warning(WARN_LANG_EXPERIMENTAL, "SWIG", 1, "Experimental target language. "
+ "Target language %s specified by %s is an experimental language. "
+ "See the 'Target Languages' section in the Introduction chapter of the SWIG documentation.\n",
+ tlm->help ? tlm->help : "", tlm->name);
+ } else if (tlm->status == Deprecated) {
+ Swig_warning(WARN_LANG_DEPRECATED, "SWIG", 1, "Deprecated target language. "
+ "Target language %s specified by %s is a deprecated target language. "
+ "It will be removed in the next release of SWIG unless a new maintainer steps forward to bring it up to at least experimental status. "
+ "See the 'Target Languages' section in the Introduction chapter of the SWIG documentation.\n",
+ tlm->help ? tlm->help : "", tlm->name);
+ }
+
+ lang->top(top);
+
+ Delete(infile_filename);
+ Delete(basename);
+ }
+ }
+ if (dump_lang_symbols) {
+ lang->dumpSymbols();
+ }
+ if (dump_top & STAGE4) {
+ Printf(stdout, "debug-top stage 4\n");
+ Swig_print_tree(top);
+ }
+ if (dump_module & STAGE4) {
+ Printf(stdout, "debug-module stage 4\n");
+ Swig_print_tree(Getattr(top, "module"));
+ }
+ if (xmlout && top) {
+ delete lang;
+ lang = 0;
+ Swig_print_xml(top, xmlout);
+ }
+ Delete(top);
+ }
+ if (tm_debug)
+ Swig_typemap_debug();
+ if (memory_debug)
+ DohMemoryDebug();
+
+ char *outfiles = getenv("CCACHE_OUTFILES");
+ if (outfiles) {
+ File *f_outfiles = NewFile(outfiles, "w", 0);
+ if (!f_outfiles) {
+ Printf(stderr, "Failed to write list of output files to the filename '%s' specified in CCACHE_OUTFILES environment variable - ", outfiles);
+ FileErrorDisplay(outfiles);
+ Exit(EXIT_FAILURE);
+ } else {
+ int i;
+ for (i = 0; i < Len(all_output_files); i++)
+ Printf(f_outfiles, "%s\n", Getitem(all_output_files, i));
+ Delete(f_outfiles);
+ }
+ }
+
+ // Deletes
+ Delete(libfiles);
+ Preprocessor_delete();
+
+ while (freeze) {
+ }
+
+ delete lang;
+
+ int error_count = werror ? Swig_warn_count() : 0;
+ error_count += Swig_error_count();
+
+ if (error_count != 0)
+ Exit(EXIT_FAILURE);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SWIG_exit_handler()
+ *
+ * Cleanup and either freeze or exit
+ * ----------------------------------------------------------------------------- */
+
+static void SWIG_exit_handler(int status) {
+ while (freeze) {
+ }
+
+ if (status > 0) {
+ CloseAllOpenFiles();
+
+ /* Remove all generated files */
+ if (all_output_files) {
+ for (int i = 0; i < Len(all_output_files); i++) {
+ String *filename = Getitem(all_output_files, i);
+ int removed = remove(Char(filename));
+ if (removed == -1)
+ fprintf(stderr, "On exit, could not delete file %s: %s\n", Char(filename), strerror(errno));
+ }
+ }
+ }
+}
diff --git a/contrib/tools/swig/Source/Modules/mzscheme.cxx b/contrib/tools/swig/Source/Modules/mzscheme.cxx
new file mode 100644
index 00000000000..c8c845f242b
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/mzscheme.cxx
@@ -0,0 +1,761 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * mzscheme.cxx
+ *
+ * Mzscheme language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <ctype.h>
+
+static const char *usage = "\
+Mzscheme Options (available with -mzscheme)\n\
+ -declaremodule - Create extension that declares a module\n\
+ -dynamic-load <lib>,[lib,...] - Do not link with these libraries, dynamic load them\n\
+ -noinit - Do not emit module initialization code\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+";
+
+static String *fieldnames_tab = 0;
+static String *convert_tab = 0;
+static String *convert_proto_tab = 0;
+static String *struct_name = 0;
+static String *mangled_struct_name = 0;
+
+static String *prefix = 0;
+static bool declaremodule = false;
+static bool noinit = false;
+static String *load_libraries = NULL;
+static String *module = 0;
+static const char *mzscheme_path = "mzscheme";
+static String *init_func_def = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_init = 0;
+
+// Used for garbage collection
+static int exporting_destructor = 0;
+static String *swigtype_ptr = 0;
+static String *cls_swigtype = 0;
+
+class MZSCHEME:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ int i;
+
+ SWIG_library_directory(mzscheme_path);
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-declaremodule") == 0) {
+ declaremodule = true;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noinit") == 0) {
+ noinit = true;
+ Swig_mark_arg(i);
+ }
+ else if (strcmp(argv[i], "-dynamic-load") == 0) {
+ if (argv[i + 1]) {
+ Delete(load_libraries);
+ load_libraries = NewString(argv[i + 1]);
+ Swig_mark_arg(i++);
+ Swig_mark_arg(i);
+ } else {
+ Swig_arg_error();
+ }
+ }
+ }
+ }
+
+ // If a prefix has been specified make sure it ends in a '_' (not actually used!)
+ if (prefix) {
+ const char *px = Char(prefix);
+ if (px[Len(prefix) - 1] != '_')
+ Printf(prefix, "_");
+ } else
+ prefix = NewString("swig_");
+
+ // Add a symbol for this module
+
+ Preprocessor_define("SWIGMZSCHEME 1", 0);
+
+ // Read in default typemaps */
+ SWIG_config_file("mzscheme.swg");
+ allow_overloading();
+
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+
+ init_func_def = NewString("");
+ Swig_register_filebyname("init", init_func_def);
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "MZSCHEME");
+
+ module = Getattr(n, "name");
+
+ Language::top(n);
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+ if (!noinit) {
+ if (declaremodule) {
+ Printf(f_init, "#define SWIG_MZSCHEME_CREATE_MENV(env) scheme_primitive_module(scheme_intern_symbol(\"%s\"), env)\n", module);
+ } else {
+ Printf(f_init, "#define SWIG_MZSCHEME_CREATE_MENV(env) (env)\n");
+ }
+ Printf(f_init, "%s\n", Char(init_func_def));
+ if (declaremodule) {
+ Printf(f_init, "\tscheme_finish_primitive_module(menv);\n");
+ }
+ Printf(f_init, "\treturn scheme_void;\n}\n");
+ Printf(f_init, "Scheme_Object *scheme_initialize(Scheme_Env *env) {\n");
+
+ if (load_libraries) {
+ Printf(f_init, "mz_set_dlopen_libraries(\"%s\");\n", load_libraries);
+ }
+
+ Printf(f_init, "\treturn scheme_reload(env);\n");
+ Printf(f_init, "}\n");
+
+ Printf(f_init, "Scheme_Object *scheme_module_name(void) {\n");
+ if (declaremodule) {
+ Printf(f_init, " return scheme_intern_symbol((char*)\"%s\");\n", module);
+ } else {
+ Printf(f_init, " return scheme_make_symbol((char*)\"%s\");\n", module);
+ }
+ Printf(f_init, "}\n");
+ }
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * Create a function declaration and register it with the interpreter.
+ * ------------------------------------------------------------ */
+
+ void throw_unhandled_mzscheme_type_error(SwigType *d) {
+ Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, "Unable to handle type %s.\n", SwigType_str(d, 0));
+ }
+
+ /* Return true iff T is a pointer type */
+
+ int
+ is_a_pointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+ }
+
+ virtual int functionWrapper(Node *n) {
+ char *iname = GetChar(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+
+ Wrapper *f = NewWrapper();
+ String *proc_name = NewString("");
+ String *target = NewString("");
+ String *arg = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *build = NewString("");
+ String *tm;
+ int i = 0;
+ int numargs;
+ int numreq;
+ String *overname = 0;
+
+ if (load_libraries) {
+ ParmList *parms = Getattr(n, "parms");
+ SwigType *type = Getattr(n, "type");
+ String *name = NewString("caller");
+ Setattr(n, "wrap:action", Swig_cresult(type, Swig_cresult_name(), Swig_cfunction_call(name, parms)));
+ }
+
+ // Make a wrapper name for this
+ String *wname = Swig_name_wrapper(iname);
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ // Build the name for Scheme.
+ Printv(proc_name, iname, NIL);
+ Replaceall(proc_name, "_", "-");
+
+ // writing the function wrapper function
+ Printv(f->def, "static Scheme_Object *", wname, " (", NIL);
+ Printv(f->def, "int argc, Scheme_Object **argv", NIL);
+ Printv(f->def, ")\n{", NIL);
+
+ /* Define the scheme name in C. This define is used by several
+ macros. */
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ numargs = emit_num_arguments(l);
+ numreq = emit_num_required(l);
+
+ /* Add the holder for the pointer to the function to be opened */
+ if (load_libraries) {
+ Wrapper_add_local(f, "_function_loaded", "static int _function_loaded=(1==0)");
+ Wrapper_add_local(f, "_the_function", "static void *_the_function=NULL");
+ {
+ String *parms = ParmList_protostr(l);
+ String *func = NewStringf("(*caller)(%s)", parms);
+ Wrapper_add_local(f, "caller", SwigType_lstr(returntype, func));
+ }
+ }
+
+ // adds local variables
+ Wrapper_add_local(f, "lenv", "int lenv = 1");
+ Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]");
+
+ if (load_libraries) {
+ Printf(f->code, "if (!_function_loaded) { _the_function=mz_load_function(\"%s\");_function_loaded=(1==1); }\n", iname);
+ Printf(f->code, "if (!_the_function) { scheme_signal_error(\"Cannot load C function '%s'\"); }\n", iname);
+ Printf(f->code, "caller=_the_function;\n");
+ }
+
+ // Now write code to extract the parameters (this is super ugly)
+
+ for (i = 0, p = l; i < numargs; i++) {
+ /* Skip ignored arguments */
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ // Produce names of source and target
+ Clear(target);
+ Clear(arg);
+ String *source = NewStringf("argv[%d]", i);
+ Printf(target, "%s", ln);
+ Printv(arg, Getattr(p, "name"), NIL);
+
+ if (i >= numreq) {
+ Printf(f->code, "if (argc > %d) {\n", i);
+ }
+ // Handle parameter types.
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ // no typemap found
+ // check if typedef and resolve
+ throw_unhandled_mzscheme_type_error(pt);
+ p = nextSibling(p);
+ }
+ if (i >= numreq) {
+ Printf(f->code, "}\n");
+ }
+ Delete(source);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Pass output arguments back to the caller.
+
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Free up any memory allocated for the arguments.
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Now write code to make the function call
+
+ String *actioncode = emit_action(n);
+
+ // Now have return value, figure out what to do with it.
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$result", "values[0]");
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+ Printv(f->code, tm, "\n", NIL);
+ } else {
+ throw_unhandled_mzscheme_type_error(returntype);
+ }
+ emit_return_variable(n, returntype, f);
+
+ // Dump the argument output code
+ Printv(f->code, Char(outarg), NIL);
+
+ // Dump the argument cleanup code
+ Printv(f->code, Char(cleanup), NIL);
+
+ // Look for any remaining cleanup
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+ // Free any memory allocated by the function being wrapped..
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ // Wrap things up (in a manner of speaking)
+
+ Printv(f->code, tab4, "return SWIG_MzScheme_PackageValues(lenv, values);\n", NIL);
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printv(f->code, "}\n", NIL);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+
+ Wrapper_print(f, f_wrappers);
+
+ if (!Getattr(n, "sym:overloaded")) {
+
+ // Now register the function
+ char temp[256];
+ sprintf(temp, "%d", numargs);
+ if (exporting_destructor) {
+ Printf(init_func_def, "SWIG_TypeClientData(SWIGTYPE%s, (void *) %s);\n", swigtype_ptr, wname);
+ }
+ Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, wname, proc_name, numreq, numargs);
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ /* Emit overloading dispatch function */
+
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(argc,argv);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "static Scheme_Object *\n", dname, "(int argc, Scheme_Object **argv) {", NIL);
+ Printv(df->code, dispatch, "\n", NIL);
+ Printf(df->code, "scheme_signal_error(\"No matching function for overloaded '%s'\");\n", iname);
+ Printf(df->code, "return NULL;\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printf(init_func_def, "scheme_add_global(\"%s\", scheme_make_prim_w_arity(%s,\"%s\",%d,%d),menv);\n", proc_name, dname, proc_name, 0, maxargs);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ }
+
+ Delete(proc_name);
+ Delete(target);
+ Delete(arg);
+ Delete(outarg);
+ Delete(cleanup);
+ Delete(build);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ *
+ * Create a link to a C variable.
+ * This creates a single function _wrap_swig_var_varname().
+ * This function takes a single optional argument. If supplied, it means
+ * we are setting this variable to some value. If omitted, it means we are
+ * simply evaluating this variable. Either way, we return the variables
+ * value.
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ String *proc_name = NewString("");
+ String *tm;
+ String *tm2 = NewString("");
+ String *argnum = NewString("0");
+ String *arg = NewString("argv[0]");
+ Wrapper *f;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ f = NewWrapper();
+
+ // evaluation function names
+ String *var_name = Swig_name_wrapper(iname);
+
+ // Build the name for scheme.
+ Printv(proc_name, iname, NIL);
+ Replaceall(proc_name, "_", "-");
+ Setattr(n, "wrap:name", proc_name);
+
+ if ((SwigType_type(t) != T_USER) || (is_a_pointer(t))) {
+
+ Printf(f->def, "static Scheme_Object *%s(int argc, Scheme_Object** argv) {\n", var_name);
+ Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ Wrapper_add_local(f, "swig_result", "Scheme_Object *swig_result");
+
+ if (!GetFlag(n, "feature:immutable")) {
+ /* Check for a setting of the variable value */
+ Printf(f->code, "if (argc) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$input", "argv[0]");
+ Replaceall(tm, "$argnum", "1");
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_mzscheme_type_error(t);
+ }
+ Printf(f->code, "}\n");
+ }
+ // Now return the value of the variable (regardless
+ // of evaluating or setting)
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "swig_result");
+ /* Printf (f->code, "%s\n", tm); */
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_mzscheme_type_error(t);
+ }
+ Printf(f->code, "\nreturn swig_result;\n");
+ Printf(f->code, "#undef FUNC_NAME\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ // Now add symbol to the MzScheme interpreter
+
+ Printv(init_func_def,
+ "scheme_add_global(\"", proc_name, "\", scheme_make_prim_w_arity(", var_name, ", \"", proc_name, "\", ", "0", ", ", "1", "), menv);\n", NIL);
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
+ }
+ Delete(var_name);
+ Delete(proc_name);
+ Delete(argnum);
+ Delete(arg);
+ Delete(tm2);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+
+ String *tm;
+
+ if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ // See if there's a typemap
+ if ((tm = Swig_typemap_lookup("constant", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ // Create a static variable and assign it a value
+ String *var_name = NewStringf("_wrap_const_%s", Swig_name_mangle_string(Getattr(n, "sym:name")));
+ Printf(f_header, "static %s = %s;\n", SwigType_lstr(type, var_name), value);
+
+ // Now create a variable declaration
+
+ {
+ /* Hack alert: will cleanup later -- Dave */
+ Node *nn = NewHash();
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ Setattr(nn, "name", var_name);
+ Setattr(nn, "sym:name", iname);
+ Setattr(nn, "type", type);
+ SetFlag(nn, "feature:immutable");
+ variableWrapper(nn);
+ Delete(nn);
+ }
+ Delete(var_name);
+ }
+ return SWIG_OK;
+ }
+
+ virtual int destructorHandler(Node *n) {
+ exporting_destructor = true;
+ Language::destructorHandler(n);
+ exporting_destructor = false;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+ virtual int classHandler(Node *n) {
+ String *scm_structname = NewString("");
+ SwigType *ctype_ptr = NewStringf("p.%s", getClassType());
+
+ SwigType *t = NewStringf("p.%s", Getattr(n, "name"));
+ swigtype_ptr = SwigType_manglestr(t);
+ Delete(t);
+
+ cls_swigtype = SwigType_manglestr(Getattr(n, "name"));
+
+
+ fieldnames_tab = NewString("");
+ convert_tab = NewString("");
+ convert_proto_tab = NewString("");
+
+ struct_name = Getattr(n, "sym:name");
+ mangled_struct_name = Swig_name_mangle_string(Getattr(n, "sym:name"));
+
+ Printv(scm_structname, struct_name, NIL);
+ Replaceall(scm_structname, "_", "-");
+
+ Printv(fieldnames_tab, "static const char *_swig_struct_", cls_swigtype, "_field_names[] = { \n", NIL);
+
+ Printv(convert_proto_tab, "static Scheme_Object *_swig_convert_struct_", cls_swigtype, "(", SwigType_str(ctype_ptr, "ptr"), ");\n", NIL);
+
+ Printv(convert_tab, "static Scheme_Object *_swig_convert_struct_", cls_swigtype, "(", SwigType_str(ctype_ptr, "ptr"), ")\n {\n", NIL);
+
+ Printv(convert_tab,
+ tab4, "Scheme_Object *obj;\n", tab4, "Scheme_Object *fields[_swig_struct_", cls_swigtype, "_field_names_cnt];\n", tab4, "int i = 0;\n\n", NIL);
+
+ /* Generate normal wrappers */
+ Language::classHandler(n);
+
+ Printv(convert_tab, tab4, "obj = scheme_make_struct_instance(", "_swig_struct_type_", cls_swigtype, ", i, fields);\n", NIL);
+ Printv(convert_tab, tab4, "return obj;\n}\n\n", NIL);
+
+ Printv(fieldnames_tab, "};\n", NIL);
+
+ Printv(f_header, "static Scheme_Object *_swig_struct_type_", cls_swigtype, ";\n", NIL);
+
+ Printv(f_header, fieldnames_tab, NIL);
+ Printv(f_header, "#define _swig_struct_", cls_swigtype, "_field_names_cnt (sizeof(_swig_struct_", cls_swigtype, "_field_names)/sizeof(char*))\n", NIL);
+
+ Printv(f_header, convert_proto_tab, NIL);
+ Printv(f_wrappers, convert_tab, NIL);
+
+ Printv(init_func_def, "_swig_struct_type_", cls_swigtype,
+ " = SWIG_MzScheme_new_scheme_struct(menv, \"", scm_structname, "\", ",
+ "_swig_struct_", cls_swigtype, "_field_names_cnt,", "(char**) _swig_struct_", cls_swigtype, "_field_names);\n", NIL);
+
+ Delete(swigtype_ptr);
+ swigtype_ptr = 0;
+ Delete(fieldnames_tab);
+ Delete(convert_tab);
+ Delete(ctype_ptr);
+ Delete(convert_proto_tab);
+ struct_name = 0;
+ mangled_struct_name = 0;
+ Delete(cls_swigtype);
+ cls_swigtype = 0;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ Language::membervariableHandler(n);
+
+ if (!is_smart_pointer()) {
+ String *symname = Getattr(n, "sym:name");
+ String *name = Getattr(n, "name");
+ SwigType *type = Getattr(n, "type");
+ String *swigtype = SwigType_manglestr(Getattr(n, "type"));
+ String *tm = 0;
+ String *access_mem = NewString("");
+ SwigType *ctype_ptr = NewStringf("p.%s", Getattr(n, "type"));
+
+ Printv(fieldnames_tab, tab4, "\"", symname, "\",\n", NIL);
+ Printv(access_mem, "(ptr)->", name, NIL);
+ if ((SwigType_type(type) == T_USER) && (!is_a_pointer(type))) {
+ Printv(convert_tab, tab4, "fields[i++] = ", NIL);
+ Printv(convert_tab, "_swig_convert_struct_", swigtype, "((", SwigType_str(ctype_ptr, 0), ")&((ptr)->", name, "));\n", NIL);
+ } else if ((tm = Swig_typemap_lookup("varout", n, access_mem, 0))) {
+ Replaceall(tm, "$result", "fields[i++]");
+ Printv(convert_tab, tm, "\n", NIL);
+ } else
+ Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported member variable type %s (ignored).\n", SwigType_str(type, 0));
+
+ Delete(access_mem);
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ /* Check whether we have an R5RS identifier. */
+ /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */
+ /* <initial> --> <letter> | <special initial> */
+ if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~'))) {
+ /* <peculiar identifier> --> + | - | ... */
+ if ((strcmp(c, "+") == 0)
+ || strcmp(c, "-") == 0 || strcmp(c, "...") == 0)
+ return 1;
+ else
+ return 0;
+ }
+ /* <subsequent> --> <initial> | <digit> | <special subsequent> */
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%')
+ || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
+ || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
+ || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+')
+ || (*c == '-') || (*c == '.') || (*c == '@')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ String *runtimeCode() {
+ String *s = Swig_include_sys("mzrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'mzrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigmzrun.h");
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_mzscheme() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_mzscheme() {
+ return new MZSCHEME();
+}
+extern "C" Language *swig_mzscheme(void) {
+ return new_swig_mzscheme();
+}
diff --git a/contrib/tools/swig/Source/Modules/nested.cxx b/contrib/tools/swig/Source/Modules/nested.cxx
new file mode 100644
index 00000000000..1f62e0d1c3b
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/nested.cxx
@@ -0,0 +1,406 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * 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) {
+ 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 {
+ int inclass = 1;
+ Swig_symbol_conflict_warn(n, c, symname, inclass);
+ }
+ }
+ }
+ 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 (!n)
+ return;
+ 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);
+
+ // Merge the extension into the symbol table
+ if (Node *am = Getattr(Swig_extend_hash(), name)) {
+ Swig_extend_merge(c, am);
+ Swig_extend_append_previous(c, am);
+ Delattr(Swig_extend_hash(), name);
+ }
+ 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);
+ 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 and its instances
+ SetFlag(c, "feature:ignore");
+ while (next && Getattr(next, "nested:unnamedtype") == c) {
+ SetFlag(next, "feature:ignore");
+ next = nextSibling(next);
+ }
+ 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") || Language::instance()->nestedClassesSupport() == Language::NCS_None) {
+ Delattr(c, "nested:outer");
+ remove_outer_class_reference(c);
+ }
+ }
+}
+
+void Swig_nested_process_classes(Node *n) {
+ if (!n)
+ return;
+ Node *c = firstChild(n);
+ while (c) {
+ Node *next = nextSibling(c);
+ if (!Getattr(c, "templatetype")) {
+ if (GetFlag(c, "nested") && (GetFlag(c, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None)) {
+ removeNode(c);
+ if (!checkAttribute(c, "access", "public"))
+ SetFlag(c, "feature:ignore");
+ else if (Strcmp(nodeType(n),"extend") == 0 && Strcmp(nodeType(parentNode(n)),"class") == 0)
+ insertNodeAfter(parentNode(n), c);
+ else
+ insertNodeAfter(n, c);
+ }
+ Swig_nested_process_classes(c);
+ }
+ c = next;
+ }
+ remove_outer_class_reference(n);
+}
+
diff --git a/contrib/tools/swig/Source/Modules/ocaml.cxx b/contrib/tools/swig/Source/Modules/ocaml.cxx
new file mode 100644
index 00000000000..ce80eb0bbe2
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/ocaml.cxx
@@ -0,0 +1,1837 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * ocaml.cxx
+ *
+ * Ocaml language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <ctype.h>
+
+static const char *usage = "\
+Ocaml Options (available with -ocaml)\n\
+ -oldvarnames - Old intermediary method names for variable wrappers\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+ -where - Emit library location\n\
+\n";
+
+static int classmode = 0;
+static int in_constructor = 0, in_destructor = 0, in_copyconst = 0;
+static int const_enum = 0;
+static int static_member_function = 0;
+static int generate_sizeof = 0;
+static String *prefix = 0;
+static const char *ocaml_path = "ocaml";
+static bool old_variable_names = false;
+static String *classname = 0;
+static String *module = 0;
+static String *init_func_def = 0;
+static String *f_classtemplate = 0;
+static SwigType *name_qualifier_type = 0;
+
+static Hash *seen_enums = 0;
+static Hash *seen_enumvalues = 0;
+static Hash *seen_constructors = 0;
+
+static File *f_header = 0;
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_wrappers = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static File *f_init = 0;
+static File *f_mlout = 0;
+static File *f_mliout = 0;
+static File *f_mlbody = 0;
+static File *f_mlibody = 0;
+static File *f_mltail = 0;
+static File *f_mlitail = 0;
+static File *f_enumtypes_type = 0;
+static File *f_enumtypes_value = 0;
+static File *f_class_ctors = 0;
+static File *f_class_ctors_end = 0;
+static File *f_enum_to_int = 0;
+static File *f_int_to_enum = 0;
+
+class OCAML:public Language {
+public:
+
+ OCAML() {
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n", "} else {\n", " caml_failwith(\"accessing abstract class or protected constructor\"); \n", "}\n", NIL);
+ director_multiple_inheritance = 1;
+ directorLanguage();
+ }
+
+ String *Swig_class_name(Node *n) {
+ String *name;
+ name = Copy(Getattr(n, "sym:name"));
+ return name;
+ }
+
+ void PrintIncludeArg() {
+ Printv(stdout, SWIG_LIB, SWIG_FILE_DELIMITER, ocaml_path, "\n", NIL);
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i;
+
+ prefix = 0;
+
+ SWIG_library_directory(ocaml_path);
+
+ // Look for certain command line options
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-where") == 0) {
+ PrintIncludeArg();
+ Exit(EXIT_SUCCESS);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-oldvarnames") == 0) {
+ Swig_mark_arg(i);
+ old_variable_names = true;
+ }
+ }
+ }
+
+ // If a prefix has been specified make sure it ends in a '_' (not actually used!)
+ if (prefix) {
+ const char *px = Char(prefix);
+ if (px[Len(prefix) - 1] != '_')
+ Printf(prefix, "_");
+ } else
+ prefix = NewString("swig_");
+
+ // Add a symbol for this module
+
+ Preprocessor_define("SWIGOCAML 1", 0);
+
+ // Read in default typemaps */
+ SWIG_config_file("ocaml.i");
+ allow_overloading();
+
+ }
+
+ /* Swig_director_declaration()
+ *
+ * Generate the full director class declaration, complete with base classes.
+ * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
+ *
+ */
+
+ String *Swig_director_declaration(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *directorname = NewStringf("SwigDirector_%s", classname);
+ String *base = Getattr(n, "classtype");
+ String *declaration = Swig_class_declaration(n, directorname);
+ Printf(declaration, " : public %s, public Swig::Director {\n", base);
+ Delete(classname);
+ Delete(directorname);
+ return declaration;
+ }
+
+ void emitBanner(File *f) {
+ Printf(f, "(* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ---------------------------------------------------------------------------- *)\n\n");
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ *
+ * Recognize the %module, and capture the module name.
+ * Create the default enum cases.
+ * Set up the named outputs:
+ *
+ * init
+ * ml
+ * mli
+ * wrapper
+ * header
+ * runtime
+ * directors
+ * directors_h
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* Set comparison with none for ConstructorToFunction */
+ setSubclassInstanceCheck(NewString("caml_list_nth(args,0) != Val_unit"));
+
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ String *mod_docstring = NULL;
+ {
+ Node *module = Getattr(n, "module");
+ if (module) {
+ Node *options = Getattr(module, "options");
+ if (options) {
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(options, "dirprot")) {
+ allow_dirprot();
+ }
+ if (Getattr(options, "sizeof")) {
+ generate_sizeof = 1;
+ }
+ mod_docstring = Getattr(options, "docstring");
+ }
+ }
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors = NewString("");
+ f_directors_h = NewString("");
+ f_enumtypes_type = NewString("");
+ f_enumtypes_value = NewString("");
+ init_func_def = NewString("");
+ f_mlbody = NewString("");
+ f_mlibody = NewString("");
+ f_mltail = NewString("");
+ f_mlitail = NewString("");
+ f_class_ctors = NewString("");
+ f_class_ctors_end = NewString("");
+ f_enum_to_int = NewString("");
+ f_int_to_enum = NewString("");
+ f_classtemplate = NewString("");
+
+ module = Getattr(n, "name");
+
+ seen_constructors = NewHash();
+ seen_enums = NewHash();
+ seen_enumvalues = NewHash();
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("init", init_func_def);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("mli", f_mlibody);
+ Swig_register_filebyname("ml", f_mlbody);
+ Swig_register_filebyname("mlitail", f_mlitail);
+ Swig_register_filebyname("mltail", f_mltail);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+ Swig_register_filebyname("classtemplate", f_classtemplate);
+ Swig_register_filebyname("class_ctors", f_class_ctors);
+
+ if (old_variable_names) {
+ Swig_name_register("set", "%n%v__set__");
+ Swig_name_register("get", "%n%v__get__");
+ }
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "OCAML");
+
+ Printf(f_runtime, "#define SWIG_MODULE \"%s\"\n", module);
+ /* Module name */
+ Printf(f_mlbody, "let module_name = \"%s\"\n", module);
+ Printf(f_mlibody, "val module_name : string\n");
+ Printf(f_enum_to_int,
+ "let enum_to_int x (v : c_obj) =\n"
+ " match v with\n"
+ " C_enum _y ->\n"
+ " (let y = _y in match (x : c_enum_type) with\n"
+ " `unknown -> " " (match y with\n" " `Int x -> (Swig.C_int x)\n" " | _ -> raise (LabelNotFromThisEnum v))\n");
+
+ Printf(f_int_to_enum, "let int_to_enum x y =\n" " match (x : c_enum_type) with\n" " `unknown -> C_enum (`Int y)\n");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ /* Produce the enum_to_int and int_to_enum functions */
+
+ Printf(f_enumtypes_type, "open Swig\n" "type c_enum_type = [ \n `unknown\n");
+ Printf(f_enumtypes_value, "type c_enum_value = [ \n `Int of int\n");
+ String *mlfile = NewString("");
+ String *mlifile = NewString("");
+
+ Printv(mlfile, module, ".ml", NIL);
+ Printv(mlifile, module, ".mli", NIL);
+
+ String *mlfilen = NewStringf("%s%s", SWIG_output_directory(), mlfile);
+ if ((f_mlout = NewFile(mlfilen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(mlfilen);
+ Exit(EXIT_FAILURE);
+ }
+ String *mlifilen = NewStringf("%s%s", SWIG_output_directory(), mlifile);
+ if ((f_mliout = NewFile(mlifilen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(mlifilen);
+ Exit(EXIT_FAILURE);
+ }
+ emitBanner(f_mlout);
+ emitBanner(f_mliout);
+
+ Language::top(n);
+
+ if (mod_docstring) {
+ if (Len(mod_docstring)) {
+ Printv(f_mliout, "(** ", mod_docstring, " *)\n", NIL);
+ }
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ Printf(f_enum_to_int, ") | _ -> (C_int (get_int v))\n" "let _ = Callback.register \"%s_enum_to_int\" enum_to_int\n", module);
+ Printf(f_mlibody, "val enum_to_int : c_enum_type -> c_obj -> Swig.c_obj\n");
+
+ Printf(f_int_to_enum, "let _ = Callback.register \"%s_int_to_enum\" int_to_enum\n", module);
+ Printf(f_mlibody, "val int_to_enum : c_enum_type -> int -> c_obj\n");
+ Printf(f_init, "#define SWIG_init f_%s_init\n" "%s" "}\n", module, init_func_def);
+ Printf(f_mlbody, "external f_init : unit -> unit = \"f_%s_init\" ;;\n" "let _ = f_init ()\n", module);
+ Printf(f_enumtypes_type, "]\n");
+ Printf(f_enumtypes_value, "]\n\n" "type c_obj = c_enum_value c_obj_t\n");
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_directors_h, f_header);
+ Dump(f_header, f_begin);
+ Dump(f_directors, f_wrappers);
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ Dump(f_enumtypes_type, f_mlout);
+ Dump(f_enumtypes_value, f_mlout);
+ Dump(f_mlbody, f_mlout);
+ Dump(f_enum_to_int, f_mlout);
+ Dump(f_int_to_enum, f_mlout);
+ Delete(f_int_to_enum);
+ Delete(f_enum_to_int);
+ Dump(f_class_ctors, f_mlout);
+ Dump(f_class_ctors_end, f_mlout);
+ Dump(f_mltail, f_mlout);
+ Delete(f_mlout);
+
+ Dump(f_enumtypes_type, f_mliout);
+ Dump(f_enumtypes_value, f_mliout);
+ Dump(f_mlibody, f_mliout);
+ Dump(f_mlitail, f_mliout);
+ Delete(f_mliout);
+
+ return SWIG_OK;
+ }
+
+ /* Produce an error for the given type */
+ void throw_unhandled_ocaml_type_error(SwigType *d, const char *types) {
+ Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number, "Unable to handle type %s (%s).\n", SwigType_str(d, 0), types);
+ }
+
+ /* Return true iff T is a pointer type */
+ int
+ is_a_pointer(SwigType *t) {
+ return SwigType_ispointer(SwigType_typedef_resolve_all(t));
+ }
+
+ /*
+ * Delete one reference from a given type.
+ */
+
+ void oc_SwigType_del_reference(SwigType *t) {
+ if (SwigType_isqualifier(t)) {
+ SwigType_del_qualifier(t);
+ }
+ SwigType_del_reference(t);
+ }
+
+ void oc_SwigType_del_array(SwigType *t) {
+ if (SwigType_isqualifier(t)) {
+ SwigType_del_qualifier(t);
+ }
+ if (SwigType_isarray(t)) {
+ SwigType_del_array(t);
+ }
+ }
+
+ /*
+ * Return true iff T is a reference type
+ */
+
+ int
+ is_a_reference(SwigType *t) {
+ return SwigType_isreference(SwigType_typedef_resolve_all(t));
+ }
+
+ int
+ is_an_array(SwigType *t) {
+ return SwigType_isarray(SwigType_typedef_resolve_all(t));
+ }
+
+ virtual int membervariableHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ Language::membervariableHandler(n);
+
+ String *mname = Swig_name_member(NSPACE_TODO, classname, symname);
+ String *getname = Swig_name_get(NSPACE_TODO, mname);
+ String *mangled_getname = mangleNameForCaml(getname);
+ Delete(getname);
+
+ if (!GetFlag(n, "feature:immutable")) {
+ String *setname = Swig_name_set(NSPACE_TODO, mname);
+ String *mangled_setname = mangleNameForCaml(setname);
+ Delete(setname);
+ Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else _%s args) ;\n", symname, mangled_getname, mangled_setname);
+ Delete(mangled_setname);
+ } else {
+ Printf(f_class_ctors, " \"[%s]\", (fun args -> " "if args = (C_list [ raw_ptr ]) then _%s args else C_void) ;\n", symname, mangled_getname);
+ }
+ Delete(mangled_getname);
+ Delete(mname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * Create a function declaration and register it with the interpreter.
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ char *iname = GetChar(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ String *return_type_normalized = normalizeTemplatedClassName(returntype);
+ ParmList *l = Getattr(n, "parms");
+ int director_method = 0;
+ Parm *p;
+
+ Wrapper *f = NewWrapper();
+ String *proc_name = NewString("");
+ String *target = NewString("");
+ String *arg = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *build = NewString("");
+ String *tm;
+ int i = 0;
+ int numargs;
+ int numreq;
+ int newobj = GetFlag(n, "feature:new");
+ String *nodeType = Getattr(n, "nodeType");
+ int destructor = (!Cmp(nodeType, "destructor"));
+ String *overname = 0;
+ bool isOverloaded = Getattr(n, "sym:overloaded") ? true : false;
+ // For overloaded functions, only the dispatch function needs to be exposed in the ml and mli files.
+ bool expose_func = !isOverloaded || !Getattr(n, "sym:nextSibling");
+
+ // Make a wrapper name for this
+ String *wname = Swig_name_wrapper(iname);
+ if (isOverloaded) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n)) {
+ DelWrapper(f);
+ return SWIG_ERROR;
+ }
+ }
+ if (overname) {
+ Append(wname, overname);
+ }
+ /* Do this to disambiguate functions emitted from different modules */
+ Append(wname, module);
+
+ Setattr(n, "wrap:name", wname);
+
+ // Build the name for Scheme.
+ Printv(proc_name, "_", iname, NIL);
+ String *mangled_name = mangleNameForCaml(proc_name);
+
+ if (classmode && in_constructor && expose_func) { // Emit constructor for object
+ String *mangled_name_nounder = NewString((char *) (Char(mangled_name)) + 1);
+ Printf(f_class_ctors_end, "let %s clst = _%s clst\n", mangled_name_nounder, mangled_name_nounder);
+ Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name_nounder);
+ Delete(mangled_name_nounder);
+ } else if (classmode && in_destructor) {
+ Printf(f_class_ctors, " \"~\", %s ;\n", mangled_name);
+ } else if (classmode && !in_constructor && !in_destructor && !static_member_function &&
+ !Getattr(n, "membervariableHandler:sym:name") && expose_func) {
+ String *opname = Copy(Getattr(n, "memberfunctionHandler:sym:name"));
+
+ Replaceall(opname, "operator ", "");
+ Printf(f_class_ctors, " \"%s\", %s ;\n", opname, mangled_name);
+ Delete(opname);
+ }
+
+ if (classmode && in_constructor) {
+ Setattr(seen_constructors, mangled_name, "true");
+ }
+ // writing the function wrapper function
+ Printv(f->def, "SWIGEXT value ", wname, " (", NIL);
+ Printv(f->def, "value args", NIL);
+ Printv(f->def, ")\n{", NIL);
+
+ /* Define the scheme name in C. This define is used by several
+ macros. */
+ //Printv(f->def, "#define FUNC_NAME \"", mangled_name, "\"", NIL);
+
+ // adds local variables
+ Wrapper_add_local(f, "args", "CAMLparam1(args)");
+ Wrapper_add_local(f, "ret", "CAMLlocal2(swig_result,rv)");
+ returntype = SwigType_typedef_qualified(returntype);
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ numargs = emit_num_arguments(l);
+ numreq = emit_num_required(l);
+ if (!isOverloaded) {
+ if (numargs > 0) {
+ if (numreq > 0) {
+ Printf(f->code, "if (caml_list_length(args) < %d || caml_list_length(args) > %d) {\n", numreq, numargs);
+ } else {
+ Printf(f->code, "if (caml_list_length(args) > %d) {\n", numargs);
+ }
+ Printf(f->code, "caml_invalid_argument(\"Incorrect number of arguments passed to '%s'\");\n}\n", iname);
+ } else {
+ Printf(f->code, "if (caml_list_length(args) > 0) caml_invalid_argument(\"'%s' takes no arguments\");\n", iname);
+ }
+ }
+ Printf(f->code, "swig_result = Val_unit;\n");
+
+ // Now write code to extract the parameters (this is super ugly)
+
+ for (i = 0, p = l; i < numargs; i++) {
+ /* Skip ignored arguments */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ pt = SwigType_typedef_qualified(pt);
+
+ // Produce names of source and target
+ Clear(target);
+ Clear(arg);
+ String *source = NewStringf("caml_list_nth(args,%d)", i);
+ Printf(target, "%s", ln);
+ Printv(arg, Getattr(p, "name"), NIL);
+
+ if (i >= numreq) {
+ Printf(f->code, "if (caml_list_length(args) > %d) {\n", i);
+ }
+ // Handle parameter types.
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ // no typemap found
+ // check if typedef and resolve
+ throw_unhandled_ocaml_type_error(pt, "in");
+ p = nextSibling(p);
+ }
+ if (i >= numreq) {
+ Printf(f->code, "}\n");
+ }
+ Delete(source);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Pass output arguments back to the caller.
+
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Replaceall(tm, "$ntype", normalizeTemplatedClassName(Getattr(p, "type")));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Free up any memory allocated for the arguments.
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* if the object is a director, and the method call originated from its
+ * underlying ocaml object, resolve the call by going up the c++
+ * inheritance chain. otherwise try to resolve the method in ocaml.
+ * without this check an infinite loop is set up between the director and
+ * shadow class method calls.
+ */
+
+ // NOTE: this code should only be inserted if this class is the
+ // base class of a director class. however, in general we haven't
+ // yet analyzed all classes derived from this one to see if they are
+ // directors. furthermore, this class may be used as the base of
+ // a director class defined in a completely different module at a
+ // later time, so this test must be included whether or not directorbase
+ // is true. we do skip this code if directors have not been enabled
+ // at the command line to preserve source-level compatibility with
+ // non-polymorphic swig. also, if this wrapper is for a smart-pointer
+ // method, there is no need to perform the test since the calling object
+ // (the smart-pointer) and the director object (the "pointee") are
+ // distinct.
+
+ director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Append(f->code, "upcall = (director);\n");
+ }
+
+ // Now write code to make the function call
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$result", "rv");
+ Replaceall(tm, "$ntype", return_type_normalized);
+ Printv(f->code, tm, "\n", NIL);
+ } else {
+ throw_unhandled_ocaml_type_error(returntype, "out");
+ }
+ emit_return_variable(n, returntype, f);
+
+ // Dump the argument output code
+ Printv(f->code, Char(outarg), NIL);
+
+ // Dump the argument cleanup code
+ Printv(f->code, Char(cleanup), NIL);
+
+ // Look for any remaining cleanup
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ // Free any memory allocated by the function being wrapped..
+
+ if ((tm = Swig_typemap_lookup("swig_result", n, Swig_cresult_name(), 0))) {
+ Printv(f->code, tm, "\n", NIL);
+ }
+ // Wrap things up (in a manner of speaking)
+
+ Printv(f->code, tab4, "swig_result = caml_list_append(swig_result,rv);\n", NIL);
+ Printv(f->code, tab4, "CAMLreturn(swig_result);\n", NIL);
+ Printv(f->code, "}\n", NIL);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+
+ Wrapper_print(f, f_wrappers);
+
+ if (isOverloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ int maxargs;
+ Wrapper *df = NewWrapper();
+ String *dispatch = Swig_overload_dispatch(n,
+ "free(argv);\n" "CAMLreturn(%s(args));\n",
+ &maxargs);
+
+ Wrapper_add_local(df, "argv", "value *argv");
+
+ /* Undifferentiate name .. this is the dispatch function */
+ wname = Swig_name_wrapper(iname);
+ /* Do this to disambiguate functions emitted from different
+ * modules */
+ Append(wname, module);
+
+ Printv(df->def,
+ "SWIGEXT value ", wname, "(value args) {\n" " CAMLparam1(args);\n" " int i;\n" " int argc = caml_list_length(args);\n", NIL);
+ Printv(df->code,
+ "argv = (value *)malloc( argc * sizeof( value ) );\n"
+ "for( i = 0; i < argc; i++ ) {\n" " argv[i] = caml_list_nth(args,i);\n" "}\n", NIL);
+ Printv(df->code, dispatch, "\nfree(argv);\n", NIL);
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling");
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(df->code, "caml_failwith(\"Wrong number or type of arguments for overloaded function '%s'.\\n\""
+ "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", iname, protoTypes);
+ Delete(protoTypes);
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+
+ DelWrapper(df);
+ Delete(dispatch);
+ }
+ }
+
+ if (expose_func) {
+ Printf(f_mlbody, "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n", mangled_name, wname);
+ Printf(f_mlbody, "let %s arg = match %s_f (%s(fnhelper arg)) with\n", mangled_name, mangled_name,
+ in_constructor && Swig_directorclass(getCurrentClass()) ? "director_core_helper " : "");
+ Printf(f_mlbody, " [] -> C_void\n"
+ "| [x] -> (if %s then Gc.finalise \n"
+ " (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n"
+ "| lst -> C_list lst ;;\n", newobj ? "true" : "false");
+ }
+
+ if ((!classmode || in_constructor || in_destructor || static_member_function) && expose_func)
+ Printf(f_mlibody, "val %s : c_obj -> c_obj\n", mangled_name);
+
+ Delete(proc_name);
+ Delete(target);
+ Delete(arg);
+ Delete(outarg);
+ Delete(cleanup);
+ Delete(build);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ *
+ * Create a link to a C variable.
+ * This creates a single function _wrap_varname().
+ * This function takes a single optional argument. If supplied, it means
+ * we are setting this variable to some value. If omitted, it means we are
+ * simply evaluating this variable. We return the value of the variable
+ * in both cases.
+ *
+ * symname is the name of the variable with respect to C. This
+ * may need to differ from the original name in the case of enums.
+ * enumvname is the name of the variable with respect to ocaml. This
+ * will vary if the variable has been renamed.
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ char *name = GetChar(n, "feature:symname");
+ String *iname = Getattr(n, "feature:enumvname");
+ String *mname = mangleNameForCaml(iname);
+ SwigType *t = Getattr(n, "type");
+
+ String *proc_name = NewString("");
+ String *tm;
+ Wrapper *f;
+
+ if (!name) {
+ name = GetChar(n, "name");
+ }
+
+ if (!iname) {
+ iname = Getattr(n, "sym:name");
+ mname = mangleNameForCaml(NewString(iname));
+ }
+
+ if (!iname || !addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ f = NewWrapper();
+
+ // evaluation function names
+ String *var_name = Swig_name_wrapper(iname);
+
+ // Build the name for OCaml.
+ Printv(proc_name, iname, NIL);
+ Setattr(n, "wrap:name", proc_name);
+
+ Printf(f->def, "SWIGEXT value %s(value args) {\n", var_name);
+ // Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
+
+ Wrapper_add_local(f, "args", "CAMLparam1(args)");
+ Wrapper_add_local(f, "swig_result", "CAMLlocal1(swig_result)");
+ Printf(f->code, "swig_result = Val_unit;\n");
+
+ int assignable = !is_immutable(n);
+ if (assignable) {
+ /* Check for a setting of the variable value */
+ Printf(f->code, "if (args != Val_int(0)) {\n");
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$input", "args");
+ emit_action_code(n, f->code, tm);
+ } else if ((tm = Swig_typemap_lookup("in", n, name, 0))) {
+ Replaceall(tm, "$input", "args");
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_ocaml_type_error(t, "varin/in");
+ }
+ Printf(f->code, "}\n");
+ }
+ // Now return the value of the variable (regardless
+ // of evaluating or setting)
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "swig_result");
+ emit_action_code(n, f->code, tm);
+ } else if ((tm = Swig_typemap_lookup("out", n, name, 0))) {
+ Replaceall(tm, "$result", "swig_result");
+ emit_action_code(n, f->code, tm);
+ } else {
+ throw_unhandled_ocaml_type_error(t, "varout/out");
+ }
+
+ Printf(f->code, "\nCAMLreturn(swig_result);\n");
+ Printf(f->code, "}\n");
+
+ Wrapper_print(f, f_wrappers);
+
+ // Now add symbol to the Ocaml interpreter
+
+ if (!assignable) {
+ Printf(f_mlbody, "external _%s : c_obj -> Swig.c_obj = \"%s\" \n", mname, var_name);
+ Printf(f_mlibody, "val _%s : c_obj -> Swig.c_obj\n", iname);
+ if (const_enum) {
+ Printf(f_enum_to_int, " | `%s -> _%s C_void\n", mname, mname);
+ Printf(f_int_to_enum, " if y = (get_int (_%s C_void)) then `%s else\n", mname, mname);
+ }
+ } else {
+ Printf(f_mlbody, "external _%s : c_obj -> c_obj = \"%s\"\n", mname, var_name);
+ Printf(f_mlibody, "external _%s : c_obj -> c_obj = \"%s\"\n", mname, var_name);
+ }
+
+ Delete(var_name);
+ Delete(proc_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler --
+ * Overridden to set static_member_function
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ static_member_function = 1;
+ Language::staticmemberfunctionHandler(n);
+ static_member_function = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ *
+ * The one trick here is that we have to make sure we rename the
+ * constant to something useful that doesn't collide with the
+ * original if any exists.
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "feature:symname");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ SwigType *qname = Getattr(n, "qualified:name");
+
+ if (qname)
+ value = qname;
+
+ if (!name) {
+ name = mangleNameForCaml(Getattr(n, "name"));
+ Insert(name, 0, "_swig_wrap_");
+ Setattr(n, "feature:symname", name);
+ }
+ // See if there's a typemap
+
+ // Create variable and assign it a value
+ Printf(f_header, "static %s = %s;\n", SwigType_str(type, name), value);
+ SetFlag(n, "feature:immutable");
+ variableWrapper(n);
+ return SWIG_OK;
+ }
+
+ int constructorHandler(Node *n) {
+ int ret;
+
+ in_constructor = 1;
+ ret = Language::constructorHandler(n);
+ in_constructor = 0;
+
+ return ret;
+ }
+
+ /* destructorHandler:
+ * Turn on destructor flag to inform decisions in functionWrapper
+ */
+
+ int destructorHandler(Node *n) {
+ int ret;
+
+ in_destructor = 1;
+ ret = Language::destructorHandler(n);
+ in_destructor = 0;
+
+ return ret;
+ }
+
+ /* copyconstructorHandler:
+ * Turn on constructor and copyconstructor flags for functionWrapper
+ */
+
+ int copyconstructorHandler(Node *n) {
+ int ret;
+
+ in_copyconst = 1;
+ in_constructor = 1;
+ ret = Language::copyconstructorHandler(n);
+ in_constructor = 0;
+ in_copyconst = 0;
+
+ return ret;
+ }
+
+ /**
+ * A simple, somewhat general purpose function for writing to multiple
+ * streams from a source template. This allows the user to define the
+ * class definition in ways different from the one I have here if they
+ * want to. It will also make the class definition system easier to
+ * fiddle with when I want to change methods, etc.
+ */
+
+ void Multiwrite(String *s) {
+ char *find_marker = strstr(Char(s), "(*Stream:");
+ while (find_marker) {
+ char *next = strstr(find_marker, "*)");
+ find_marker += strlen("(*Stream:");
+
+ if (next) {
+ int num_chars = (int)(next - find_marker);
+ String *stream_name = NewString(find_marker);
+ Delslice(stream_name, num_chars, Len(stream_name));
+ File *fout = Swig_filebyname(stream_name);
+ if (fout) {
+ next += strlen("*)");
+ char *following = strstr(next, "(*Stream:");
+ find_marker = following;
+ if (!following)
+ following = next + strlen(next);
+ String *chunk = NewString(next);
+ Delslice(chunk, (int)(following - next), Len(chunk));
+ Printv(fout, chunk, NIL);
+ }
+ }
+ }
+ }
+
+ bool isSimpleType(String *name) {
+ char *ch = Char(name);
+
+ return !(strchr(ch, '(') || strchr(ch, '<') || strchr(ch, ')') || strchr(ch, '>'));
+ }
+
+ /* We accept all chars in identifiers because we use strings to index
+ * them. */
+ int validIdentifier(String *name) {
+ return Len(name) > 0 ? 1 : 0;
+ }
+
+ /* classHandler
+ *
+ * Create a "class" definition for ocaml. I thought quite a bit about
+ * how I should do this part of it, and arrived here, using a function
+ * invocation to select a method, and dispatch. This can obviously be
+ * done better, but I can't see how, given that I want to support
+ * overloaded methods, out parameters, and operators.
+ *
+ * I needed a system that would do this:
+ *
+ * a Be able to call these methods:
+ * int foo( int x );
+ * float foo( int x, int &out );
+ *
+ * b Be typeable, even in the presence of mutually dependent classes.
+ *
+ * c Support some form of operator invocation.
+ *
+ * (c) I chose strings for the method names so that "+=" would be a
+ * valid method name, and the somewhat natural << (invoke x) "+=" y >>
+ * would work.
+ *
+ * (a) (b) Since the c_obj type exists, it's easy to return C_int in one
+ * case and C_list [ C_float ; C_int ] in the other. This makes tricky
+ * problems with out parameters disappear; they're simply appended to the
+ * return list.
+ *
+ * (b) Since every item that comes from C++ is the same type, there is no
+ * problem with the following:
+ *
+ * class Foo;
+ * class Bar { Foo *toFoo(); }
+ * class Foo { Bar *toBar(); }
+ *
+ * Since the Objective caml types of Foo and Bar are the same. Now that
+ * I correctly incorporate SWIG's typechecking, this isn't a big deal.
+ *
+ * The class is in the form of a function returning a c_obj. The c_obj
+ * is a C_obj containing a function which invokes a method on the
+ * underlying object given its type.
+ *
+ * The name emitted here is normalized before being sent to
+ * Callback.register, because we need this string to look up properly
+ * when the typemap passes the descriptor string. I've been considering
+ * some, possibly more forgiving method that would do some transformations
+ * on the $descriptor in order to find a potential match. This is for
+ * later.
+ *
+ * Important things to note:
+ *
+ * We rely on exception handling (BadMethodName) in order to call an
+ * ancestor. This can be improved.
+ *
+ * The method used to get :classof could be improved to look at the type
+ * info that the base pointer contains. It's really an error to have a
+ * SWIG-generated object that does not contain type info, since the
+ * existence of the object means that SWIG knows the type.
+ *
+ * :parents could use :classof to tell what class it is and make a better
+ * decision. This could be nice, (i.e. provide a run-time graph of C++
+ * classes represented);.
+ *
+ * I can't think of a more elegant way of converting a C_obj fun to a
+ * pointer than "operator &"...
+ *
+ * Added a 'sizeof' that will allow you to do the expected thing.
+ * This should help users to fill buffer structs and the like (as is
+ * typical in windows-styled code). It's only enabled if you give
+ * %feature(sizeof) and then, only for simple types.
+ *
+ * Overall, carrying the list of methods and base classes has worked well.
+ * It allows me to give the Ocaml user introspection over their objects.
+ */
+
+ int classHandler(Node *n) {
+ String *name = Getattr(n, "name");
+ classname = Getattr(n, "sym:name");
+
+ if (!name)
+ return SWIG_OK;
+
+ String *mangled_name = mangleNameForCaml(name);
+ String *this_class_def = NewString(f_classtemplate);
+ String *name_normalized = normalizeTemplatedClassName(name);
+ String *old_class_ctors = f_class_ctors;
+ String *base_classes = NewString("");
+ f_class_ctors = NewString("");
+ bool sizeof_feature = generate_sizeof && isSimpleType(name);
+
+
+ classmode = true;
+ int rv = Language::classHandler(n);
+ classmode = false;
+
+ if (sizeof_feature) {
+ Printf(f_wrappers,
+ "SWIGEXT value _wrap_%s_sizeof( value args ) {\n"
+ " CAMLparam1(args);\n" " CAMLreturn(Val_int(sizeof(%s)));\n" "}\n", mangled_name, name_normalized);
+
+ Printf(f_mlbody, "external __%s_sizeof : unit -> int = " "\"_wrap_%s_sizeof\"\n", mangled_name, mangled_name);
+ }
+
+
+ /* Insert sizeof operator for concrete classes */
+ if (sizeof_feature) {
+ Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__", mangled_name, "_sizeof ())) ;\n", NIL);
+ }
+ /* Handle up-casts in a nice way */
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if (bname) {
+ String *base_create = NewString("");
+ Printv(base_create, "(create_class \"", bname, "\")", NIL);
+ Printv(f_class_ctors, " \"::", bname, "\", (fun args -> ", base_create, " args) ;\n", NIL);
+ Printv(base_classes, base_create, " ;\n", NIL);
+ }
+ b = Next(b);
+ }
+ }
+
+ Replaceall(this_class_def, "$classname", mangled_name);
+ Replaceall(this_class_def, "$normalized", name_normalized);
+ Replaceall(this_class_def, "$realname", name);
+ Replaceall(this_class_def, "$baselist", base_classes);
+ Replaceall(this_class_def, "$classbody", f_class_ctors);
+
+ Delete(f_class_ctors);
+ f_class_ctors = old_class_ctors;
+
+ // Actually write out the class definition
+
+ Multiwrite(this_class_def);
+
+ Setattr(n, "ocaml:ctor", mangled_name);
+
+ return rv;
+ }
+
+ String *normalizeTemplatedClassName(String *name) {
+ String *name_normalized = SwigType_typedef_resolve_all(name);
+ bool took_action;
+
+ do {
+ took_action = false;
+
+ if (is_a_pointer(name_normalized)) {
+ SwigType_del_pointer(name_normalized);
+ took_action = true;
+ }
+
+ if (is_a_reference(name_normalized)) {
+ oc_SwigType_del_reference(name_normalized);
+ took_action = true;
+ }
+
+ if (is_an_array(name_normalized)) {
+ oc_SwigType_del_array(name_normalized);
+ took_action = true;
+ }
+ } while (took_action);
+
+ return SwigType_str(name_normalized, 0);
+ }
+
+ /*
+ * Produce the symbol name that ocaml will use when referring to the
+ * target item. I wonder if there's a better way to do this:
+ * (WF - use Swig_name_mangle_string/Swig_name_mangle_type)
+ *
+ * I shudder to think about doing it with a hash lookup, but that would
+ * make a couple of things easier:
+ */
+
+ String *mangleNameForCaml(String *s) {
+ String *out = Copy(s);
+ Replaceall(out, " ", "_xx");
+ Replaceall(out, "::", "_xx");
+ Replaceall(out, ",", "_x");
+ Replaceall(out, "+", "_xx_plus");
+ Replaceall(out, "-", "_xx_minus");
+ Replaceall(out, "<", "_xx_ldbrace");
+ Replaceall(out, ">", "_xx_rdbrace");
+ Replaceall(out, "!", "_xx_not");
+ Replaceall(out, "%", "_xx_mod");
+ Replaceall(out, "^", "_xx_xor");
+ Replaceall(out, "*", "_xx_star");
+ Replaceall(out, "&", "_xx_amp");
+ Replaceall(out, "|", "_xx_or");
+ Replaceall(out, "(", "_xx_lparen");
+ Replaceall(out, ")", "_xx_rparen");
+ Replaceall(out, "[", "_xx_lbrace");
+ Replaceall(out, "]", "_xx_rbrace");
+ Replaceall(out, "~", "_xx_bnot");
+ Replaceall(out, "=", "_xx_equals");
+ Replaceall(out, "/", "_xx_slash");
+ Replaceall(out, ".", "_xx_dot");
+ Replaceall(out, "?", "_xx_question");
+ Replaceall(out, ":", "_xx_colon");
+ return out;
+ }
+
+ SwigType *fully_qualified_enum_type(Node *n) {
+ Node *parent = 0;
+ String *fully_qualified_name = NewString("");
+ String *parent_type = 0;
+
+ parent = parentNode(n);
+ while (parent) {
+ parent_type = nodeType(parent);
+ if (Getattr(parent, "name")) {
+ String *parent_copy = NewStringf("%s::", Getattr(parent, "name"));
+ if (Cmp(parent_type, "class") == 0 || Cmp(parent_type, "namespace") == 0)
+ Insert(fully_qualified_name, 0, parent_copy);
+ Delete(parent_copy);
+ }
+ if (!Cmp(parent_type, "class"))
+ break;
+ parent = parentNode(parent);
+ }
+
+ return fully_qualified_name;
+ }
+
+ /* Benedikt Grundmann inspired --> Enum wrap styles */
+
+ int enumvalueDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *qtype = 0;
+
+ if (name_qualifier_type) {
+ qtype = Copy(name_qualifier_type);
+ Printv(qtype, name, NIL);
+ }
+
+ if (const_enum && qtype && symname && !Getattr(seen_enumvalues, symname)) {
+ Setattr(seen_enumvalues, symname, "true");
+ SetFlag(n, "feature:immutable");
+ Setattr(n, "feature:enumvalue", "1"); // this does not appear to be used
+
+ Setattr(n, "qualified:name", SwigType_namestr(qtype));
+
+ String *evname = SwigType_manglestr(qtype);
+ Insert(evname, 0, "SWIG_ENUM_");
+
+ Setattr(n, "feature:enumvname", symname);
+ Setattr(n, "feature:symname", evname);
+ Delete(evname);
+ Printf(f_enumtypes_value, "| `%s\n", symname);
+
+ return Language::enumvalueDeclaration(n);
+ } else
+ return SWIG_OK;
+ }
+
+ /* -------------------------------------------------------------------
+ * This function is a bit uglier than it deserves.
+ *
+ * I used to direct lookup the name of the enum. Now that certain fixes
+ * have been made in other places, the names of enums are now fully
+ * qualified, which is a good thing, overall, but requires me to do
+ * some legwork.
+ *
+ * The other thing that uglifies this function is the varying way that
+ * typedef enum and enum are handled. I need to produce consistent names,
+ * which means looking up and registering by typedef and enum name. */
+ int enumDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *name = Getattr(n, "name");
+ if (name) {
+ String *oname = NewString(name);
+ /* name is now fully qualified */
+ String *fully_qualified_name = NewString(name);
+ bool seen_enum = false;
+ if (name_qualifier_type)
+ Delete(name_qualifier_type);
+ char *strip_position;
+ name_qualifier_type = fully_qualified_enum_type(n);
+
+ strip_position = strstr(Char(oname), "::");
+
+ while (strip_position) {
+ strip_position += 2;
+ oname = NewString(strip_position);
+ strip_position = strstr(Char(oname), "::");
+ }
+
+ seen_enum = (Getattr(seen_enums, fully_qualified_name) ? true : false);
+
+ if (!seen_enum) {
+ const_enum = true;
+ Printf(f_enum_to_int, "| `%s -> (match y with\n", oname);
+ Printf(f_int_to_enum, "| `%s -> C_enum (\n", oname);
+ /* * * * A note about enum name resolution * * * *
+ * This code should now work, but I think we can do a bit better.
+ * The problem I'm having is that swig isn't very precise about
+ * typedef name resolution. My opinion is that SwigType_typedef
+ * resolve_all should *always* return the enum tag if one exists,
+ * rather than the admittedly friendlier enclosing typedef.
+ *
+ * This would make one of the cases below unnecessary.
+ * * * */
+ Printf(f_mlbody, "let _ = Callback.register \"%s_marker\" (`%s)\n", fully_qualified_name, oname);
+ if (!strncmp(Char(fully_qualified_name), "enum ", 5)) {
+ String *fq_noenum = NewString(Char(fully_qualified_name) + 5);
+ Printf(f_mlbody,
+ "let _ = Callback.register \"%s_marker\" (`%s)\n" "let _ = Callback.register \"%s_marker\" (`%s)\n", fq_noenum, oname, fq_noenum, name);
+ }
+
+ Printf(f_enumtypes_type, "| `%s\n", oname);
+ Insert(fully_qualified_name, 0, "enum ");
+ Setattr(seen_enums, fully_qualified_name, n);
+ }
+ }
+
+ int ret = Language::enumDeclaration(n);
+
+ if (const_enum) {
+ Printf(f_int_to_enum, "`Int y)\n");
+ Printf(f_enum_to_int, "| `Int x -> Swig.C_int x\n" "| _ -> raise (LabelNotFromThisEnum v))\n");
+ }
+
+ const_enum = false;
+
+ return ret;
+ }
+
+ /* ----------------------------------------------------------------------------
+ * BEGIN C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+ /*
+ * Modified polymorphism code for Ocaml language module.
+ *
+ * TODO
+ *
+ * Move some boilerplate code generation to Swig_...() functions.
+ *
+ */
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Python object.
+ *
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ SwigType *returntype = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ int status = SWIG_OK;
+ int idx;
+ bool pure_virtual = false;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+ Printf(w->locals, "CAMLparam0();\n");
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void)
+ Printf(w->code, "%s;\n", super_call);
+ else
+ Printf(w->code, "CAMLreturnT(%s, %s);\n", SwigType_str(returntype, 0), super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ Wrapper_add_local(w, "swig_result", "CAMLlocal2(swig_result, args)");
+ /* attach typemaps to arguments (C/C++ -> Ocaml) */
+ String *arglist = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+ int num_arguments = emit_num_arguments(l);
+ int i;
+ char source[256];
+
+ /* build argument list and type conversion string */
+ for (i = 0, idx = 0, p = l; i < num_arguments; i++) {
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ Putc(',', arglist);
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ Printv(wrap_args, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ /* special handling for pointers to other C++ director classes.
+ * ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. in other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. we avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, ptype);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(ptype) + 2);
+ /* name as pointer */
+ String *ppname = Copy(pname);
+ if (SwigType_isreference(ptype)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Python doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", pname);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(ptype, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(ptype, pname),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(ptype);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "value", source, "= Val_unit", NIL);
+ Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Printf(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "}\n");
+ Delete(director);
+ Printv(arglist, source, NIL);
+ } else {
+ Wrapper_add_localv(w, source, "value", source, "= Val_unit", NIL);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
+ // source, nonconst, base);
+ Printv(arglist, source, NIL);
+ }
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ Printv(w->code, "swig_result = Val_unit;\n", 0);
+ Printf(w->code, "args = Val_unit;\n");
+
+ /* wrap complex arguments to values */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the OCaml object */
+ Printv(w->code,
+ "swig_result = caml_swig_alloc(1,C_list);\n" "Store_field(swig_result,0,args);\n" "args = swig_result;\n" "swig_result = Val_unit;\n", 0);
+ Printf(w->code, "static const value *swig_ocaml_func_val = NULL;\n" "if (!swig_ocaml_func_val) {\n");
+ Printf(w->code, " swig_ocaml_func_val = caml_named_value(\"swig_runmethod\");\n }\n");
+ Printf(w->code, "swig_result = caml_callback3(*swig_ocaml_func_val,swig_get_self(),caml_copy_string(\"%s\"),args);\n", Getattr(n, "name"));
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ }
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Printf(w->code, "if (!%s) {\n", Swig_cresult_name());
+ Printf(w->code, " value error = *caml_named_value(\"director_except\");\n");
+ Replaceall(tm, "$error", "error");
+ Printv(w->code, Str(tm), "\n", NIL);
+ Printf(w->code, "}\n");
+ }
+
+ /*
+ * Python method may return a simple object, or a tuple.
+ * for in/out arguments, we have to extract the appropriate values from the
+ * argument list, then marshal everything back to C/C++ (return value and
+ * output arguments).
+ */
+
+ /* marshal return value and other outputs (if any) from value to C/C++
+ * type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ tm = Swig_typemap_lookup("directorout", n, "c_result", w);
+ if (tm != 0) {
+ Replaceall(tm, "$input", "swig_result");
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ Replaceall(tm, "$result", "swig_result");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(arglist);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ /* any existing helper functions to handle this? */
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "CAMLreturnT(%s, (%s)c_result);\n", rettype, rettype);
+ } else {
+ Printf(w->code, "CAMLreturnT(%s, (%s)*c_result);\n", rettype, rettype);
+ }
+ Delete(rettype);
+ }
+ } else {
+ Printf(w->code, "CAMLreturn0;\n");
+ }
+
+ Printf(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p, *q;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("value");
+ p = NewParm(type, NewString("self"), n);
+ q = Copy(p);
+ set_nextSibling(q, superparms);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Setattr(n, "parms", q);
+ Language::classDirectorConstructor(n);
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ //Delete(parms);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname;
+ classname = Swig_class_name(n);
+
+ /* insert self parameter */
+ Parm *p, *q;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("value");
+ p = NewParm(type, NewString("self"), n);
+ q = Copy(p);
+ set_nextSibling(p, parms);
+
+ {
+ Wrapper *w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(value self) : Swig::Director(self) { }", classname, classname);
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ }
+ Printf(f_directors_h, " SwigDirector_%s(value self);\n", classname);
+ Delete(classname);
+ Setattr(n, "parms", q);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n" "%s\n" "public:\n", declaration);
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * typedefHandler
+ *
+ * This is here in order to maintain the correct association between
+ * typedef names and enum names.
+ *
+ * Since I implement enums as polymorphic variant tags, I need to call
+ * back into ocaml to evaluate them. This requires a string that can
+ * be generated in the typemaps, and also at SWIG time to be the same
+ * string. The problem that arises is that SWIG variously generates
+ * enum e_name_tag
+ * e_name_tag
+ * e_typedef_name
+ * for
+ * typedef enum e_name_tag { ... } e_typedef_name;
+ *
+ * Since I need these strings to be consistent, I must maintain a correct
+ * association list between typedef and enum names.
+ * --------------------------------------------------------------------- */
+ int typedefHandler(Node *n) {
+ String *type = Getattr(n, "type");
+ Node *enum_node = type ? Getattr(seen_enums, type) : 0;
+ if (enum_node) {
+ String *name = Getattr(enum_node, "name");
+
+ Printf(f_mlbody, "let _ = Callback.register \"%s_marker\" (`%s)\n", Getattr(n, "name"), name);
+
+ }
+ return SWIG_OK;
+ }
+
+ String *runtimeCode() {
+ String *s = Swig_include_sys("ocamlrun.swg");
+ if (!s) {
+ Printf(stderr, "*** Unable to open 'ocamlrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigocamlrun.h");
+ }
+};
+
+/* -------------------------------------------------------------------------
+ * swig_ocaml() - Instantiate module
+ * ------------------------------------------------------------------------- */
+
+static Language *new_swig_ocaml() {
+ return new OCAML();
+}
+extern "C" Language *swig_ocaml(void) {
+ return new_swig_ocaml();
+}
diff --git a/contrib/tools/swig/Source/Modules/octave.cxx b/contrib/tools/swig/Source/Modules/octave.cxx
new file mode 100644
index 00000000000..0e39a99ec77
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/octave.cxx
@@ -0,0 +1,1574 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * octave.cxx
+ *
+ * Octave language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static String *global_name = 0;
+static String *op_prefix = 0;
+
+static const char *usage = "\
+Octave Options (available with -octave)\n\
+ -globals <name> - Set <name> used to access C global variables [default: 'cvar']\n\
+ Use '.' to load C global variables into module namespace\n\
+ -opprefix <str> - Prefix <str> for global operator functions [default: 'op_']\n\
+\n";
+
+
+class OCTAVE:public Language {
+private:
+ File *f_begin;
+ File *f_runtime;
+ File *f_header;
+ File *f_doc;
+ File *f_wrappers;
+ File *f_init;
+ File *f_initbeforefunc;
+ File *f_directors;
+ File *f_directors_h;
+ String *s_global_tab;
+ String *s_members_tab;
+ String *class_name;
+
+ int have_constructor;
+ int have_destructor;
+ String *constructor_name;
+
+ Hash *docs;
+
+ void Octave_begin_function(Node *n, File *f, const_String_or_char_ptr cname, const_String_or_char_ptr wname, bool dld) {
+ if (dld) {
+ String *tname = texinfo_name(n, "std::string()");
+ Printf(f, "SWIG_DEFUN( %s, %s, %s ) {", cname, wname, tname);
+ }
+ else {
+ Printf(f, "static octave_value_list %s (const octave_value_list& args, int nargout) {", wname);
+ }
+ }
+
+public:
+ OCTAVE():
+ f_begin(0),
+ f_runtime(0),
+ f_header(0),
+ f_doc(0),
+ f_wrappers(0),
+ f_init(0),
+ f_initbeforefunc(0),
+ f_directors(0),
+ f_directors_h(0),
+ s_global_tab(0),
+ s_members_tab(0),
+ class_name(0),
+ have_constructor(0),
+ have_destructor(0),
+ constructor_name(0),
+ docs(0)
+ {
+ /* Add code to manage protected constructors and directors */
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " error(\"accessing abstract class or protected constructor\"); \n", " SWIG_fail;\n", "}\n", NIL);
+
+ enable_cplus_runtime_mode();
+ allow_overloading();
+ director_multiple_inheritance = 1;
+ directorLanguage();
+ docs = NewHash();
+ }
+
+ virtual void main(int argc, char *argv[]) {
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-globals") == 0) {
+ if (argv[i + 1]) {
+ global_name = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-opprefix") == 0) {
+ if (argv[i + 1]) {
+ op_prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ if (!global_name)
+ global_name = NewString("cvar");
+ if (!op_prefix)
+ op_prefix = NewString("op_");
+
+ SWIG_library_directory("octave");
+ Preprocessor_define("SWIGOCTAVE 1", 0);
+ SWIG_config_file("octave.swg");
+ allow_overloading();
+
+ // Octave API is C++, so output must be C++ compatible even when wrapping C code
+ if (!cparse_cplusplus)
+ Swig_cparse_cplusplusout(1);
+ }
+
+ virtual int top(Node *n) {
+ {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ int dirprot = 0;
+ if (Getattr(options, "dirprot")) {
+ dirprot = 1;
+ }
+ if (Getattr(options, "nodirprot")) {
+ dirprot = 0;
+ }
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ if (dirprot)
+ allow_dirprot();
+ }
+ }
+ }
+ }
+
+ String *module = Getattr(n, "name");
+ String *outfile = Getattr(n, "outfile");
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_header = NewString("");
+ f_doc = NewString("");
+ f_wrappers = NewString("");
+ f_init = NewString("");
+ f_initbeforefunc = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+ s_global_tab = NewString("");
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("doc", f_doc);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "OCTAVE");
+
+ Printf(f_runtime, "#define SWIG_name_d \"%s\"\n", module);
+ Printf(f_runtime, "#define SWIG_name %s\n", module);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIG_global_name \"%s\"\n", global_name);
+ Printf(f_runtime, "#define SWIG_op_prefix \"%s\"\n", op_prefix);
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ Swig_banner(f_directors_h);
+ if (dirprot_mode()) {
+ // Printf(f_directors_h, "#include <map>\n");
+ // Printf(f_directors_h, "#include <string>\n\n");
+ }
+ }
+
+ Printf(f_runtime, "\n");
+
+ Printf(s_global_tab, "\nstatic const struct swig_octave_member swig_globals[] = {\n");
+ Printf(f_init, "static bool SWIG_init_user(octave_swig_type* module_ns)\n{\n");
+
+ if (!CPlusPlus)
+ Printf(f_header,"extern \"C\" {\n");
+
+ Language::top(n);
+
+ if (!CPlusPlus)
+ Printf(f_header,"}\n");
+
+ if (Len(docs))
+ emit_doc_texinfo();
+
+ if (Swig_directors_enabled()) {
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ Printf(f_init, "return true;\n}\n");
+ Printf(s_global_tab, "{0,0,0,0,0,0}\n};\n");
+
+ Printv(f_wrappers, s_global_tab, NIL);
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+ Dump(f_doc, f_begin);
+ if (Swig_directors_enabled()) {
+ Dump(f_directors_h, f_begin);
+ Dump(f_directors, f_begin);
+ }
+ Dump(f_wrappers, f_begin);
+ Dump(f_initbeforefunc, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(s_global_tab);
+ Delete(f_initbeforefunc);
+ Delete(f_init);
+ Delete(f_wrappers);
+ Delete(f_doc);
+ Delete(f_header);
+ Delete(f_directors);
+ Delete(f_directors_h);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ String *texinfo_escape(String *_s) {
+ const char* s=(const char*)Data(_s);
+ while (*s&&(*s=='\t'||*s=='\r'||*s=='\n'||*s==' '))
+ ++s;
+ String *r = NewString("");
+ for (int j=0;s[j];++j) {
+ if (s[j] == '\n') {
+ Append(r, "\\n\\\n");
+ } else if (s[j] == '\r') {
+ Append(r, "\\r");
+ } else if (s[j] == '\t') {
+ Append(r, "\\t");
+ } else if (s[j] == '\\') {
+ Append(r, "\\\\");
+ } else if (s[j] == '\'') {
+ Append(r, "\\\'");
+ } else if (s[j] == '\"') {
+ Append(r, "\\\"");
+ } else
+ Putc(s[j], r);
+ }
+ return r;
+ }
+ void emit_doc_texinfo() {
+ for (Iterator it = First(docs); it.key; it = Next(it)) {
+ String *wrap_name = it.key;
+
+ String *synopsis = Getattr(it.item, "synopsis");
+ String *decl_info = Getattr(it.item, "decl_info");
+ String *cdecl_info = Getattr(it.item, "cdecl_info");
+ String *args_info = Getattr(it.item, "args_info");
+
+ String *doc_str = NewString("");
+ Printv(doc_str, synopsis, decl_info, cdecl_info, args_info, NIL);
+ String *escaped_doc_str = texinfo_escape(doc_str);
+
+ if (Len(doc_str)>0) {
+ Printf(f_doc,"static const char* %s_texinfo = ",wrap_name);
+ Printf(f_doc,"\"-*- texinfo -*-\\n\\\n%s", escaped_doc_str);
+ if (Len(decl_info))
+ Printf(f_doc,"\\n\\\n@end deftypefn");
+ Printf(f_doc,"\";\n");
+ }
+
+ Delete(escaped_doc_str);
+ Delete(doc_str);
+ Delete(wrap_name);
+ }
+ Printf(f_doc,"\n");
+ }
+ bool is_empty_doc_node(Node* n) {
+ if (!n)
+ return true;
+ String *synopsis = Getattr(n, "synopsis");
+ String *decl_info = Getattr(n, "decl_info");
+ String *cdecl_info = Getattr(n, "cdecl_info");
+ String *args_info = Getattr(n, "args_info");
+ return !Len(synopsis) && !Len(decl_info) &&
+ !Len(cdecl_info) && !Len(args_info);
+ }
+ String *texinfo_name(Node* n, const char* defval = "0") {
+ String *tname = NewString("");
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(iname);
+ Node* d = Getattr(docs, wname);
+
+ if (is_empty_doc_node(d))
+ Printf(tname, defval);
+ else
+ Printf(tname, "%s_texinfo", wname);
+
+ return tname;
+ }
+ void process_autodoc(Node *n) {
+ String *iname = Getattr(n, "sym:name");
+ String *name = Getattr(n, "name");
+ String *wname = Swig_name_wrapper(iname);
+ String *str = Getattr(n, "feature:docstring");
+ bool autodoc_enabled = !Cmp(Getattr(n, "feature:autodoc"), "1");
+ Node* d = Getattr(docs, wname);
+ if (!d) {
+ d = NewHash();
+ Setattr(d, "synopsis", NewString(""));
+ Setattr(d, "decl_info", NewString(""));
+ Setattr(d, "cdecl_info", NewString(""));
+ Setattr(d, "args_info", NewString(""));
+ Setattr(docs, wname, d);
+ }
+
+ String *synopsis = Getattr(d, "synopsis");
+ String *decl_info = Getattr(d, "decl_info");
+ // String *cdecl_info = Getattr(d, "cdecl_info");
+ String *args_info = Getattr(d, "args_info");
+
+ // * couldn't we just emit the docs here?
+
+ if (autodoc_enabled) {
+ String *decl_str = NewString("");
+ String *args_str = NewString("");
+ make_autodocParmList(n, decl_str, args_str);
+ Append(decl_info, "@deftypefn {Loadable Function} ");
+
+ SwigType *type = Getattr(n, "type");
+ if (type && Strcmp(type, "void")) {
+ Node *nn = classLookup(Getattr(n, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ Append(decl_info, "@var{retval} = ");
+ Printf(args_str, "%s@var{retval} is of type %s. ", args_str, type_str);
+ Delete(type_str);
+ }
+
+ Append(decl_info, name);
+ Append(decl_info, " (");
+ Append(decl_info, decl_str);
+ Append(decl_info, ")\n");
+ Append(args_info, args_str);
+ Delete(decl_str);
+ Delete(args_str);
+ }
+
+ if (str && Len(str) > 0) {
+ // strip off {} if necessary
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+
+ // emit into synopsis section
+ Append(synopsis, str);
+ }
+ }
+
+ virtual int importDirective(Node *n) {
+ String *modname = Getattr(n, "module");
+ if (modname)
+ Printf(f_init, "if (!SWIG_Octave_LoadModule(\"%s\")) return false;\n", modname);
+ return Language::importDirective(n);
+ }
+
+ const char *get_implicitconv_flag(Node *n) {
+ int conv = 0;
+ if (n && GetFlag(n, "feature:implicitconv")) {
+ conv = 1;
+ }
+ return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0";
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addMissingParameterNames()
+ * For functions that have not had nameless parameters set in the Language class.
+ *
+ * Inputs:
+ * plist - entire parameter list
+ * arg_offset - argument number for first parameter
+ * Side effects:
+ * The "lname" attribute in each parameter in plist will be contain a parameter name
+ * ----------------------------------------------------------------------------- */
+
+ void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
+ Parm *p = plist;
+ int i = arg_offset;
+ while (p) {
+ if (!Getattr(p, "lname")) {
+ String *name = makeParameterName(n, p, i);
+ Setattr(p, "lname", name);
+ Delete(name);
+ }
+ i++;
+ p = nextSibling(p);
+ }
+ }
+
+ void make_autodocParmList(Node *n, String *decl_str, String *args_str) {
+ String *pdocs = 0;
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ int arg_num = is_wrapping_class() ? 1 : 0;
+
+ addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ for (p = plist; p; p = pnext, arg_num++) {
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *pdoc = Getattr(p, "tmap:doc");
+ if (pdoc) {
+ name = Getattr(p, "tmap:doc:name");
+ type = Getattr(p, "tmap:doc:type");
+ value = Getattr(p, "tmap:doc:value");
+ }
+
+ String *made_name = 0;
+ if (!name) {
+ name = made_name = makeParameterName(n, p, arg_num);
+ }
+
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ if (SwigType_isvarargs(type))
+ break;
+
+ String *tex_name = NewString("");
+ if (name)
+ Printf(tex_name, "@var{%s}", name);
+ else
+ Printf(tex_name, "@var{?}");
+
+ if (Len(decl_str))
+ Append(decl_str, ", ");
+ Append(decl_str, tex_name);
+
+ if (value) {
+ String *new_value = convertValue(value, Getattr(p, "numval"), Getattr(p, "stringval"), Getattr(p, "type"));
+ if (new_value) {
+ value = new_value;
+ } else {
+ Node *lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(decl_str, " = %s", value);
+ }
+
+ Node *nn = classLookup(Getattr(p, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ Printf(args_str, "%s is of type %s. ", tex_name, type_str);
+
+ Delete(type_str);
+ Delete(tex_name);
+ Delete(made_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ }
+
+ /* ------------------------------------------------------------
+ * convertValue()
+ * Check if string v can be an Octave value literal,
+ * (eg. number or string), or translate it to an Octave literal.
+ * ------------------------------------------------------------ */
+ String *convertValue(String *v, String *numval, String *stringval, SwigType *t) {
+ if (stringval) {
+ return stringval;
+ }
+ if (numval) {
+ if (SwigType_type(t) == T_BOOL) {
+ return NewString(*Char(numval) == '0' ? "false" : "true");
+ }
+ return numval;
+ }
+ if (Equal(v, "0") || Equal(v, "NULL") || Equal(v, "nullptr"))
+ return SwigType_ispointer(t) ? NewString("None") : NewString("0");
+ // FIXME: TRUE and FALSE are not standard and could be defined in other ways
+ if (Equal(v, "TRUE"))
+ return NewString("true");
+ if (Equal(v, "FALSE"))
+ return NewString("false");
+ return 0;
+ }
+
+ virtual int functionWrapper(Node *n) {
+ Parm *p;
+ String *tm;
+ int j;
+
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ int destructor = (!Cmp(nodeType, "destructor"));
+ String *storage = Getattr(n, "storage");
+
+ bool overloaded = !!Getattr(n, "sym:overloaded");
+ bool last_overload = overloaded && !Getattr(n, "sym:nextSibling");
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(iname);
+ String *overname = Copy(wname);
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+
+ if (!overloaded && !addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ if (overloaded)
+ Append(overname, Getattr(n, "sym:overname"));
+
+ if (!overloaded || last_overload)
+ process_autodoc(n);
+
+ Wrapper *f = NewWrapper();
+ Octave_begin_function(n, f->def, iname, overname, !overloaded);
+
+ // Start default try block to execute
+ // cleanup code if exception is thrown
+ Printf(f->code, "try {\n");
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ int num_arguments = emit_num_arguments(l);
+ int num_required = emit_num_required(l);
+ int varargs = emit_isvarargs(l);
+ char source[64];
+
+ Printf(f->code, "if (!SWIG_check_num_args(\"%s\",args.length(),%i,%i,%i)) "
+ "{\n SWIG_fail;\n }\n", iname, num_arguments, num_required, varargs);
+
+ if (constructor && num_arguments == 1 && num_required == 1) {
+ if (Cmp(storage, "explicit") == 0) {
+ Node *parent = Swig_methodclass(n);
+ if (GetFlag(parent, "feature:implicitconv")) {
+ String *desc = NewStringf("SWIGTYPE%s", SwigType_manglestr(Getattr(n, "type")));
+ Printf(f->code, "if (SWIG_CheckImplicit(%s)) SWIG_fail;\n", desc);
+ Delete(desc);
+ }
+ }
+ }
+
+ for (j = 0, p = l; j < num_arguments; ++j) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ if (!tm || checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ sprintf(source, "args(%d)", j);
+ Setattr(p, "emit:input", source);
+
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ if (Getattr(p, "tmap:in:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ Replaceall(tm, "$implicitconv", convflag);
+ Setattr(p, "implicitconv", convflag);
+ }
+
+ String *getargs = NewString("");
+ if (j >= num_required)
+ Printf(getargs, "if (%d<args.length()) {\n%s\n}", j, tm);
+ else
+ Printv(getargs, tm, NIL);
+ Printv(f->code, getargs, "\n", NIL);
+ Delete(getargs);
+
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ break;
+ }
+ }
+
+ // Check for trailing varargs
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", "varargs");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ // Insert constraint checking code
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Insert cleanup code
+ String *cleanup = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ if (Getattr(p, "tmap:freearg:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ if (strcmp(convflag, "0") == 0) {
+ tm = 0;
+ }
+ }
+ if (tm && (Len(tm) != 0)) {
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Insert argument output code
+ String *outarg = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$result", "_outp");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ int director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Append(f->code, "upcall = !!dynamic_cast<Swig::Director*>(arg1);\n");
+ }
+
+ Setattr(n, "wrap:name", overname);
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ Wrapper_add_local(f, "_out", "octave_value_list _out");
+ Wrapper_add_local(f, "_outp", "octave_value_list *_outp=&_out");
+ Wrapper_add_local(f, "_outv", "octave_value _outv");
+
+ // Return the function value
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$result", "_outv");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s\n", tm);
+ Printf(f->code, "if (_outv.is_defined()) _outp = " "SWIG_Octave_AppendOutput(_outp, _outv);\n");
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), iname);
+ }
+ emit_return_variable(n, returntype, f);
+
+ Printv(f->code, outarg, NIL);
+ Printv(f->code, cleanup, NIL);
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$result", "_outv");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printf(f->code, "return _out;\n");
+
+ // Execute cleanup code if branched to fail: label
+ Printf(f->code, "fail:\n");
+ Printv(f->code, cleanup, NIL);
+ Printf(f->code, "return octave_value_list();\n");
+
+ // Execute cleanup code if exception was thrown
+ Printf(f->code, "}\n");
+ Printf(f->code, "catch(...) {\n");
+ Printv(f->code, cleanup, NIL);
+ Printf(f->code, "throw;\n");
+ Printf(f->code, "}\n");
+
+ // End wrapper function
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(f->code, "$symname", iname);
+ Wrapper_print(f, f_wrappers);
+ DelWrapper(f);
+
+ if (last_overload)
+ dispatchFunction(n);
+
+ if (!overloaded || last_overload) {
+ String *tname = texinfo_name(n);
+ Printf(s_global_tab, "{\"%s\",%s,0,0,2,%s},\n", iname, wname, tname);
+ Delete(tname);
+ }
+
+ Delete(overname);
+ Delete(wname);
+ Delete(cleanup);
+ Delete(outarg);
+
+ return SWIG_OK;
+ }
+
+ void dispatchFunction(Node *n) {
+ Wrapper *f = NewWrapper();
+
+ String *iname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(iname);
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(args, nargout);", &maxargs);
+ String *tmp = NewString("");
+
+ Octave_begin_function(n, f->def, iname, wname, true);
+ Wrapper_add_local(f, "argc", "int argc = args.length()");
+ Printf(tmp, "octave_value_ref argv[%d]={", maxargs);
+ for (int j = 0; j < maxargs; ++j)
+ Printf(tmp, "%soctave_value_ref(args,%d)", j ? "," : " ", j);
+ Printf(tmp, "}");
+ Wrapper_add_local(f, "argv", tmp);
+ Printv(f->code, dispatch, "\n", NIL);
+ Printf(f->code, "error(\"No matching function for overload\");\n");
+ Printf(f->code, "return octave_value_list();\n");
+ Printv(f->code, "}\n", NIL);
+
+ Wrapper_print(f, f_wrappers);
+ Delete(tmp);
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(wname);
+ }
+
+ virtual int variableWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ String *tm;
+ Wrapper *getf = NewWrapper();
+ Wrapper *setf = NewWrapper();
+
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+
+ String *getwname = Swig_name_wrapper(getname);
+ String *setwname = Swig_name_wrapper(setname);
+
+ Octave_begin_function(n, setf->def, setname, setwname, true);
+ Printf(setf->code, "if (!SWIG_check_num_args(\"%s_set\",args.length(),1,1,0)) return octave_value_list();\n", iname);
+ if (!is_immutable(n)) {
+ Setattr(n, "wrap:name", setname);
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$input", "args(0)");
+ if (Getattr(n, "tmap:varin:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ emit_action_code(n, setf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ }
+ Append(setf->code, "return octave_value_list();\n");
+ Append(setf->code, "fail:\n");
+ Append(setf->code, "return octave_value_list();\n");
+ } else {
+ Printf(setf->code, "return octave_set_immutable(args,nargout);");
+ }
+ Append(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+
+ Setattr(n, "wrap:name", getname);
+ int addfail = 0;
+ Octave_begin_function(n, getf->def, getname, getwname, true);
+ Wrapper_add_local(getf, "obj", "octave_value obj");
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "obj");
+ addfail = emit_action_code(n, getf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ }
+ Append(getf->code, "return obj;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, "return octave_value_list();\n");
+ }
+ Append(getf->code, "}\n");
+ Wrapper_print(getf, f_wrappers);
+
+ Printf(s_global_tab, "{\"%s\",0,%s,%s,2,0},\n", iname, getwname, setwname);
+
+ Delete(getwname);
+ Delete(setwname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+
+ return SWIG_OK;
+ }
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *cppvalue = Getattr(n, "cppvalue");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ String *str = SwigType_str(type, wname);
+ Printf(f_header, "static %s = %s;\n", str, value);
+ Delete(str);
+ value = wname;
+ }
+ if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$value", cppvalue ? cppvalue : value);
+ Replaceall(tm, "$nsname", iname);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int nativeWrapper(Node *n) {
+ return Language::nativeWrapper(n);
+ }
+
+ virtual int enumDeclaration(Node *n) {
+ return Language::enumDeclaration(n);
+ }
+
+ virtual int enumvalueDeclaration(Node *n) {
+ return Language::enumvalueDeclaration(n);
+ }
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ virtual int classHandler(Node *n) {
+ have_constructor = 0;
+ have_destructor = 0;
+ constructor_name = 0;
+
+ class_name = Getattr(n, "sym:name");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ // This is a bug, due to the fact that swig_type -> octave_class mapping
+ // is 1-to-n.
+ static Hash *emitted = NewHash();
+ String *mangled_classname = Swig_name_mangle_type(Getattr(n, "name"));
+ if (Getattr(emitted, mangled_classname)) {
+ Delete(mangled_classname);
+ return SWIG_NOWRAP;
+ }
+ Setattr(emitted, mangled_classname, "1");
+ Delete(mangled_classname);
+
+ assert(!s_members_tab);
+ s_members_tab = NewString("");
+ Printv(s_members_tab, "static swig_octave_member swig_", class_name, "_members[] = {\n", NIL);
+
+ Language::classHandler(n);
+
+ SwigType *t = Copy(Getattr(n, "name"));
+ SwigType_add_pointer(t);
+
+ // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers)
+ SwigType *smart = Getattr(n, "smart");
+ String *wrap_class = NewStringf("&_wrap_class_%s", class_name);
+ if (smart) {
+ SwigType *psmart = Copy(smart);
+ SwigType_add_pointer(psmart);
+ SwigType_remember_clientdata(psmart, wrap_class);
+ Delete(psmart);
+ }
+ SwigType_remember_clientdata(t, wrap_class);
+
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *cname = Swig_name_disown(nspace, class_name);
+ String *wcname = Swig_name_wrapper(cname);
+ String *cnameshdw = NewStringf("%s_shadow", cname);
+ String *wcnameshdw = Swig_name_wrapper(cnameshdw);
+ Octave_begin_function(n, f_wrappers, cnameshdw, wcnameshdw, true);
+ Printf(f_wrappers, " if (args.length()!=1) {\n");
+ Printf(f_wrappers, " error(\"disown takes no arguments\");\n");
+ Printf(f_wrappers, " return octave_value_list();\n");
+ Printf(f_wrappers, " }\n");
+ Printf(f_wrappers, " %s (args, nargout);\n", wcname);
+ Printf(f_wrappers, " return args;\n");
+ Printf(f_wrappers, "}\n");
+ Printf(s_members_tab, "{\"__disown\",%s,0,0,0,0},\n", wcnameshdw);
+ Delete(wcname);
+ Delete(cname);
+ Delete(wcnameshdw);
+ Delete(cnameshdw);
+ }
+
+ Printf(s_members_tab, "{0,0,0,0,0,0}\n};\n");
+ Printv(f_wrappers, s_members_tab, NIL);
+
+ String *base_class_names = NewString("");
+ String *base_class = NewString("");
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "name");
+ if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
+ b = Next(b);
+ continue;
+ }
+
+ String *bname_mangled = SwigType_manglestr(SwigType_add_pointer(Copy(bname)));
+ Printf(base_class_names, "\"%s\",", bname_mangled);
+ Printf(base_class, "0,");
+ b = Next(b);
+ Delete(bname_mangled);
+ }
+ }
+
+ Printv(f_wrappers, "static const char *swig_", class_name, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Printv(f_wrappers, "static const swig_type_info *swig_", class_name, "_base[] = {", base_class, "0};\n", NIL);
+ Printv(f_wrappers, "static swig_octave_class _wrap_class_", class_name, " = {\"", class_name, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
+ Printv(f_wrappers, Swig_directorclass(n) ? "1," : "0,", NIL);
+ if (have_constructor) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *cname = Swig_name_construct(nspace, constructor_name);
+ String *wcname = Swig_name_wrapper(cname);
+ String *tname = texinfo_name(n);
+ Printf(f_wrappers, "%s,%s,", wcname, tname);
+ Delete(tname);
+ Delete(wcname);
+ Delete(cname);
+ } else
+ Printv(f_wrappers, "0,0,", NIL);
+ if (have_destructor) {
+ String *nspace = Getattr(n, "sym:nspace");
+ String *cname = Swig_name_destroy(nspace, class_name);
+ String *wcname = Swig_name_wrapper(cname);
+ Printf(f_wrappers, "%s,", wcname);
+ Delete(wcname);
+ Delete(cname);
+ } else
+ Printv(f_wrappers, "0", ",", NIL);
+ Printf(f_wrappers, "swig_%s_members,swig_%s_base_names,swig_%s_base };\n\n", class_name, class_name, class_name);
+
+ Delete(base_class);
+ Delete(base_class_names);
+ Delete(t);
+ Delete(s_members_tab);
+ s_members_tab = 0;
+ class_name = 0;
+
+ return SWIG_OK;
+ }
+
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ assert(s_members_tab);
+ assert(class_name);
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ String *realname = iname ? iname : name;
+ String *wname = Getattr(n, "wrap:name");
+ assert(wname);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *tname = texinfo_name(n);
+ String *rname = Copy(wname);
+ bool overloaded = !!Getattr(n, "sym:overloaded");
+ if (overloaded)
+ Delslice(rname, Len(rname) - Len(Getattr(n, "sym:overname")), DOH_END);
+ Printf(s_members_tab, "{\"%s\",%s,0,0,0,%s},\n",
+ realname, rname, tname);
+ Delete(rname);
+ Delete(tname);
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int membervariableHandler(Node *n) {
+ Setattr(n, "feature:autodoc", "0");
+
+ Language::membervariableHandler(n);
+
+ assert(s_members_tab);
+ assert(class_name);
+ String *symname = Getattr(n, "sym:name");
+ String *getname = Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *setname = Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *getwname = Swig_name_wrapper(getname);
+ String *setwname = GetFlag(n, "feature:immutable") ? NewString("octave_set_immutable") : Swig_name_wrapper(setname);
+ assert(s_members_tab);
+
+ Printf(s_members_tab, "{\"%s\",0,%s,%s,0,0},\n", symname, getwname, setwname);
+
+ Delete(getname);
+ Delete(setname);
+ Delete(getwname);
+ Delete(setwname);
+ return SWIG_OK;
+ }
+
+ virtual int constructorHandler(Node *n) {
+ have_constructor = 1;
+ if (!constructor_name)
+ constructor_name = NewString(Getattr(n, "sym:name"));
+
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("void");
+ SwigType_add_pointer(type);
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "self_obj");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Setattr(n, "hidden", "1");
+ Delete(self);
+ }
+
+ return Language::constructorHandler(n);
+ }
+
+ virtual int destructorHandler(Node *n) {
+ have_destructor = 1;
+ return Language::destructorHandler(n);
+ }
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ Language::staticmemberfunctionHandler(n);
+
+ assert(s_members_tab);
+ assert(class_name);
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ String *realname = iname ? iname : name;
+ String *wname = Getattr(n, "wrap:name");
+ assert(wname);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ String *tname = texinfo_name(n);
+ String *rname = Copy(wname);
+ bool overloaded = !!Getattr(n, "sym:overloaded");
+ if (overloaded)
+ Delslice(rname, Len(rname) - Len(Getattr(n, "sym:overname")), DOH_END);
+ Printf(s_members_tab, "{\"%s\",%s,0,0,1,%s},\n",
+ realname, rname, tname);
+ Delete(rname);
+ Delete(tname);
+ }
+
+ return SWIG_OK;
+ }
+
+ virtual int memberconstantHandler(Node *n) {
+ return Language::memberconstantHandler(n);
+ }
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Setattr(n, "feature:autodoc", "0");
+
+ Language::staticmembervariableHandler(n);
+
+ if (!GetFlag(n, "wrappedasconstant")) {
+ assert(s_members_tab);
+ assert(class_name);
+ String *symname = Getattr(n, "sym:name");
+ String *getname = Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *setname = Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname));
+ String *getwname = Swig_name_wrapper(getname);
+ String *setwname = GetFlag(n, "feature:immutable") ? NewString("octave_set_immutable") : Swig_name_wrapper(setname);
+ assert(s_members_tab);
+
+ Printf(s_members_tab, "{\"%s\",0,%s,%s,1,0},\n", symname, getwname, setwname);
+
+ Delete(getname);
+ Delete(setname);
+ Delete(getwname);
+ Delete(setwname);
+ }
+ return SWIG_OK;
+ }
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ // insert self parameter
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("void");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ // constructor
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s," "\nSwig::Director(static_cast<%s*>(this)) { \n", classname, target, call, basetype);
+ Append(w->def, "}\n");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ // constructor header
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ {
+ Wrapper *w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(void* self) :"
+ "\nSwig::Director((octave_swig_type*)self,static_cast<%s*>(this)) { \n", classname, classname, classname);
+ Append(w->def, "}\n");
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ }
+ Printf(f_directors_h, " SwigDirector_%s(octave_swig_type* self);\n", classname);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ SwigType *returntype = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ // determine if the method returns a pointer
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ // virtual method definition
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+
+ // header declaration
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ // declare method return value
+ // if the return value is a reference or const reference, a specialized typemap must
+ // handle it, including declaration of c_result ($result).
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ // attach typemaps to arguments (C/C++ -> Octave)
+ String *parse_args = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ // build argument list and type conversion string
+ p = l;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+ Wrapper_add_local(w, "tmpv", "octave_value tmpv");
+
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ String *parse = Getattr(p, "tmap:directorin:parse");
+ if (!parse) {
+ Setattr(p, "emit:directorinput", "tmpv");
+ Replaceall(tm, "$input", "tmpv");
+ Replaceall(tm, "$owner", "0");
+ Printv(wrap_args, tm, "\n", NIL);
+ Printf(wrap_args, "args.append(tmpv);\n");
+ Putc('O', parse_args);
+ } else {
+ Append(parse_args, parse);
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ p = nextSibling(p);
+ }
+
+ String *method_name = Getattr(n, "sym:name");
+
+ Printv(w->code, wrap_args, NIL);
+
+ // emit method invocation
+ Wrapper_add_local(w, "args", "octave_value_list args");
+ Wrapper_add_local(w, "out", "octave_value_list out");
+ Wrapper_add_local(w, "idx", "std::list<octave_value_list> idx");
+ Printf(w->code, "idx.push_back(octave_value_list(\"%s\"));\n", method_name);
+ Printf(w->code, "idx.push_back(args);\n");
+ Printf(w->code, "out=swig_get_self()->subsref(\".(\",idx,%d);\n", outputs);
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ idx = 0;
+
+ // marshal return value
+ if (!is_void) {
+ Printf(w->code, "if (out.length()<%d) {\n", outputs);
+ Printf(w->code, "Swig::DirectorTypeMismatchException::raise(\"Octave "
+ "method %s.%s failed to return the required number " "of arguments.\");\n", classname, method_name);
+ Printf(w->code, "}\n");
+
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ char temp[24];
+ sprintf(temp, "out(%d)", idx);
+ Replaceall(tm, "$input", temp);
+ // Replaceall(tm, "$argnum", temp);
+ Replaceall(tm, "$disown", Getattr(n, "wrap:disown") ? "SWIG_POINTER_DISOWN" : "0");
+ if (Getattr(n, "tmap:directorout:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+ idx++;
+
+ // marshal outputs
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ char temp[24];
+ sprintf(temp, "out(%d)", idx);
+ Replaceall(tm, "$result", temp);
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(parse_args);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+ // emit the director method
+ if (status == SWIG_OK) {
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+ // clean up
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *srun = Swig_include_sys("octrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'octrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigoctaverun.h");
+ }
+};
+
+extern "C" Language *swig_octave(void) {
+ return new OCTAVE();
+}
diff --git a/contrib/tools/swig/Source/Modules/overload.cxx b/contrib/tools/swig/Source/Modules/overload.cxx
new file mode 100644
index 00000000000..5882953bd26
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/overload.cxx
@@ -0,0 +1,872 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * overload.cxx
+ *
+ * This file is used to analyze overloaded functions and methods.
+ * It looks at signatures and tries to gather information for
+ * building a dispatch function.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+#define MAX_OVERLOAD 4096
+
+/* Overload "argc" and "argv" */
+String *argv_template_string;
+String *argc_template_string;
+
+namespace {
+struct Overloaded {
+ Node *n; /* Node */
+ int argc; /* Argument count */
+ ParmList *parms; /* Parameters used for overload check */
+ int error; /* Ambiguity error */
+ bool implicitconv_function; /* For ordering implicitconv functions*/
+};
+}
+
+static int fast_dispatch_mode = 0;
+static int cast_dispatch_mode = 0;
+
+/* Set fast_dispatch_mode */
+void Wrapper_fast_dispatch_mode_set(int flag) {
+ fast_dispatch_mode = flag;
+}
+
+void Wrapper_cast_dispatch_mode_set(int flag) {
+ cast_dispatch_mode = flag;
+}
+
+/* -----------------------------------------------------------------------------
+ * mark_implicitconv_function()
+ *
+ * Mark function if it contains an implicitconv type in the parameter list
+ * ----------------------------------------------------------------------------- */
+static void mark_implicitconv_function(Overloaded& onode) {
+ Parm *parms = onode.parms;
+ if (parms) {
+ bool is_implicitconv_function = false;
+ Parm *p = parms;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+ if (GetFlag(p, "implicitconv")) {
+ is_implicitconv_function = true;
+ break;
+ }
+ p = nextSibling(p);
+ }
+ if (is_implicitconv_function)
+ onode.implicitconv_function = true;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_rank()
+ *
+ * This function takes an overloaded declaration and creates a list that ranks
+ * all overloaded methods in an order that can be used to generate a dispatch
+ * function.
+ * Slight difference in the way this function is used by scripting languages and
+ * statically typed languages. The script languages call this method via
+ * Swig_overload_dispatch() - where wrappers for all overloaded methods are generated,
+ * however sometimes the code can never be executed. The non-scripting languages
+ * call this method via Swig_overload_check() for each overloaded method in order
+ * to determine whether or not the method should be wrapped. Note the slight
+ * difference when overloading methods that differ by const only. The
+ * scripting languages will ignore the const method, whereas the non-scripting
+ * languages ignore the first method parsed.
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
+ Overloaded nodes[MAX_OVERLOAD];
+ int nnodes = 0;
+ Node *o = Getattr(n, "sym:overloaded");
+ Node *c;
+
+ if (!o)
+ return 0;
+
+ c = o;
+ while (c) {
+ if (Getattr(c, "error")) {
+ c = Getattr(c, "sym:nextSibling");
+ continue;
+ }
+ /* if (SmartPointer && Getattr(c,"cplus:staticbase")) {
+ c = Getattr(c,"sym:nextSibling");
+ continue;
+ } */
+
+ /* Make a list of all the declarations (methods) that are overloaded with
+ * this one particular method name */
+ if (Getattr(c, "wrap:name")) {
+ assert(nnodes < MAX_OVERLOAD);
+ nodes[nnodes].n = c;
+ nodes[nnodes].parms = Getattr(c, "wrap:parms");
+ nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
+ nodes[nnodes].error = 0;
+ nodes[nnodes].implicitconv_function = false;
+
+ mark_implicitconv_function(nodes[nnodes]);
+ nnodes++;
+ }
+ c = Getattr(c, "sym:nextSibling");
+ }
+
+ /* Sort the declarations by required argument count */
+ {
+ int i, j;
+ for (i = 0; i < nnodes; i++) {
+ for (j = i + 1; j < nnodes; j++) {
+ if (nodes[i].argc > nodes[j].argc) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ }
+ }
+ }
+
+ /* Sort the declarations by argument types */
+ {
+ int i, j;
+ for (i = 0; i < nnodes - 1; i++) {
+ if (nodes[i].argc == nodes[i + 1].argc) {
+ for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
+ Parm *p1 = nodes[i].parms;
+ Parm *p2 = nodes[j].parms;
+ int differ = 0;
+ int num_checked = 0;
+ while (p1 && p2 && (num_checked < nodes[i].argc)) {
+ // Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
+ if (checkAttribute(p1, "tmap:in:numinputs", "0")) {
+ p1 = Getattr(p1, "tmap:in:next");
+ continue;
+ }
+ if (checkAttribute(p2, "tmap:in:numinputs", "0")) {
+ p2 = Getattr(p2, "tmap:in:next");
+ continue;
+ }
+ String *t1 = Getattr(p1, "tmap:typecheck:precedence");
+ String *t2 = Getattr(p2, "tmap:typecheck:precedence");
+ if ((!t1) && (!nodes[i].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
+ nodes[i].error = 1;
+ } else if ((!t2) && (!nodes[j].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
+ nodes[j].error = 1;
+ }
+ if (t1 && t2) {
+ int t1v, t2v;
+ t1v = atoi(Char(t1));
+ t2v = atoi(Char(t2));
+ differ = t1v - t2v;
+ } else if (!t1 && t2)
+ differ = 1;
+ else if (t1 && !t2)
+ differ = -1;
+ else if (!t1 && !t2)
+ differ = -1;
+ num_checked++;
+ if (differ > 0) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ break;
+ } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
+ t1 = Getattr(p1, "equivtype");
+ t1 = t1 ? t1 : Getattr(p1, "ltype");
+ if (!t1) {
+ t1 = SwigType_ltype(Getattr(p1, "type"));
+ if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t1);
+ }
+ Setattr(p1, "ltype", t1);
+ }
+ t2 = Getattr(p2, "equivtype");
+ t2 = t2 ? t2 : Getattr(p2, "ltype");
+ if (!t2) {
+ t2 = SwigType_ltype(Getattr(p2, "type"));
+ if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t2);
+ }
+ Setattr(p2, "ltype", t2);
+ }
+
+ /* Need subtype check here. If t2 is a subtype of t1, then we need to change the
+ order */
+
+ if (SwigType_issubtype(t2, t1)) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+
+ if (Strcmp(t1, t2) != 0) {
+ differ = 1;
+ break;
+ }
+ } else if (differ) {
+ break;
+ }
+ if (Getattr(p1, "tmap:in:next")) {
+ p1 = Getattr(p1, "tmap:in:next");
+ } else {
+ p1 = nextSibling(p1);
+ }
+ if (Getattr(p2, "tmap:in:next")) {
+ p2 = Getattr(p2, "tmap:in:next");
+ } else {
+ p2 = nextSibling(p2);
+ }
+ }
+ if (!differ) {
+ /* See if declarations differ by const only */
+ String *decl1 = Getattr(nodes[i].n, "decl");
+ String *decl2 = Getattr(nodes[j].n, "decl");
+ if (decl1 && decl2) {
+ /* Remove ref-qualifiers. Note that rvalue ref-qualifiers are already ignored and
+ * it is illegal to overload a function with and without ref-qualifiers. So with
+ * all the combinations of ref-qualifiers and cv-qualifiers, we just detect
+ * the cv-qualifier (const) overloading. */
+ String *d1 = Copy(decl1);
+ String *d2 = Copy(decl2);
+ if (SwigType_isreference(d1) || SwigType_isrvalue_reference(d1)) {
+ Delete(SwigType_pop(d1));
+ }
+ if (SwigType_isreference(d2) || SwigType_isrvalue_reference(d2)) {
+ Delete(SwigType_pop(d2));
+ }
+ String *dq1 = Copy(d1);
+ String *dq2 = Copy(d2);
+ if (SwigType_isconst(d1)) {
+ Delete(SwigType_pop(dq1));
+ }
+ if (SwigType_isconst(d2)) {
+ Delete(SwigType_pop(dq2));
+ }
+ if (Strcmp(dq1, dq2) == 0) {
+
+ if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
+ if (script_lang_wrapping) {
+ // Swap nodes so that the const method gets ignored (shadowed by the non-const method)
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ Delete(dq1);
+ Delete(dq2);
+ }
+ }
+ if (!differ) {
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ List *result = NewList();
+ {
+ int i;
+ int argc_changed_index = -1;
+ for (i = 0; i < nnodes; i++) {
+ if (nodes[i].error)
+ Setattr(nodes[i].n, "overload:ignore", "1");
+ Append(result, nodes[i].n);
+ // Printf(stdout,"[ %d ] %d %s\n", i, nodes[i].implicitconv_function, ParmList_errorstr(nodes[i].parms));
+ if (i == nnodes-1 || nodes[i].argc != nodes[i+1].argc) {
+ if (argc_changed_index+2 < nnodes && (nodes[argc_changed_index+1].argc == nodes[argc_changed_index+2].argc)) {
+ // Add additional implicitconv functions in same order as already ranked.
+ // Consider overloaded functions by argument count... only add additional implicitconv functions if
+ // the number of functions with the same arg count > 1, ie, only if overloaded by same argument count.
+ int j;
+ for (j = argc_changed_index + 1; j <= i; j++) {
+ if (nodes[j].implicitconv_function) {
+ SetFlag(nodes[j].n, "implicitconvtypecheckoff");
+ Append(result, nodes[j].n);
+ // Printf(stdout,"[ %d ] %d + %s\n", j, nodes[j].implicitconv_function, ParmList_errorstr(nodes[j].parms));
+ }
+ }
+ }
+ argc_changed_index = i;
+ }
+ }
+ }
+ return result;
+}
+
+// /* -----------------------------------------------------------------------------
+// * print_typecheck()
+// * ----------------------------------------------------------------------------- */
+
+static bool print_typecheck(String *f, int j, Parm *pj, bool implicitconvtypecheckoff) {
+ char tmp[256];
+ sprintf(tmp, Char(argv_template_string), j);
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ tm = Copy(tm);
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv && !implicitconvtypecheckoff) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, tm, "\n", NIL);
+ Delete(tm);
+ return true;
+ } else
+ return false;
+}
+
+/* -----------------------------------------------------------------------------
+ * ReplaceFormat()
+ * ----------------------------------------------------------------------------- */
+
+static String *ReplaceFormat(const_String_or_char_ptr fmt, int j) {
+ String *lfmt = NewString(fmt);
+ char buf[50];
+ sprintf(buf, "%d", j);
+ Replaceall(lfmt, "$numargs", buf);
+ int i;
+ String *commaargs = NewString("");
+ for (i = 0; i < j; i++) {
+ Printv(commaargs, ", ", NIL);
+ Printf(commaargs, Char(argv_template_string), i);
+ }
+ Replaceall(lfmt, "$commaargs", commaargs);
+ return lfmt;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_dispatch()
+ *
+ * Generate a dispatch function. argc is assumed to hold the argument count.
+ * argv is the argument vector.
+ *
+ * Note that for C++ class member functions, Swig_overload_dispatch() assumes
+ * that argc includes the "self" argument and that the first element of argv[]
+ * is the "self" argument. So for a member function:
+ *
+ * Foo::bar(int x, int y, int z);
+ *
+ * the argc should be 4 (not 3!) and the first element of argv[] would be
+ * the appropriate scripting language reference to "self". For regular
+ * functions (and static class functions) the argc and argv only include
+ * the regular function arguments.
+ * ----------------------------------------------------------------------------- */
+
+/*
+ Cast dispatch mechanism.
+*/
+String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
+ int i, j;
+
+ *maxargs = 1;
+
+ String *f = NewString("");
+ String *sw = NewString("");
+ Printf(f, "{\n");
+ Printf(f, "unsigned long _index = 0;\n");
+ Printf(f, "SWIG_TypeRank _rank = 0; \n");
+
+ /* Get a list of methods ranked by precedence values and argument count */
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+
+ /* Loop over the functions */
+
+ bool emitcheck = true;
+ for (i = 0; i < nfunc; i++) {
+ int fn = 0;
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+
+ if (num_required == num_arguments) {
+ Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
+ } else {
+ Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
+ }
+ Printf(f, "SWIG_TypeRank _ranki = 0;\n");
+ Printf(f, "SWIG_TypeRank _rankm = 0;\n");
+ if (num_arguments)
+ Printf(f, "SWIG_TypeRank _pi = 1;\n");
+
+ /* create a list with the wrappers that collide with the
+ current one based on argument number */
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; k++) {
+ Node *nk = Getitem(dispatch, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
+ Append(coll, nk);
+ }
+
+ // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
+
+ int num_braces = 0;
+ bool test = (num_arguments > 0);
+ if (test) {
+ int need_v = 1;
+ j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
+ pj = Getattr(pj, "tmap:in:next");
+ continue;
+ }
+
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ tm = Copy(tm);
+ /* normalise for comparison later */
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+
+ /* if all the wrappers have the same type check on this
+ argument we can optimize it out */
+ for (int k = 0; k < Len(coll) && !emitcheck; k++) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ /* finds arg j on the collider wrapper */
+ while (pl && l <= j) {
+ if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
+ pl = Getattr(pl, "tmap:in:next");
+ continue;
+ }
+ if (l == j) {
+ /* we are at arg j, so we compare the tmaps now */
+ String *tml = Getattr(pl, "tmap:typecheck");
+ /* normalise it before comparing */
+ if (tml)
+ Replaceid(tml, Getattr(pl, "lname"), "_v");
+ if (!tml || Cmp(tm, tml))
+ emitcheck = true;
+ //printf("tmap: %s[%d] (%d) => %s\n\n",
+ // Char(Getattr(nk, "sym:name")),
+ // l, emitcheck, tml?Char(tml):0);
+ }
+ Parm *pl1 = Getattr(pl, "tmap:in:next");
+ if (pl1)
+ pl = pl1;
+ else
+ pl = nextSibling(pl);
+ l++;
+ }
+ }
+
+ if (emitcheck) {
+ if (need_v) {
+ Printf(f, "int _v = 0;\n");
+ need_v = 0;
+ }
+ if (j >= num_required) {
+ Printf(f, "if (%s > %d) {\n", argc_template_string, j);
+ num_braces++;
+ }
+ String *tmp = NewStringf(argv_template_string, j);
+
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv && !implicitconvtypecheckoff) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, "{\n", tm, "}\n", NIL);
+ Delete(tm);
+ fn = i + 1;
+ Printf(f, "if (!_v) goto check_%d;\n", fn);
+ Printf(f, "_ranki += _v*_pi;\n");
+ Printf(f, "_rankm += _pi;\n");
+ Printf(f, "_pi *= SWIG_MAXCASTRANK;\n");
+ }
+ }
+ if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
+ /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'.\n",
+ Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Dispatching calls to this method may not work correctly, see the 'Typemaps and Overloading' section in the Typemaps chapter of the SWIG documentation.\n");
+ }
+ Parm *pj1 = Getattr(pj, "tmap:in:next");
+ if (pj1)
+ pj = pj1;
+ else
+ pj = nextSibling(pj);
+ j++;
+ }
+ }
+
+ /* close braces */
+ for ( /* empty */ ; num_braces > 0; num_braces--)
+ Printf(f, "}\n");
+
+ Printf(f, "if (!_index || (_ranki < _rank)) {\n");
+ Printf(f, " _rank = _ranki; _index = %d;\n", i + 1);
+ Printf(f, " if (_rank == _rankm) goto dispatch;\n");
+ Printf(f, "}\n");
+ String *lfmt = ReplaceFormat(fmt, num_arguments);
+ Printf(sw, "case %d:\n", i + 1);
+ Printf(sw, Char(lfmt), Getattr(ni, "wrap:name"));
+ Printf(sw, "\n");
+
+ Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (fn)
+ Printf(f, "check_%d:\n\n", fn);
+
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
+
+ Delete(lfmt);
+ Delete(coll);
+ }
+ Delete(dispatch);
+ Printf(f, "dispatch:\n");
+ Printf(f, "switch(_index) {\n");
+ Printf(f, "%s", sw);
+ Printf(f, "}\n");
+
+ Printf(f, "}\n");
+ return f;
+}
+
+/*
+ Fast dispatch mechanism, provided by Salvador Fandi~no Garc'ia (#930586).
+*/
+static String *overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) {
+ int i, j;
+
+ *maxargs = 1;
+
+ String *f = NewString("");
+
+ /* Get a list of methods ranked by precedence values and argument count */
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+
+ /* Loop over the functions */
+
+ for (i = 0; i < nfunc; i++) {
+ int fn = 0;
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+
+ if (num_required == num_arguments) {
+ Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
+ } else {
+ Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
+ }
+
+ /* create a list with the wrappers that collide with the
+ current one based on argument number */
+ List *coll = NewList();
+ for (int k = i + 1; k < nfunc; k++) {
+ Node *nk = Getitem(dispatch, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nrk = emit_num_required(pk);
+ int nak = emit_num_arguments(pk);
+ if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
+ Append(coll, nk);
+ }
+
+ // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
+
+ bool emitcheck = false;
+ int num_braces = 0;
+ bool test = (Len(coll) > 0 && num_arguments);
+ if (test) {
+ int need_v = 1;
+ j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
+ pj = Getattr(pj, "tmap:in:next");
+ continue;
+ }
+
+ String *tm = Getattr(pj, "tmap:typecheck");
+ if (tm) {
+ tm = Copy(tm);
+ /* normalise for comparison later */
+ Replaceid(tm, Getattr(pj, "lname"), "_v");
+
+ /* if all the wrappers have the same type check on this
+ argument we can optimize it out */
+ emitcheck = false;
+ for (int k = 0; k < Len(coll) && !emitcheck; k++) {
+ Node *nk = Getitem(coll, k);
+ Parm *pk = Getattr(nk, "wrap:parms");
+ int nak = emit_num_arguments(pk);
+ if (nak <= j)
+ continue;
+ int l = 0;
+ Parm *pl = pk;
+ /* finds arg j on the collider wrapper */
+ while (pl && l <= j) {
+ if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
+ pl = Getattr(pl, "tmap:in:next");
+ continue;
+ }
+ if (l == j) {
+ /* we are at arg j, so we compare the tmaps now */
+ String *tml = Getattr(pl, "tmap:typecheck");
+ /* normalise it before comparing */
+ if (tml)
+ Replaceid(tml, Getattr(pl, "lname"), "_v");
+ if (!tml || Cmp(tm, tml))
+ emitcheck = true;
+ //printf("tmap: %s[%d] (%d) => %s\n\n",
+ // Char(Getattr(nk, "sym:name")),
+ // l, emitcheck, tml?Char(tml):0);
+ }
+ Parm *pl1 = Getattr(pl, "tmap:in:next");
+ if (pl1)
+ pl = pl1;
+ else
+ pl = nextSibling(pl);
+ l++;
+ }
+ }
+
+ if (emitcheck) {
+ if (need_v) {
+ Printf(f, "int _v = 0;\n");
+ need_v = 0;
+ }
+ if (j >= num_required) {
+ Printf(f, "if (%s > %d) {\n", argc_template_string, j);
+ num_braces++;
+ }
+ String *tmp = NewStringf(argv_template_string, j);
+
+ String *conv = Getattr(pj, "implicitconv");
+ if (conv && !implicitconvtypecheckoff) {
+ Replaceall(tm, "$implicitconv", conv);
+ } else {
+ Replaceall(tm, "$implicitconv", "0");
+ }
+ Replaceall(tm, "$input", tmp);
+ Printv(f, "{\n", tm, "}\n", NIL);
+ Delete(tm);
+ fn = i + 1;
+ Printf(f, "if (!_v) goto check_%d;\n", fn);
+ }
+ }
+ if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
+ /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'.\n",
+ Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Dispatching calls to this method may not work correctly, see the 'Typemaps and Overloading' section in the Typemaps chapter of the SWIG documentation.\n");
+ }
+ Parm *pj1 = Getattr(pj, "tmap:in:next");
+ if (pj1)
+ pj = pj1;
+ else
+ pj = nextSibling(pj);
+ j++;
+ }
+ }
+
+ /* close braces */
+ for ( /* empty */ ; num_braces > 0; num_braces--)
+ Printf(f, "}\n");
+
+ // The language module may want to generate different code for last overloaded function called (with same number of arguments)
+ String *lfmt = ReplaceFormat(!emitcheck && fmt_fastdispatch ? fmt_fastdispatch : fmt, num_arguments);
+ Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
+
+ Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (fn)
+ Printf(f, "check_%d:\n\n", fn);
+
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
+
+ Delete(lfmt);
+ Delete(coll);
+ }
+ Delete(dispatch);
+ return f;
+}
+
+String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs, const_String_or_char_ptr fmt_fastdispatch) {
+
+ if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) {
+ return overload_dispatch_fast(n, fmt, maxargs, fmt_fastdispatch);
+ }
+
+ int i, j;
+
+ *maxargs = 1;
+
+ String *f = NewString("");
+
+ /* Get a list of methods ranked by precedence values and argument count */
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+
+ /* Loop over the functions */
+
+ for (i = 0; i < nfunc; i++) {
+ Node *ni = Getitem(dispatch, i);
+ Parm *pi = Getattr(ni, "wrap:parms");
+ bool implicitconvtypecheckoff = GetFlag(ni, "implicitconvtypecheckoff") != 0;
+ int num_required = emit_num_required(pi);
+ int num_arguments = emit_num_arguments(pi);
+ if (GetFlag(n, "wrap:this")) {
+ num_required++;
+ num_arguments++;
+ }
+ if (num_arguments > *maxargs)
+ *maxargs = num_arguments;
+
+ if (num_required == num_arguments) {
+ Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
+ } else {
+ Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
+ }
+
+ if (num_arguments) {
+ Printf(f, "int _v = 0;\n");
+ }
+
+ int num_braces = 0;
+ j = 0;
+ Parm *pj = pi;
+ while (pj) {
+ if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
+ pj = Getattr(pj, "tmap:in:next");
+ continue;
+ }
+ if (j >= num_required) {
+ String *lfmt = ReplaceFormat(fmt, num_arguments);
+ Printf(f, "if (%s <= %d) {\n", argc_template_string, j);
+ Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
+ Printf(f, "}\n");
+ Delete(lfmt);
+ }
+ if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj, implicitconvtypecheckoff)) {
+ Printf(f, "if (_v) {\n");
+ num_braces++;
+ }
+ if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
+ /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'.\n",
+ Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
+ Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
+ "Dispatching calls to this method may not work correctly, see the 'Typemaps and Overloading' section in the Typemaps chapter of the SWIG documentation.\n");
+ }
+ Parm *pk = Getattr(pj, "tmap:in:next");
+ if (pk)
+ pj = pk;
+ else
+ pj = nextSibling(pj);
+ j++;
+ }
+ String *lfmt = ReplaceFormat(fmt, num_arguments);
+ Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
+ Delete(lfmt);
+ /* close braces */
+ for ( /* empty */ ; num_braces > 0; num_braces--)
+ Printf(f, "}\n");
+ Printf(f, "}\n"); /* braces closes "if" for this method */
+ if (implicitconvtypecheckoff)
+ Delattr(ni, "implicitconvtypecheckoff");
+ }
+ Delete(dispatch);
+ return f;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_overload_check()
+ * ----------------------------------------------------------------------------- */
+void Swig_overload_check(Node *n) {
+ Swig_overload_rank(n, false);
+}
diff --git a/contrib/tools/swig/Source/Modules/perl5.cxx b/contrib/tools/swig/Source/Modules/perl5.cxx
new file mode 100644
index 00000000000..e6a50466e1d
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/perl5.cxx
@@ -0,0 +1,2513 @@
+/* ----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * perl5.cxx
+ *
+ * Perl5 language module for SWIG.
+ * ------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+static const char *usage = "\
+Perl 5 Options (available with -perl5)\n\
+ -compat - Compatibility mode\n\
+ -const - Wrap constants as constants and not variables (implies -proxy)\n\
+ -nopm - Do not generate the .pm file\n\
+ -noproxy - Don't create proxy classes\n\
+ -proxy - Create proxy classes (enabled by default)\n\
+ -static - Omit code related to dynamic loading\n\
+\n";
+
+static int compat = 0;
+
+static int no_pmfile = 0;
+
+static int export_all = 0;
+
+/*
+ * pmfile
+ * set by the -pm flag, overrides the name of the .pm file
+ */
+static String *pmfile = 0;
+
+/*
+ * module
+ * set by the %module directive, e.g. "Xerces". It will determine
+ * the name of the .pm file, and the dynamic library, and the name
+ * used by any module wanting to %import the module.
+ */
+static String *module = 0;
+
+/*
+ * namespace_module
+ * the fully namespace qualified name of the module. It will be used
+ * to set the package namespace in the .pm file, as well as the name
+ * of the initialization methods in the glue library. This will be
+ * the same as module, above, unless the %module directive is given
+ * the 'package' option, e.g. %module(package="Foo::Bar") "baz"
+ */
+static String *namespace_module = 0;
+
+/*
+ * cmodule
+ * the namespace of the internal glue code, set to the value of
+ * module with a 'c' appended
+ */
+static String *cmodule = 0;
+
+/*
+ * dest_package
+ * an optional namespace to put all classes into. Specified by using
+ * the %module(package="Foo::Bar") "baz" syntax
+ */
+static String *dest_package = 0;
+
+static String *command_tab = 0;
+static String *constant_tab = 0;
+static String *variable_tab = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_runtime_h = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static File *f_init = 0;
+static File *f_pm = 0;
+static String *pm; /* Package initialization code */
+static String *magic; /* Magic variable wrappers */
+
+static int staticoption = 0;
+
+// controlling verbose output
+static int verbose = 0;
+
+/* The following variables are used to manage Perl5 classes */
+
+static int blessed = 1; /* Enable object oriented features */
+static int do_constants = 0; /* Constant wrapping */
+static List *classlist = 0; /* List of classes */
+static int have_constructor = 0;
+static int have_destructor = 0;
+static int have_data_members = 0;
+static String *class_name = 0; /* Name of the class (what Perl thinks it is) */
+static String *real_classname = 0; /* Real name of C/C++ class */
+static String *fullclassname = 0;
+
+static String *pcode = 0; /* Perl code associated with each class */
+ /* static String *blessedmembers = 0; *//* Member data associated with each class */
+static int member_func = 0; /* Set to 1 when wrapping a member function */
+static String *func_stubs = 0; /* Function stubs */
+static String *const_stubs = 0; /* Constant stubs */
+static Node *const_stubs_enum_class = 0; /* Node for enum class if we're currently generating one */
+static String *var_stubs = 0; /* Variable stubs */
+static String *exported = 0; /* Exported symbols */
+static String *pragma_include = 0;
+static String *additional_perl_code = 0; /* Additional Perl code from %perlcode %{ ... %} */
+static Hash *operators = 0;
+static int have_operators = 0;
+
+class PERL5:public Language {
+public:
+
+ PERL5() {
+ Clear(argc_template_string);
+ Printv(argc_template_string, "items", NIL);
+ Clear(argv_template_string);
+ Printv(argv_template_string, "ST(%d)", NIL);
+ directorLanguage();
+ }
+
+ /* Test to see if a type corresponds to something wrapped with a shadow class */
+ Node *is_shadow(SwigType *t) {
+ Node *n;
+ n = classLookup(t);
+ /* Printf(stdout,"'%s' --> '%p'\n", t, n); */
+ if (n) {
+ if (!Getattr(n, "perl5:proxy")) {
+ setclassname(n);
+ }
+ return Getattr(n, "perl5:proxy");
+ }
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ int i = 1;
+
+ SWIG_library_directory("perl5");
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-package") == 0) {
+ Printv(stderr,
+ "*** -package is no longer supported\n*** use the directive '%module A::B::C' in your interface file instead\n*** see the Perl section in the manual for details.\n", NIL);
+ Exit(EXIT_FAILURE);
+ } else if (strcmp(argv[i], "-interface") == 0) {
+ Printv(stderr,
+ "*** -interface is no longer supported\n*** use the directive '%module A::B::C' in your interface file instead\n*** see the Perl section in the manual for details.\n", NIL);
+ Exit(EXIT_FAILURE);
+ } else if (strcmp(argv[i], "-exportall") == 0) {
+ export_all = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-static") == 0) {
+ staticoption = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ blessed = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ blessed = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-const") == 0) {
+ do_constants = 1;
+ blessed = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nopm") == 0) {
+ no_pmfile = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-pm") == 0) {
+ Swig_mark_arg(i);
+ i++;
+ pmfile = NewString(argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i],"-v") == 0) {
+ Swig_mark_arg(i);
+ verbose++;
+ } else if (strcmp(argv[i], "-compat") == 0) {
+ compat = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ Preprocessor_define("SWIGPERL 1", 0);
+ // SWIGPERL5 is deprecated, and no longer documented.
+ Preprocessor_define("SWIGPERL5 1", 0);
+ SWIG_config_file("perl5.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ *
+ * TODO: directors are disallowed in conjunction with many command
+ * line options. Some of them are probably safe, but it will take
+ * some effort to validate each one.
+ */
+ {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ int dirprot = 0;
+ if (Getattr(options, "dirprot"))
+ dirprot = 1;
+ if (Getattr(options, "nodirprot"))
+ dirprot = 0;
+ if (Getattr(options, "directors")) {
+ int allow = 1;
+ if (export_all) {
+ Printv(stderr, "*** directors are not supported with -exportall\n", NIL);
+ allow = 0;
+ }
+ if (staticoption) {
+ Printv(stderr, "*** directors are not supported with -static\n", NIL);
+ allow = 0;
+ }
+ if (!blessed) {
+ Printv(stderr, "*** directors are not supported with -noproxy\n", NIL);
+ allow = 0;
+ }
+ if (no_pmfile) {
+ Printv(stderr, "*** directors are not supported with -nopm\n", NIL);
+ allow = 0;
+ }
+ if (compat) {
+ Printv(stderr, "*** directors are not supported with -compat\n", NIL);
+ allow = 0;
+ }
+ if (allow) {
+ allow_directors();
+ if (dirprot)
+ allow_dirprot();
+ }
+ }
+ }
+ }
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ if (Swig_directors_enabled()) {
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ classlist = NewList();
+
+ pm = NewString("");
+ func_stubs = NewString("");
+ var_stubs = NewString("");
+ const_stubs = NewString("");
+ exported = NewString("");
+ magic = NewString("");
+ pragma_include = NewString("");
+ additional_perl_code = NewString("");
+
+ command_tab = NewString("static swig_command_info swig_commands[] = {\n");
+ constant_tab = NewString("static swig_constant_info swig_constants[] = {\n");
+ variable_tab = NewString("static swig_variable_info swig_variables[] = {\n");
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "PERL");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+ Printf(f_runtime, "#define SWIG_CASTRANK_MODE\n");
+ Printf(f_runtime, "\n");
+
+ // Is the imported module in another package? (IOW, does it use the
+ // %module(package="name") option and it's different than the package
+ // of this module.)
+ Node *mod = Getattr(n, "module");
+ Node *options = Getattr(mod, "options");
+ module = Copy(Getattr(n,"name"));
+
+ String *underscore_module = Copy(module);
+ Replaceall(underscore_module,":","_");
+
+ if (verbose > 0) {
+ fprintf(stdout, "top: using namespace_module: %s\n", Char(namespace_module));
+ }
+
+ if (Swig_directors_enabled()) {
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", underscore_module);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", underscore_module);
+ if (dirprot_mode()) {
+ Printf(f_directors_h, "#include <map>\n");
+ Printf(f_directors_h, "#include <string>\n\n");
+ }
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(magic, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ if (verbose > 0) {
+ fprintf(stdout, "top: using module: %s\n", Char(module));
+ }
+
+ dest_package = options ? Getattr(options, "package") : 0;
+ if (dest_package) {
+ namespace_module = Copy(dest_package);
+ if (verbose > 0) {
+ fprintf(stdout, "top: Found package: %s\n",Char(dest_package));
+ }
+ } else {
+ namespace_module = Copy(module);
+ if (verbose > 0) {
+ fprintf(stdout, "top: No package found\n");
+ }
+ }
+ /* If we're in blessed mode, change the package name to "packagec" */
+
+ if (blessed) {
+ cmodule = NewStringf("%sc",namespace_module);
+ } else {
+ cmodule = NewString(namespace_module);
+ }
+
+ /* Create a .pm file
+ * Need to strip off any prefixes that might be found in
+ * the module name */
+
+ if (no_pmfile) {
+ f_pm = NewString(0);
+ } else {
+ if (!pmfile) {
+ char *m = Char(module) + Len(module);
+ while (m != Char(module)) {
+ if (*m == ':') {
+ m++;
+ break;
+ }
+ m--;
+ }
+ pmfile = NewStringf("%s.pm", m);
+ }
+ String *filen = NewStringf("%s%s", SWIG_output_directory(), pmfile);
+ if ((f_pm = NewFile(filen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(filen);
+ filen = NULL;
+ Swig_register_filebyname("pm", f_pm);
+ Swig_register_filebyname("perl", f_pm);
+ }
+ {
+ String *boot_name = NewStringf("boot_%s", underscore_module);
+ Printf(f_header,"#define SWIG_init %s\n\n", boot_name);
+ Printf(f_header,"#define SWIG_name \"%s::%s\"\n", cmodule, boot_name);
+ Printf(f_header,"#define SWIG_prefix \"%s::\"\n", cmodule);
+ Delete(boot_name);
+ }
+
+ Swig_banner_target_lang(f_pm, "#");
+ Printf(f_pm, "\n");
+
+ Printf(f_pm, "package %s;\n", module);
+
+ /*
+ * If the package option has been given we are placing our
+ * symbols into some other packages namespace, so we do not
+ * mess with @ISA or require for that package
+ */
+ if (dest_package) {
+ Printf(f_pm,"use base qw(DynaLoader);\n");
+ } else {
+ Printf(f_pm,"use base qw(Exporter);\n");
+ if (!staticoption) {
+ Printf(f_pm,"use base qw(DynaLoader);\n");
+ }
+ }
+
+ /* Start creating magic code */
+
+ Printv(magic,
+ "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n",
+ "#define MAGIC_CLASS\n",
+ "SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {\n",
+ tab4, "MAGIC_PPERL\n", tab4, "croak(\"Value is read-only.\");\n", tab4, "return 0;\n", "}\n", NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ /* emit wrappers */
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ String *base = NewString("");
+
+ /* Dump out variable wrappers */
+
+ Printv(magic, "\n#ifdef __cplusplus\n}\n#endif\n", NIL);
+
+ Printf(f_header, "%s\n", magic);
+
+ String *type_table = NewString("");
+
+ /* Patch the type table to reflect the names used by shadow classes */
+ if (blessed) {
+ Iterator cls;
+ for (cls = First(classlist); cls.item; cls = Next(cls)) {
+ String *pname = Getattr(cls.item, "perl5:proxy");
+ if (pname) {
+ SwigType *type = Getattr(cls.item, "classtypeobj");
+ if (!type)
+ continue; /* If unnamed class, no type will be found */
+ type = Copy(type);
+
+ SwigType_add_pointer(type);
+ String *mangled = SwigType_manglestr(type);
+ SwigType_remember_mangleddata(mangled, NewStringf("\"%s\"", pname));
+ Delete(type);
+ Delete(mangled);
+ }
+ }
+ }
+ SwigType_emit_type_table(f_runtime, type_table);
+
+ Printf(f_wrappers, "%s", type_table);
+ Delete(type_table);
+
+ Printf(constant_tab, "{0,0,0,0,0,0}\n};\n");
+ Printv(f_wrappers, constant_tab, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ Printf(f_init, "\t ST(0) = &PL_sv_yes;\n");
+ Printf(f_init, "\t XSRETURN(1);\n");
+ Printf(f_init, "}\n");
+
+ /* Finish off tables */
+ Printf(variable_tab, "{0,0,0,0}\n};\n");
+ Printv(f_wrappers, variable_tab, NIL);
+
+ Printf(command_tab, "{0,0}\n};\n");
+ Printv(f_wrappers, command_tab, NIL);
+
+
+ Printf(f_pm, "package %s;\n", cmodule);
+
+ if (!staticoption) {
+ Printf(f_pm,"bootstrap %s;\n", module);
+ } else {
+ Printf(f_pm,"package %s;\n", cmodule);
+ Printf(f_pm,"boot_%s();\n", underscore_module);
+ }
+
+ Printf(f_pm, "package %s;\n", module);
+ /*
+ * If the package option has been given we are placing our
+ * symbols into some other packages namespace, so we do not
+ * mess with @EXPORT
+ */
+ if (!dest_package) {
+ Printf(f_pm,"@EXPORT = qw(%s);\n", exported);
+ }
+
+ Printf(f_pm, "%s", pragma_include);
+
+ if (blessed) {
+
+ /*
+ * These methods will be duplicated if package
+ * has been specified, so we do not output them
+ */
+ if (!dest_package) {
+ Printv(base, "\n# ---------- BASE METHODS -------------\n\n", "package ", namespace_module, ";\n\n", NIL);
+
+ /* Write out the TIE method */
+
+ Printv(base, "sub TIEHASH {\n", tab4, "my ($classname,$obj) = @_;\n", tab4, "return bless $obj, $classname;\n", "}\n\n", NIL);
+
+ /* Output a CLEAR method. This is just a place-holder, but by providing it we
+ * can make declarations such as
+ * %$u = ( x => 2, y=>3, z =>4 );
+ *
+ * Where x,y,z are the members of some C/C++ object. */
+
+ Printf(base, "sub CLEAR { }\n\n");
+
+ /* Output default firstkey/nextkey methods */
+
+ Printf(base, "sub FIRSTKEY { }\n\n");
+ Printf(base, "sub NEXTKEY { }\n\n");
+
+ /* Output a FETCH method. This is actually common to all classes */
+ Printv(base,
+ "sub FETCH {\n",
+ tab4, "my ($self,$field) = @_;\n", tab4, "my $member_func = \"swig_${field}_get\";\n", tab4, "$self->$member_func();\n", "}\n\n", NIL);
+
+ /* Output a STORE method. This is also common to all classes (might move to base class) */
+
+ Printv(base,
+ "sub STORE {\n",
+ tab4, "my ($self,$field,$newval) = @_;\n",
+ tab4, "my $member_func = \"swig_${field}_set\";\n", tab4, "$self->$member_func($newval);\n", "}\n\n", NIL);
+
+ /* Output a 'this' method */
+
+ Printv(base, "sub this {\n", tab4, "my $ptr = shift;\n", tab4, "return tied(%$ptr);\n", "}\n\n", NIL);
+
+ Printf(f_pm, "%s", base);
+ }
+
+ /* Emit function stubs for stand-alone functions */
+ Printf(f_pm, "\n# ------- FUNCTION WRAPPERS --------\n\n");
+ Printf(f_pm, "package %s;\n\n", namespace_module);
+ Printf(f_pm, "%s", func_stubs);
+
+ /* Emit package code for different classes */
+ Printf(f_pm, "%s", pm);
+
+ if (Len(const_stubs) > 0) {
+ /* Emit constant stubs */
+ Printf(f_pm, "\n# ------- CONSTANT STUBS -------\n\n");
+ Printf(f_pm, "%s", const_stubs);
+ }
+
+ /* Emit variable stubs */
+
+ Printf(f_pm, "\n# ------- VARIABLE STUBS --------\n\n");
+ Printf(f_pm, "package %s;\n\n", namespace_module);
+ Printf(f_pm, "%s", var_stubs);
+ }
+
+ /* Add additional Perl code at the end */
+ Printf(f_pm, "%s", additional_perl_code);
+
+ Printf(f_pm, "1;\n");
+ Delete(f_pm);
+ Delete(base);
+ Delete(dest_package);
+ Delete(underscore_module);
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ Dump(f_directors, f_begin);
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_directors);
+ Delete(f_directors_h);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective(Node *n)
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ if (blessed) {
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ Printf(f_pm, "require %s;\n", modname);
+ }
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *overname = 0;
+ int director_method = 0;
+
+ Parm *p;
+ int i;
+ Wrapper *f;
+ char source[256], temp[256];
+ String *tm;
+ String *cleanup, *outarg;
+ int num_saved = 0;
+ int num_arguments, num_required;
+ int varargs = 0;
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+ cleanup = NewString("");
+ outarg = NewString("");
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+ Printv(f->def, "XS(", wname, ") {\n", "{\n", /* scope to destroy C++ objects before croaking */
+ NIL);
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+ varargs = emit_isvarargs(l);
+
+ Wrapper_add_local(f, "argvi", "int argvi = 0");
+
+ /* Check the number of arguments */
+ if (!varargs) {
+ Printf(f->code, " if ((items < %d) || (items > %d)) {\n", num_required, num_arguments);
+ } else {
+ Printf(f->code, " if (items < %d) {\n", num_required);
+ }
+ Printf(f->code, " SWIG_croak(\"Usage: %s\");\n", usage_func(Char(iname), returntype, l));
+ Printf(f->code, "}\n");
+
+ /* Write code to extract parameters. */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Skip ignored arguments */
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+
+ /* Produce string representation of source and target arguments */
+ sprintf(source, "ST(%d)", i);
+
+ if (i >= num_required) {
+ Printf(f->code, " if (items > %d) {\n", i);
+ }
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source); /* Save input location */
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ Printf(f->code, "%s\n", tm);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ }
+ if (i >= num_required) {
+ Printf(f->code, " }\n");
+ }
+ }
+
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ sprintf(source, "ST(%d)", i);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printf(f->code, "if (items >= %d) {\n", i);
+ Printv(f->code, tm, "\n", NIL);
+ Printf(f->code, "}\n");
+ }
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ num_saved = 0;
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ SwigType *t = Getattr(p, "type");
+ Replaceall(tm, "$result", "ST(argvi)");
+ if (is_shadow(t)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+
+ String *in = Getattr(p, "emit:input");
+ if (in) {
+ sprintf(temp, "_saved[%d]", num_saved);
+ Replaceall(tm, "$arg", temp);
+ Replaceall(tm, "$input", temp);
+ Printf(f->code, "_saved[%d] = %s;\n", num_saved, in);
+ num_saved++;
+ }
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* If there were any saved arguments, emit a local variable for them */
+ if (num_saved) {
+ sprintf(temp, "_saved[%d]", num_saved);
+ Wrapper_add_localv(f, "_saved", "SV *", temp, NIL);
+ }
+
+ director_method = is_member_director(n) && !is_smart_pointer() && 0 != Cmp(nodeType(n), "destructor");
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
+ Printf(f->code, "SWIG_exception_fail(SWIG_RuntimeError, \"accessing protected member %s\");\n", name);
+ Append(f->code, "}\n");
+ }
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Printf(f->code, "upcall = director && SvSTASH(SvRV(ST(0))) == gv_stashpv(director->swig_get_class(), 0);\n");
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Append(f->code, "try {\n");
+ }
+
+ /* Now write code to make the function call */
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (director_method) {
+ Append(actioncode, "} catch (Swig::DirectorException& swig_err) {\n");
+ Append(actioncode, " sv_setsv(ERRSV, swig_err.getNative());\n");
+ Append(actioncode, " SWIG_fail;\n");
+ Append(actioncode, "}\n");
+ }
+
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ SwigType *t = Getattr(n, "type");
+ Replaceall(tm, "$result", "ST(argvi)");
+ if (is_shadow(t)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_OWNER");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printf(f->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), name);
+ }
+ emit_return_variable(n, returntype, f);
+
+ /* If there were any output args, take care of them. */
+
+ Printv(f->code, outarg, NIL);
+
+ /* If there was any cleanup, do that. */
+
+ Printv(f->code, cleanup, NIL);
+
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "ST(argvi)");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ Printv(f->code, "XSRETURN(argvi);\n", "fail:\n", cleanup, "SWIG_croak_null();\n" "}\n" "}\n", NIL);
+
+ /* Add the dXSARGS last */
+
+ Wrapper_add_local(f, "dXSARGS", "dXSARGS");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(f->code, "$symname", iname);
+
+ /* Dump the wrapper function */
+
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the function */
+
+ if (!Getattr(n, "sym:overloaded")) {
+ Printf(command_tab, "{\"%s::%s\", %s},\n", cmodule, iname, wname);
+ } else if (!Getattr(n, "sym:nextSibling")) {
+ /* Generate overloaded dispatch function */
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch_cast(n, "PUSHMARK(MARK); SWIG_CALLXS(%s); return;", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "XS(", dname, ") {\n", NIL);
+
+ Wrapper_add_local(df, "dXSARGS", "dXSARGS");
+ Printv(df->code, dispatch, "\n", NIL);
+ Printf(df->code, "croak(\"No matching function for overloaded '%s'\");\n", iname);
+ Printf(df->code, "XSRETURN(0);\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printf(command_tab, "{\"%s::%s\", %s},\n", cmodule, iname, dname);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ if (!Getattr(n, "sym:nextSibling")) {
+ if (export_all) {
+ Printf(exported, "%s ", iname);
+ }
+
+ /* --------------------------------------------------------------------
+ * Create a stub for this function, provided it's not a member function
+ * -------------------------------------------------------------------- */
+
+ if ((blessed) && (!member_func)) {
+ Printv(func_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL);
+ }
+
+ }
+ Delete(cleanup);
+ Delete(outarg);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+ virtual int variableWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ Wrapper *getf, *setf;
+ String *tm;
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+
+ String *get_name = Swig_name_wrapper(getname);
+ String *set_name = Swig_name_wrapper(setname);
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* Create a Perl function for setting the variable value */
+
+ int assignable = !is_immutable(n);
+ if (assignable) {
+ Setattr(n, "wrap:name", set_name);
+ Printf(setf->def, "SWIGCLASS_STATIC int %s(pTHX_ SV* sv, MAGIC * SWIGUNUSEDPARM(mg)) {\n", set_name);
+ Printv(setf->code, tab4, "MAGIC_PPERL\n", NIL);
+
+ /* Check for a few typemaps */
+ tm = Swig_typemap_lookup("varin", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$input", "sv");
+ /* Printf(setf->code,"%s\n", tm); */
+ emit_action_code(n, setf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_NOWRAP;
+ }
+ Printf(setf->code, "fail:\n");
+ Printf(setf->code, " return 1;\n}\n");
+ Replaceall(setf->code, "$symname", iname);
+ Wrapper_print(setf, magic);
+ }
+
+ /* Now write a function to evaluate the variable */
+ Setattr(n, "wrap:name", get_name);
+ int addfail = 0;
+ Printf(getf->def, "SWIGCLASS_STATIC int %s(pTHX_ SV *sv, MAGIC *SWIGUNUSEDPARM(mg)) {\n", get_name);
+ Printv(getf->code, tab4, "MAGIC_PPERL\n", NIL);
+
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "sv");
+ if (is_shadow(t)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ /* Printf(getf->code,"%s\n", tm); */
+ addfail = emit_action_code(n, getf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_NOWRAP;
+ }
+ Printf(getf->code, " return 1;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, " return 0;\n");
+ }
+ Append(getf->code, "}\n");
+
+
+ Replaceall(getf->code, "$symname", iname);
+ Wrapper_print(getf, magic);
+
+ String *tt = Getattr(n, "tmap:varout:type");
+ if (tt) {
+ tt = NewStringf("&%s", tt);
+ } else {
+ tt = NewString("0");
+ }
+ /* Now add symbol to the PERL interpreter */
+ if (!assignable) {
+ Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS swig_magic_readonly, MAGIC_CLASS ", get_name, ",", tt, " },\n", NIL);
+
+ } else {
+ Printv(variable_tab, tab4, "{ \"", cmodule, "::", iname, "\", MAGIC_CLASS ", set_name, ", MAGIC_CLASS ", get_name, ",", tt, " },\n", NIL);
+ }
+
+ /* If we're blessed, try to figure out what to do with the variable
+ 1. If it's a Perl object of some sort, create a tied-hash
+ around it.
+ 2. Otherwise, just hack Perl's symbol table */
+
+ if (blessed) {
+ if (is_shadow(t)) {
+ Printv(var_stubs,
+ "\nmy %__", iname, "_hash;\n",
+ "tie %__", iname, "_hash,\"", is_shadow(t), "\", $",
+ cmodule, "::", iname, ";\n", "$", iname, "= \\%__", iname, "_hash;\n", "bless $", iname, ", ", is_shadow(t), ";\n", NIL);
+ } else {
+ Printv(var_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL);
+ }
+ }
+ if (export_all)
+ Printf(exported, "$%s ", iname);
+
+ Delete(tt);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ Delete(getname);
+ Delete(setname);
+ Delete(set_name);
+ Delete(get_name);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ if (is_shadow(type)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ Printf(constant_tab, "%s,\n", tm);
+ } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ if (is_shadow(type)) {
+ Replaceall(tm, "$shadow", "SWIG_SHADOW");
+ } else {
+ Replaceall(tm, "$shadow", "0");
+ }
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ if (blessed) {
+ if (is_shadow(type)) {
+ Printv(var_stubs,
+ "\nmy %__", iname, "_hash;\n",
+ "tie %__", iname, "_hash,\"", is_shadow(type), "\", $",
+ cmodule, "::", iname, ";\n", "$", iname, "= \\%__", iname, "_hash;\n", "bless $", iname, ", ", is_shadow(type), ";\n", NIL);
+ } else if (do_constants) {
+ char *dcolon = Strstr(name, "::");
+ if (!dcolon) {
+ if (Len(const_stubs) == 0 || const_stubs_enum_class != NULL) {
+ Printf(const_stubs, "package %s;\n", namespace_module);
+ const_stubs_enum_class = NULL;
+ }
+ Printv(const_stubs, "sub ", iname, " () { $", cmodule, "::", iname, " }\n", NIL);
+ } else {
+ // C++11 strongly-typed enum.
+ Node *parent = Getattr(n, "parentNode");
+ if (const_stubs_enum_class != parent) {
+ Printf(const_stubs, "package %s::%s;\n", namespace_module, Getattr(parent, "sym:name"));
+ const_stubs_enum_class = parent;
+ }
+ Printv(const_stubs, "sub ", Getattr(n, "enumvalueDeclaration:sym:name"), " () { $", cmodule, "::", iname, " }\n", NIL);
+ }
+ } else {
+ Printv(var_stubs, "*", iname, " = *", cmodule, "::", iname, ";\n", NIL);
+ }
+ }
+ if (export_all) {
+ if (do_constants && !is_shadow(type)) {
+ Printf(exported, "%s ", name);
+ } else {
+ Printf(exported, "$%s ", iname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * usage_func()
+ * ------------------------------------------------------------ */
+ char *usage_func(char *iname, SwigType *, ParmList *l) {
+ static String *temp = 0;
+ Parm *p;
+ int i;
+
+ if (!temp)
+ temp = NewString("");
+ Clear(temp);
+ Printf(temp, "%s(", iname);
+
+ /* Now go through and print parameters */
+ p = l;
+ i = 0;
+ while (p != 0) {
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ if (!checkAttribute(p,"tmap:in:numinputs","0")) {
+ /* If parameter has been named, use that. Otherwise, just print a type */
+ if (SwigType_type(pt) != T_VOID) {
+ if (Len(pn) > 0) {
+ Printf(temp, "%s", pn);
+ } else {
+ Printf(temp, "%s", SwigType_str(pt, 0));
+ }
+ }
+ i++;
+ p = nextSibling(p);
+ if (p)
+ if (!checkAttribute(p,"tmap:in:numinputs","0"))
+ Putc(',', temp);
+ } else {
+ p = nextSibling(p);
+ if (p)
+ if ((i > 0) && (!checkAttribute(p,"tmap:in:numinputs","0")))
+ Putc(',', temp);
+ }
+ }
+ Printf(temp, ");");
+ return Char(temp);
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ String *funcname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(funcname, n))
+ return SWIG_ERROR;
+
+ Printf(command_tab, "{\"%s::%s\", %s},\n", cmodule, name, funcname);
+ if (export_all)
+ Printf(exported, "%s ", name);
+ if (blessed) {
+ Printv(func_stubs, "*", name, " = *", cmodule, "::", name, ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+/* ----------------------------------------------------------------------------
+ * OBJECT-ORIENTED FEATURES
+ *
+ * These extensions provide a more object-oriented interface to C++
+ * classes and structures. The code here is based on extensions
+ * provided by David Fletcher and Gary Holt.
+ *
+ * I have generalized these extensions to make them more general purpose
+ * and to resolve object-ownership problems.
+ *
+ * The approach here is very similar to the Python module :
+ * 1. All of the original methods are placed into a single
+ * package like before except that a 'c' is appended to the
+ * package name.
+ *
+ * 2. All methods and function calls are wrapped with a new
+ * perl function. While possibly inefficient this allows
+ * us to catch complex function arguments (which are hard to
+ * track otherwise).
+ *
+ * 3. Classes are represented as tied-hashes in a manner similar
+ * to Gary Holt's extension. This allows us to access
+ * member data.
+ *
+ * 4. Stand-alone (global) C functions are modified to take
+ * tied hashes as arguments for complex datatypes (if
+ * appropriate).
+ *
+ * 5. Global variables involving a class/struct is encapsulated
+ * in a tied hash.
+ *
+ * ------------------------------------------------------------------------- */
+
+
+ void setclassname(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *fullname;
+ String *actualpackage;
+ Node *clsmodule = Getattr(n, "module");
+
+ if (!clsmodule) {
+ /* imported module does not define a module name. Oh well */
+ return;
+ }
+
+ /* Do some work on the class name */
+ if (verbose > 0) {
+ String *modulename = Getattr(clsmodule, "name");
+ fprintf(stdout, "setclassname: Found sym:name: %s\n", Char(symname));
+ fprintf(stdout, "setclassname: Found module: %s\n", Char(modulename));
+ fprintf(stdout, "setclassname: No package found\n");
+ }
+
+ if (dest_package) {
+ fullname = NewStringf("%s::%s", namespace_module, symname);
+ } else {
+ actualpackage = Getattr(clsmodule,"name");
+
+ if (verbose > 0) {
+ fprintf(stdout, "setclassname: Found actualpackage: %s\n", Char(actualpackage));
+ }
+ if ((!compat) && (!Strchr(symname,':'))) {
+ fullname = NewStringf("%s::%s",actualpackage,symname);
+ } else {
+ fullname = NewString(symname);
+ }
+ }
+ if (verbose > 0) {
+ fprintf(stdout, "setclassname: setting proxy: %s\n", Char(fullname));
+ }
+ Setattr(n, "perl5:proxy", fullname);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+ virtual int classDeclaration(Node *n) {
+ /* Do some work on the class name */
+ if (!Getattr(n, "feature:onlychildren")) {
+ if (blessed) {
+ setclassname(n);
+ Append(classlist, n);
+ }
+ }
+
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+
+ if (blessed) {
+ have_constructor = 0;
+ have_operators = 0;
+ have_destructor = 0;
+ have_data_members = 0;
+ operators = NewHash();
+
+ class_name = Getattr(n, "sym:name");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ /* Use the fully qualified name of the Perl class */
+ if (!compat) {
+ fullclassname = NewStringf("%s::%s", namespace_module, class_name);
+ } else {
+ fullclassname = NewString(class_name);
+ }
+ real_classname = Getattr(n, "name");
+ pcode = NewString("");
+ // blessedmembers = NewString("");
+ }
+
+ /* Emit all of the members */
+ Language::classHandler(n);
+
+
+ /* Finish the rest of the class */
+ if (blessed) {
+ /* Generate a client-data entry */
+ SwigType *ct = NewStringf("p.%s", real_classname);
+ Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", SwigType_manglestr(ct), ", (void*) \"", fullclassname, "\");\n", NIL);
+ SwigType_remember(ct);
+ Delete(ct);
+
+ Printv(pm, "\n############# Class : ", fullclassname, " ##############\n", "\npackage ", fullclassname, ";\n", NIL);
+
+ if (have_operators) {
+ Printf(pm, "use overload\n");
+ Iterator ki;
+ for (ki = First(operators); ki.key; ki = Next(ki)) {
+ char *name = Char(ki.key);
+ // fprintf(stderr,"found name: <%s>\n", name);
+ if (strstr(name, "__eq__")) {
+ Printv(pm, tab4, "\"==\" => sub { $_[0]->__eq__($_[1])},\n",NIL);
+ } else if (strstr(name, "__ne__")) {
+ Printv(pm, tab4, "\"!=\" => sub { $_[0]->__ne__($_[1])},\n",NIL);
+ // there are no tests for this in operator_overload_runme.pl
+ // it is likely to be broken
+ // } else if (strstr(name, "__assign__")) {
+ // Printv(pm, tab4, "\"=\" => sub { $_[0]->__assign__($_[1])},\n",NIL);
+ } else if (strstr(name, "__str__")) {
+ Printv(pm, tab4, "'\"\"' => sub { $_[0]->__str__()},\n",NIL);
+ } else if (strstr(name, "__plusplus__")) {
+ Printv(pm, tab4, "\"++\" => sub { $_[0]->__plusplus__()},\n",NIL);
+ } else if (strstr(name, "__minmin__")) {
+ Printv(pm, tab4, "\"--\" => sub { $_[0]->__minmin__()},\n",NIL);
+ } else if (strstr(name, "__add__")) {
+ Printv(pm, tab4, "\"+\" => sub { $_[0]->__add__($_[1])},\n",NIL);
+ } else if (strstr(name, "__sub__")) {
+ Printv(pm, tab4, "\"-\" => sub { if( not $_[2] ) { $_[0]->__sub__($_[1]) }\n",NIL);
+ Printv(pm, tab8, "elsif( $_[0]->can('__rsub__') ) { $_[0]->__rsub__($_[1]) }\n",NIL);
+ Printv(pm, tab8, "else { die(\"reverse subtraction not supported\") }\n",NIL);
+ Printv(pm, tab8, "},\n",NIL);
+ } else if (strstr(name, "__mul__")) {
+ Printv(pm, tab4, "\"*\" => sub { $_[0]->__mul__($_[1])},\n",NIL);
+ } else if (strstr(name, "__div__")) {
+ Printv(pm, tab4, "\"/\" => sub { $_[0]->__div__($_[1])},\n",NIL);
+ } else if (strstr(name, "__mod__")) {
+ Printv(pm, tab4, "\"%\" => sub { $_[0]->__mod__($_[1])},\n",NIL);
+ // there are no tests for this in operator_overload_runme.pl
+ // it is likely to be broken
+ // } else if (strstr(name, "__and__")) {
+ // Printv(pm, tab4, "\"&\" => sub { $_[0]->__and__($_[1])},\n",NIL);
+
+ // there are no tests for this in operator_overload_runme.pl
+ // it is likely to be broken
+ // } else if (strstr(name, "__or__")) {
+ // Printv(pm, tab4, "\"|\" => sub { $_[0]->__or__($_[1])},\n",NIL);
+ } else if (strstr(name, "__gt__")) {
+ Printv(pm, tab4, "\">\" => sub { $_[0]->__gt__($_[1])},\n",NIL);
+ } else if (strstr(name, "__ge__")) {
+ Printv(pm, tab4, "\">=\" => sub { $_[0]->__ge__($_[1])},\n",NIL);
+ } else if (strstr(name, "__not__")) {
+ Printv(pm, tab4, "\"!\" => sub { $_[0]->__not__()},\n",NIL);
+ } else if (strstr(name, "__lt__")) {
+ Printv(pm, tab4, "\"<\" => sub { $_[0]->__lt__($_[1])},\n",NIL);
+ } else if (strstr(name, "__le__")) {
+ Printv(pm, tab4, "\"<=\" => sub { $_[0]->__le__($_[1])},\n",NIL);
+ } else if (strstr(name, "__pluseq__")) {
+ Printv(pm, tab4, "\"+=\" => sub { $_[0]->__pluseq__($_[1])},\n",NIL);
+ } else if (strstr(name, "__mineq__")) {
+ Printv(pm, tab4, "\"-=\" => sub { $_[0]->__mineq__($_[1])},\n",NIL);
+ } else if (strstr(name, "__neg__")) {
+ Printv(pm, tab4, "\"neg\" => sub { $_[0]->__neg__()},\n",NIL);
+ } else {
+ fprintf(stderr,"Unknown operator: %s\n", name);
+ }
+ }
+ Printv(pm, tab4,
+ "\"=\" => sub { my $class = ref($_[0]); $class->new($_[0]) },\n", NIL);
+ Printv(pm, tab4, "\"fallback\" => 1;\n", NIL);
+ }
+ // make use strict happy
+ Printv(pm, "use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);\n", NIL);
+
+ /* If we are inheriting from a base class, set that up */
+
+ Printv(pm, "@ISA = qw(", NIL);
+
+ /* Handle inheritance */
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "perl5:proxy");
+ if (!bname) {
+ b = Next(b);
+ continue;
+ }
+ Printv(pm, " ", bname, NIL);
+ b = Next(b);
+ }
+ }
+
+ /* Module comes last */
+ if (!compat || Cmp(namespace_module, fullclassname)) {
+ Printv(pm, " ", namespace_module, NIL);
+ }
+
+ Printf(pm, " );\n");
+
+ /* Dump out a hash table containing the pointers that we own */
+ Printf(pm, "%%OWNER = ();\n");
+ if (have_data_members || have_destructor)
+ Printf(pm, "%%ITERATORS = ();\n");
+
+ /* Dump out the package methods */
+
+ Printv(pm, pcode, NIL);
+ Delete(pcode);
+
+ /* Output methods for managing ownership */
+
+ String *director_disown;
+ if (Getattr(n, "perl5:directordisown")) {
+ director_disown = NewStringf("%s%s($self);\n", tab4, Getattr(n, "perl5:directordisown"));
+ } else {
+ director_disown = NewString("");
+ }
+ Printv(pm,
+ "sub DISOWN {\n",
+ tab4, "my $self = shift;\n",
+ director_disown,
+ tab4, "my $ptr = tied(%$self);\n",
+ tab4, "delete $OWNER{$ptr};\n",
+ "}\n\n", "sub ACQUIRE {\n", tab4, "my $self = shift;\n", tab4, "my $ptr = tied(%$self);\n", tab4, "$OWNER{$ptr} = 1;\n", "}\n\n", NIL);
+ Delete(director_disown);
+
+ /* Only output the following methods if a class has member data */
+
+ Delete(operators);
+ operators = 0;
+ if (Swig_directorclass(n)) {
+ /* director classes need a way to recover subclass instance attributes */
+ Node *get_attr = NewHash();
+ String *mrename;
+ String *symname = Getattr(n, "sym:name");
+ mrename = Swig_name_disown(NSPACE_TODO, symname);
+ Replaceall(mrename, "disown", "swig_get_attr");
+ String *type = NewString(getClassType());
+ String *name = NewString("self");
+ SwigType_add_pointer(type);
+ Parm *p = NewParm(type, name, n);
+ Delete(name);
+ Delete(type);
+ type = NewString("SV");
+ SwigType_add_pointer(type);
+ String *action = NewString("");
+ Printv(action, "{\n", " Swig::Director *director = SWIG_DIRECTOR_CAST(arg1);\n",
+ " result = sv_newmortal();\n" " if (director) sv_setsv(result, director->swig_get_self());\n", "}\n", NIL);
+ Setfile(get_attr, Getfile(n));
+ Setline(get_attr, Getline(n));
+ Setattr(get_attr, "wrap:action", action);
+ Setattr(get_attr, "name", mrename);
+ Setattr(get_attr, "sym:name", mrename);
+ Setattr(get_attr, "type", type);
+ Setattr(get_attr, "parms", p);
+ Delete(action);
+ Delete(type);
+ Delete(p);
+
+ member_func = 1;
+ functionWrapper(get_attr);
+ member_func = 0;
+ Delete(get_attr);
+
+ Printv(pm, "sub FETCH {\n", tab4, "my ($self,$field) = @_;\n", tab4, "my $member_func = \"swig_${field}_get\";\n", tab4,
+ "if (not $self->can($member_func)) {\n", tab8, "my $h = ", cmodule, "::", mrename, "($self);\n", tab8, "return $h->{$field} if $h;\n",
+ tab4, "}\n", tab4, "return $self->$member_func;\n", "}\n", "\n", "sub STORE {\n", tab4, "my ($self,$field,$newval) = @_;\n", tab4,
+ "my $member_func = \"swig_${field}_set\";\n", tab4, "if (not $self->can($member_func)) {\n", tab8, "my $h = ", cmodule, "::", mrename,
+ "($self);\n", tab8, "return $h->{$field} = $newval if $h;\n", tab4, "}\n", tab4, "return $self->$member_func($newval);\n", "}\n", NIL);
+
+ Delete(mrename);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ member_func = 1;
+ Language::memberfunctionHandler(n);
+ member_func = 0;
+
+ if ((blessed) && (!Getattr(n, "sym:nextSibling"))) {
+
+ if (Strstr(symname, "__eq__")) {
+ SetInt(operators, "__eq__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__ne__")) {
+ SetInt(operators, "__ne__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__assign__")) {
+ SetInt(operators, "__assign__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__str__")) {
+ SetInt(operators, "__str__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__add__")) {
+ SetInt(operators, "__add__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__sub__")) {
+ SetInt(operators, "__sub__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__mul__")) {
+ SetInt(operators, "__mul__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__div__")) {
+ SetInt(operators, "__div__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__mod__")) {
+ SetInt(operators, "__mod__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__and__")) {
+ SetInt(operators, "__and__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__or__")) {
+ SetInt(operators, "__or__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__not__")) {
+ SetInt(operators, "__not__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__gt__")) {
+ SetInt(operators, "__gt__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__ge__")) {
+ SetInt(operators, "__ge__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__lt__")) {
+ SetInt(operators, "__lt__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__le__")) {
+ SetInt(operators, "__le__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__neg__")) {
+ SetInt(operators, "__neg__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__plusplus__")) {
+ SetInt(operators, "__plusplus__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__minmin__")) {
+ SetInt(operators, "__minmin__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__mineq__")) {
+ SetInt(operators, "__mineq__", 1);
+ have_operators = 1;
+ } else if (Strstr(symname, "__pluseq__")) {
+ SetInt(operators, "__pluseq__", 1);
+ have_operators = 1;
+ }
+
+ if (Getattr(n, "feature:shadow")) {
+ String *plcode = perlcode(Getattr(n, "feature:shadow"), 0);
+ String *plaction = NewStringf("%s::%s", cmodule, Swig_name_member(NSPACE_TODO, class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ *
+ * Adds an instance member.
+ * ----------------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+
+ String *symname = Getattr(n, "sym:name");
+ /* SwigType *t = Getattr(n,"type"); */
+
+ /* Emit a pair of get/set functions for the variable */
+
+ member_func = 1;
+ Language::membervariableHandler(n);
+ member_func = 0;
+
+ if (blessed) {
+
+ Printv(pcode, "*swig_", symname, "_get = *", cmodule, "::", Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)), ";\n", NIL);
+ Printv(pcode, "*swig_", symname, "_set = *", cmodule, "::", Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)), ";\n", NIL);
+
+ /* Now we need to generate a little Perl code for this */
+
+ /* if (is_shadow(t)) {
+
+ *//* This is a Perl object that we have already seen. Add an
+ entry to the members list *//*
+ Printv(blessedmembers,
+ tab4, symname, " => '", is_shadow(t), "',\n",
+ NIL);
+
+ }
+ */
+ }
+ have_data_members++;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorDeclaration()
+ *
+ * Emits a blessed constructor for our class. In addition to our construct
+ * we manage a Perl hash table containing all of the pointers created by
+ * the constructor. This prevents us from accidentally trying to free
+ * something that wasn't necessarily allocated by malloc or new
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+
+ String *symname = Getattr(n, "sym:name");
+
+ member_func = 1;
+
+ Swig_save("perl5:constructorHandler", n, "parms", NIL);
+ if (Swig_directorclass(n)) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("SV");
+ SwigType_add_pointer(type);
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "O");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Setattr(n, "hidden", "1");
+ Delete(self);
+ }
+
+ String *saved_nc = none_comparison;
+ none_comparison = NewStringf("strcmp(SvPV_nolen(ST(0)), \"%s::%s\") != 0", module, class_name);
+ String *saved_director_prot_ctor_code = director_prot_ctor_code;
+ director_prot_ctor_code = NewStringf("if ($comparison) { /* subclassed */\n" " $director_new\n" "} else {\n"
+ "SWIG_exception_fail(SWIG_RuntimeError, \"accessing abstract class or protected constructor\");\n" "}\n");
+ Language::constructorHandler(n);
+ Delete(none_comparison);
+ none_comparison = saved_nc;
+ Delete(director_prot_ctor_code);
+ director_prot_ctor_code = saved_director_prot_ctor_code;
+ Swig_restore(n);
+
+ if ((blessed) && (!Getattr(n, "sym:nextSibling"))) {
+ if (Getattr(n, "feature:shadow")) {
+ String *plcode = perlcode(Getattr(n, "feature:shadow"), 0);
+ String *plaction = NewStringf("%s::%s", module, Swig_name_member(NSPACE_TODO, class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ if ((Cmp(symname, class_name) == 0)) {
+ /* Emit a blessed constructor */
+ Printf(pcode, "sub new {\n");
+ } else {
+ /* Constructor doesn't match classname so we'll just use the normal name */
+ Printv(pcode, "sub ", Swig_name_construct(NSPACE_TODO, symname), " {\n", NIL);
+ }
+
+ const char *pkg = getCurrentClass() && Swig_directorclass(getCurrentClass())? "$_[0]" : "shift";
+ Printv(pcode,
+ tab4, "my $pkg = ", pkg, ";\n",
+ tab4, "my $self = ", cmodule, "::", Swig_name_construct(NSPACE_TODO, symname), "(@_);\n", tab4, "bless $self, $pkg if defined($self);\n", "}\n\n", NIL);
+
+ have_constructor = 1;
+ }
+ }
+ member_func = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ member_func = 1;
+ Language::destructorHandler(n);
+ if (blessed) {
+ if (Getattr(n, "feature:shadow")) {
+ String *plcode = perlcode(Getattr(n, "feature:shadow"), 0);
+ String *plaction = NewStringf("%s::%s", module, Swig_name_member(NSPACE_TODO, class_name, symname));
+ Replaceall(plcode, "$action", plaction);
+ Delete(plaction);
+ Printv(pcode, plcode, NIL);
+ } else {
+ Printv(pcode,
+ "sub DESTROY {\n",
+ tab4, "return unless $_[0]->isa('HASH');\n",
+ tab4, "my $self = tied(%{$_[0]});\n",
+ tab4, "return unless defined $self;\n",
+ tab4, "delete $ITERATORS{$self};\n",
+ tab4, "if (exists $OWNER{$self}) {\n",
+ tab8, cmodule, "::", Swig_name_destroy(NSPACE_TODO, symname), "($self);\n", tab8, "delete $OWNER{$self};\n", tab4, "}\n}\n\n", NIL);
+ have_destructor = 1;
+ }
+ }
+ member_func = 0;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ member_func = 1;
+ Language::staticmemberfunctionHandler(n);
+ member_func = 0;
+ if ((blessed) && (!Getattr(n, "sym:nextSibling"))) {
+ String *symname = Getattr(n, "sym:name");
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Language::staticmembervariableHandler(n);
+ if (blessed) {
+ String *symname = Getattr(n, "sym:name");
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldblessed = blessed;
+
+ /* Create a normal constant */
+ blessed = 0;
+ Language::memberconstantHandler(n);
+ blessed = oldblessed;
+
+ if (blessed) {
+ Printv(pcode, "*", symname, " = *", cmodule, "::", Swig_name_member(NSPACE_TODO, class_name, symname), ";\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * pragma()
+ *
+ * Pragma directive.
+ *
+ * %pragma(perl5) code="String" # Includes a string in the .pm file
+ * %pragma(perl5) include="file.pl" # Includes a file in the .pm file
+ * ------------------------------------------------------------ */
+
+ virtual int pragmaDirective(Node *n) {
+ String *lang;
+ String *code;
+ String *value;
+ if (!ImportMode) {
+ lang = Getattr(n, "lang");
+ code = Getattr(n, "name");
+ value = Getattr(n, "value");
+ if (Strcmp(lang, "perl5") == 0) {
+ if (Strcmp(code, "code") == 0) {
+ /* Dump the value string into the .pm file */
+ if (value) {
+ Printf(pragma_include, "%s\n", value);
+ }
+ } else if (Strcmp(code, "include") == 0) {
+ /* Include a file into the .pm file */
+ if (value) {
+ FILE *f = Swig_include_open(value);
+ if (!f) {
+ Swig_error(input_file, line_number, "Unable to locate file %s\n", value);
+ } else {
+ char buffer[4096];
+ while (fgets(buffer, 4095, f)) {
+ Printf(pragma_include, "%s", buffer);
+ }
+ fclose(f);
+ }
+ }
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * perlcode() - Output perlcode code into the shadow file
+ * ------------------------------------------------------------ */
+
+ String *perlcode(String *code, const String *indent) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+ int initial = 0;
+ String *s = 0;
+ Iterator si;
+ /* Get the initial indentation */
+
+ for (si = First(clist); si.item; si = Next(si)) {
+ s = si.item;
+ if (Len(s)) {
+ char *c = Char(s);
+ while (*c) {
+ if (!isspace(*c))
+ break;
+ initial++;
+ c++;
+ }
+ if (*c && !isspace(*c))
+ break;
+ else {
+ initial = 0;
+ }
+ }
+ }
+ while (si.item) {
+ s = si.item;
+ if (Len(s) > initial) {
+ char *c = Char(s);
+ c += initial;
+ Printv(out, indent, c, "\n", NIL);
+ } else {
+ Printv(out, "\n", NIL);
+ }
+ si = Next(si);
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * insertDirective()
+ *
+ * Hook for %insert directive.
+ * ------------------------------------------------------------ */
+
+ virtual int insertDirective(Node *n) {
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+
+ if ((!ImportMode) && (Cmp(section, "perl") == 0)) {
+ Printv(additional_perl_code, code, NIL);
+ } else {
+ Language::insertDirective(n);
+ }
+ return SWIG_OK;
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *shead = Swig_include_sys("perlhead.swg");
+ if (!shead) {
+ Printf(stderr, "*** Unable to open 'perlhead.swg'\n");
+ } else {
+ Append(s, shead);
+ Delete(shead);
+ }
+ String *serrors = Swig_include_sys("perlerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'perlerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *srun = Swig_include_sys("perlrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'perlrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigperlrun.h");
+ }
+
+ virtual int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ virtual int classDirectorEnd(Node *n) {
+ if (dirprot_mode()) {
+ /*
+ This implementation uses a std::map<std::string,int>.
+
+ It should be possible to rewrite it using a more elegant way,
+ like copying the Java approach for the 'override' array.
+
+ But for now, this seems to be the least intrusive way.
+ */
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "/* Internal director utilities */\n");
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_get_inner(const char *swig_protected_method_name) const {\n");
+ Printf(f_directors_h, " std::map<std::string, bool>::const_iterator iv = swig_inner.find(swig_protected_method_name);\n");
+ Printf(f_directors_h, " return (iv != swig_inner.end() ? iv->second : false);\n");
+ Printf(f_directors_h, " }\n");
+
+ Printf(f_directors_h, " void swig_set_inner(const char *swig_protected_method_name, bool swig_val) const {\n");
+ Printf(f_directors_h, " swig_inner[swig_protected_method_name] = swig_val;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable std::map<std::string, bool> swig_inner;\n");
+ }
+ Printf(f_directors_h, "};\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("SV");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call);
+ Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
+ Append(w->def, "}\n");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ SwigType *returntype = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (!is_void && !ignored_method) {
+ String *pres = NewStringf("SV *%s", Swig_cresult_name());
+ Wrapper_add_local(w, Swig_cresult_name(), pres);
+ Delete(pres);
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> Perl) */
+ String *parse_args = NewString("");
+ String *pstack = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Wrapper_add_local(w, "SP", "dSP");
+
+ {
+ String *ptype = Copy(getClassType());
+ SwigType_add_pointer(ptype);
+ String *mangle = SwigType_manglestr(ptype);
+
+ Wrapper_add_local(w, "swigself", "SV *swigself");
+ Printf(w->code, "swigself = SWIG_NewPointerObj(SWIG_as_voidptr(this), SWIGTYPE%s, SWIG_SHADOW);\n", mangle);
+ Printf(w->code, "sv_bless(swigself, gv_stashpv(swig_get_class(), 0));\n");
+ Delete(mangle);
+ Delete(ptype);
+ Append(pstack, "XPUSHs(swigself);\n");
+ }
+
+ Parm *p;
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0;
+ p = l;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewString(source);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ Replaceall(tm, "$shadow", "0");
+ /* Wrapper_add_localv(w, source, "SV *", source, "= 0", NIL); */
+ Printv(wrap_args, "SV *", source, ";\n", NIL);
+
+ Printv(wrap_args, tm, "\n", NIL);
+ Putc('O', parse_args);
+ Printv(pstack, "XPUSHs(", source, ");\n", NIL);
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ /* special handling for pointers to other C++ director classes.
+ * ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. in other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. we avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, ptype);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(ptype) + 2);
+ /* name as pointer */
+ String *ppname = Copy(pname);
+ if (SwigType_isreference(ptype)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Perl doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", pname);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(ptype, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n",
+ SwigType_str(ptype, pname), SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(ptype);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "SV *", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_DIRECTOR_CAST(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Append(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "SvREFCNT_inc((SV *)%s);\n", source);
+ Append(wrap_args, "}\n");
+ Delete(director);
+ } else {
+ Wrapper_add_localv(w, source, "SV *", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Printf(pstack, "XPUSHs(sv_2mortal(%s));\n", source);
+ }
+ Putc('O', parse_args);
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* add the method name as a PyString */
+ String *pyname = Getattr(n, "sym:name");
+
+ /* wrap complex arguments to PyObjects */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the Python object */
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(w->code, "swig_set_inner(\"%s\", true);\n", name);
+ }
+
+ Append(w->code, "ENTER;\n");
+ Append(w->code, "SAVETMPS;\n");
+ Append(w->code, "PUSHMARK(SP);\n");
+ Append(w->code, pstack);
+ Delete(pstack);
+ Append(w->code, "PUTBACK;\n");
+ Printf(w->code, "call_method(\"%s\", G_EVAL | G_SCALAR);\n", pyname);
+
+ if (dirprot_mode() && !is_public(n))
+ Printf(w->code, "swig_set_inner(\"%s\", false);\n", name);
+
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ Append(w->code, "if (SvTRUE(ERRSV)) {\n");
+ Append(w->code, " PUTBACK;\n FREETMPS;\n LEAVE;\n");
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Replaceall(tm, "$error", "ERRSV");
+ Printv(w->code, Str(tm), "\n", NIL);
+ } else {
+ Printf(w->code, " Swig::DirectorMethodException::raise(ERRSV);\n");
+ }
+ Append(w->code, "}\n");
+ Delete(tm);
+
+ /*
+ * Python method may return a simple object, or a tuple.
+ * for in/out arguments, we have to extract the appropriate PyObjects from the tuple,
+ * then marshal everything back to C/C++ (return value and output arguments).
+ *
+ */
+
+ /* marshal return value and other outputs (if any) from PyObject to C/C++ type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ if (outputs > 1) {
+ Wrapper_add_local(w, "output", "SV *output");
+ Printf(w->code, "if (count != %d) {\n", outputs);
+ Printf(w->code, " Swig::DirectorTypeMismatchException::raise(\"Perl method %s.%sfailed to return a list.\");\n", classname, pyname);
+ Append(w->code, "}\n");
+ }
+
+ idx = 0;
+
+ /* marshal return value */
+ if (!is_void) {
+ Append(w->code, "SPAGAIN;\n");
+ Printf(w->code, "%s = POPs;\n", Swig_cresult_name());
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = POPs;\n");
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ }
+ char temp[24];
+ sprintf(temp, "%d", idx);
+ Replaceall(tm, "$argnum", temp);
+
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = POPs;\n");
+ Replaceall(tm, "$result", "output");
+ } else {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ }
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(parse_args);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!ignored_method) {
+ Append(w->code, "PUTBACK;\n");
+ Append(w->code, "FREETMPS;\n");
+ Append(w->code, "LEAVE;\n");
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ int classDirectorDisown(Node *n) {
+ int rv;
+ member_func = 1;
+ rv = Language::classDirectorDisown(n);
+ member_func = 0;
+ if (rv == SWIG_OK && Swig_directorclass(n)) {
+ String *symname = Getattr(n, "sym:name");
+ String *disown = Swig_name_disown(NSPACE_TODO, symname);
+ Setattr(n, "perl5:directordisown", NewStringf("%s::%s", cmodule, disown));
+ }
+ return rv;
+ }
+
+ int classDirectorDestructor(Node *n) {
+ /* TODO: it would be nice if this didn't have to copy the body of Language::classDirectorDestructor() */
+ String *DirectorClassName = directorClassName(getCurrentClass());
+ String *body = NewString("\n");
+
+ String *ptype = Copy(getClassType());
+ SwigType_add_pointer(ptype);
+ String *mangle = SwigType_manglestr(ptype);
+
+ Printv(body, tab4, "dSP;\n", tab4, "SV *self = SWIG_NewPointerObj(SWIG_as_voidptr(this), SWIGTYPE", mangle, ", SWIG_SHADOW);\n", tab4, "\n", tab4,
+ "sv_bless(self, gv_stashpv(swig_get_class(), 0));\n", tab4, "ENTER;\n", tab4, "SAVETMPS;\n", tab4, "PUSHMARK(SP);\n", tab4,
+ "XPUSHs(self);\n", tab4, "XPUSHs(&PL_sv_yes);\n", tab4, "PUTBACK;\n", tab4, "call_method(\"DESTROY\", G_EVAL | G_VOID);\n", tab4,
+ "FREETMPS;\n", tab4, "LEAVE;\n", NIL);
+
+ Delete(mangle);
+ Delete(ptype);
+
+ if (Getattr(n, "noexcept")) {
+ Printf(f_directors_h, " virtual ~%s() noexcept;\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() noexcept {%s}\n\n", DirectorClassName, DirectorClassName, body);
+ } else if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~%s() throw();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() throw() {%s}\n\n", DirectorClassName, DirectorClassName, body);
+ } else {
+ Printf(f_directors_h, " virtual ~%s();\n", DirectorClassName);
+ Printf(f_directors, "%s::~%s() {%s}\n\n", DirectorClassName, DirectorClassName, body);
+ }
+ return SWIG_OK;
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * swig_perl5() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_perl5() {
+ return new PERL5();
+}
+extern "C" Language *swig_perl5(void) {
+ return new_swig_perl5();
+}
diff --git a/contrib/tools/swig/Source/Modules/php.cxx b/contrib/tools/swig/Source/Modules/php.cxx
new file mode 100644
index 00000000000..d676df1c425
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/php.cxx
@@ -0,0 +1,2717 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * php.cxx
+ *
+ * PHP language module for SWIG.
+ * -----------------------------------------------------------------------------
+ */
+
+#include "swigmod.h"
+#include <algorithm>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+static const char *usage = "\
+PHP Options (available with -php7)\n\
+ -prefix <prefix> - Prepend <prefix> to all class names in PHP wrappers\n\
+\n";
+
+// How to wrap non-class functions, variables and constants:
+// FIXME: Make this specifiable and also allow a real namespace.
+
+// Wrap as global PHP names.
+static bool wrap_nonclass_global = true;
+
+// Wrap in a class to fake a namespace (for compatibility with SWIG's behaviour
+// before PHP added namespaces.
+static bool wrap_nonclass_fake_class = true;
+
+static String *module = 0;
+static String *cap_module = 0;
+static String *prefix = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_runtime_h = 0;
+static File *f_h = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+
+static String *s_header;
+static String *s_wrappers;
+static String *s_init;
+static String *r_init; // RINIT user code
+static String *s_shutdown; // MSHUTDOWN user code
+static String *r_shutdown; // RSHUTDOWN user code
+static String *s_vdecl;
+static String *s_cinit; // consttab initialization code.
+static String *s_oinit;
+static String *s_arginfo;
+static String *s_entry;
+static String *cs_entry;
+static String *all_cs_entry;
+static String *fake_cs_entry;
+static String *s_creation;
+static String *pragma_incl;
+static String *pragma_code;
+static String *pragma_phpinfo;
+static String *pragma_version;
+
+static String *class_name = NULL;
+static String *base_class = NULL;
+static String *destructor_action = NULL;
+static String *magic_set = NULL;
+static String *magic_get = NULL;
+static String *magic_isset = NULL;
+
+// Class used as pseudo-namespace for compatibility.
+static String *fake_class_name() {
+ static String *result = NULL;
+ if (!result) {
+ result = Len(prefix) ? prefix : module;
+ if (!fake_cs_entry) {
+ fake_cs_entry = NewStringf("static const zend_function_entry class_%s_functions[] = {\n", result);
+ }
+
+ Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n",result);
+
+ Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\", class_%s_functions);\n", result, result);
+ Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", result);
+ Printf(s_oinit, "\n");
+ }
+ return result;
+}
+
+static String *swig_wrapped_interface_ce() {
+ static String *result = NULL;
+ if (!result) {
+ result = NewStringf("SWIG_Php_swig_wrapped_interface_ce");
+ Printf(s_oinit, " INIT_CLASS_ENTRY(%s, \"SWIG\\\\wrapped\", NULL);\n", result);
+ }
+ return result;
+}
+
+/* To reduce code size (generated and compiled) we only want to emit each
+ * different arginfo once, so we need to track which have been used.
+ */
+static Hash *arginfo_used;
+
+/* Track non-class pointer types we need to to wrap */
+static Hash *raw_pointer_types = 0;
+
+static int shadow = 1;
+
+// These static variables are used to pass some state from Handlers into functionWrapper
+static enum {
+ standard = 0,
+ memberfn,
+ staticmemberfn,
+ membervar,
+ staticmembervar,
+ constructor,
+ destructor,
+ directorconstructor,
+ directordisown
+} wrapperType = standard;
+
+extern "C" {
+ static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
+}
+
+static void SwigPHP_emit_pointer_type_registrations() {
+ if (!raw_pointer_types)
+ return;
+
+ Iterator ki = First(raw_pointer_types);
+ if (!ki.key)
+ return;
+
+ Printf(s_wrappers, "/* class object handlers for pointer wrappers */\n");
+ Printf(s_wrappers, "static zend_object_handlers swig_ptr_object_handlers;\n\n");
+
+ Printf(s_wrappers, "/* Object Creation Method for pointer wrapping class */\n");
+ Printf(s_wrappers, "static zend_object *swig_ptr_object_new(zend_class_entry *ce) {\n");
+ Printf(s_wrappers, " swig_object_wrapper *obj = (swig_object_wrapper*)zend_object_alloc(sizeof(swig_object_wrapper), ce);\n");
+ Printf(s_wrappers, " zend_object_std_init(&obj->std, ce);\n");
+ Printf(s_wrappers, " object_properties_init(&obj->std, ce);\n");
+ Printf(s_wrappers, " obj->std.handlers = &swig_ptr_object_handlers;\n");
+ Printf(s_wrappers, " obj->newobject = 0;\n");
+ Printf(s_wrappers, " return &obj->std;\n");
+ Printf(s_wrappers, "}\n\n");
+
+ Printf(s_wrappers, "/* Implement __toString equivalent, since that worked for the old-style resource wrapped pointers. */\n");
+ Append(s_wrappers, "#if PHP_MAJOR_VERSION > 8 || PHP_MINOR_VERSION >= 2\n");
+ Printf(s_wrappers, "static ZEND_RESULT_CODE swig_ptr_cast_object(zend_object *zobj, zval *retval, int type) {\n");
+ Append(s_wrappers, "#else\n");
+ Printf(s_wrappers, "static int swig_ptr_cast_object(zend_object *zobj, zval *retval, int type) {\n");
+ Append(s_wrappers, "#endif\n");
+ Printf(s_wrappers, " if (type == IS_STRING) {\n");
+ Printf(s_wrappers, " swig_object_wrapper *obj = swig_php_fetch_object(zobj);\n");
+ Printv(s_wrappers, " ZVAL_NEW_STR(retval, zend_strpprintf(0, \"SWIGPointer(%p,owned=%d)\", obj->ptr, obj->newobject));\n", NIL);
+ Printf(s_wrappers, " return SUCCESS;\n");
+ Printf(s_wrappers, " }\n");
+ Printf(s_wrappers, " return FAILURE;\n");
+ Printf(s_wrappers, "}\n\n");
+
+ Printf(s_oinit, "\n /* Register classes to represent non-class pointer types */\n");
+ Printf(s_oinit, " swig_ptr_object_handlers = *zend_get_std_object_handlers();\n");
+ Printf(s_oinit, " swig_ptr_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n");
+ Printf(s_oinit, " swig_ptr_object_handlers.cast_object = swig_ptr_cast_object;\n");
+
+ while (ki.key) {
+ String *type = ki.key;
+
+ String *swig_wrapped = swig_wrapped_interface_ce();
+ Printf(s_creation, "/* class entry for pointer to %s */\n", type);
+ Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n", type);
+
+ Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\\\\%s\", NULL);\n", "SWIG", type);
+ Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", type);
+ Printf(s_oinit, " SWIG_Php_ce_%s->create_object = swig_ptr_object_new;\n", type);
+ Printv(s_oinit, " zend_do_implement_interface(SWIG_Php_ce_", type, ", &", swig_wrapped, ");\n", NIL);
+ Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,SWIG_Php_ce_%s);\n", type, type);
+ Printf(s_oinit, "\n");
+
+ ki = Next(ki);
+ }
+}
+
+static Hash *create_php_type_flags() {
+ Hash *h = NewHash();
+ Setattr(h, "array", "MAY_BE_ARRAY");
+ Setattr(h, "bool", "MAY_BE_BOOL");
+ Setattr(h, "callable", "MAY_BE_CALLABLE");
+ Setattr(h, "float", "MAY_BE_DOUBLE");
+ Setattr(h, "int", "MAY_BE_LONG");
+ Setattr(h, "iterable", "MAY_BE_ITERABLE");
+ Setattr(h, "mixed", "MAY_BE_MIXED");
+ Setattr(h, "null", "MAY_BE_NULL");
+ Setattr(h, "object", "MAY_BE_OBJECT");
+ Setattr(h, "resource", "MAY_BE_RESOURCE");
+ Setattr(h, "string", "MAY_BE_STRING");
+ Setattr(h, "void", "MAY_BE_VOID");
+ return h;
+}
+
+static Hash *php_type_flags = create_php_type_flags();
+
+// php_class + ":" + php_method -> PHPTypes*
+// ":" + php_function -> PHPTypes*
+static Hash *all_phptypes = NewHash();
+
+// php_class_name -> php_parent_class_name
+static Hash *php_parent_class = NewHash();
+
+// Track if a method is directed in a descendent class.
+// php_class + ":" + php_method -> boolean (using SetFlag()/GetFlag()).
+static Hash *has_directed_descendent = NewHash();
+
+// Track required return type for parent class methods.
+// php_class + ":" + php_method -> List of php types.
+static Hash *parent_class_method_return_type = NewHash();
+
+// Class encapsulating the machinery to add PHP type declarations.
+class PHPTypes {
+ // List with an entry for each parameter and one for the return type.
+ //
+ // We assemble the types in here before emitting them so for an overloaded
+ // function we combine the type declarations from each overloaded form.
+ List *merged_types;
+
+ // List with an entry for each parameter which is passed "byref" in any
+ // overloaded form. We use this to pass such parameters by reference in
+ // the dispatch function. If NULL, no parameters are passed by reference.
+ List *byref;
+
+ // The id string used in the name of the arginfo for this object.
+ String *arginfo_id;
+
+ // The feature:php:type value: 0, 1 or -1 for "compatibility".
+ int php_type_flag;
+
+ // Does the node for this have directorNode set?
+ bool has_director_node;
+
+ // Track if all the overloads of a method are static.
+ //
+ // We should only flag a dispatch method as ACC_STATIC if all the dispatched
+ // to methods are static. If we have both static and non-static methods in
+ // the overloaded set we omit ACC_STATIC, and then all the methods are
+ // callable (though the static ones only via an object). If we set
+ // ACC_STATIC we get a crash on an attempt to call a non-static method.
+ bool all_overloads_static;
+
+ // Used to clamp the required number of parameters in the arginfo to be
+ // compatible with any parent class version of the method.
+ int num_required;
+
+ int get_byref(int key) const {
+ return byref && key < Len(byref) && Getitem(byref, key) != None;
+ }
+
+ int size() const {
+ return std::max(Len(merged_types), Len(byref));
+ }
+
+ String *get_phptype(int key, String *classtypes, List *more_return_types = NULL) {
+ Clear(classtypes);
+ // We want to minimise the list of class types by not redundantly listing
+ // a class for which a super-class is also listed. This canonicalisation
+ // allows for more sharing of arginfo (which reduces module size), makes
+ // for a cleaner list if it's shown to the user, and also will speed up
+ // module load a bit.
+ Hash *classes = NewHash();
+ DOH *types = Getitem(merged_types, key);
+ String *result = NewStringEmpty();
+ if (more_return_types) {
+ if (types != None) {
+ merge_type_lists(types, more_return_types);
+ }
+ }
+ if (types != None) {
+ SortList(types, NULL);
+ String *prev = NULL;
+ for (Iterator i = First(types); i.item; i = Next(i)) {
+ if (prev && Equal(prev, i.item)) {
+ // Skip duplicates when merging.
+ continue;
+ }
+ String *c = Getattr(php_type_flags, i.item);
+ if (c) {
+ if (Len(result) > 0) Append(result, "|");
+ Append(result, c);
+ } else {
+ SetFlag(classes, i.item);
+ }
+ prev = i.item;
+ }
+ }
+
+ // Remove entries for which a super-class is also listed.
+ Iterator i = First(classes);
+ while (i.key) {
+ String *this_class = i.key;
+ // We must advance the iterator early so we don't delete the element it
+ // points to.
+ i = Next(i);
+ String *parent = this_class;
+ while ((parent = Getattr(php_parent_class, parent)) != NULL) {
+ if (GetFlag(classes, parent)) {
+ Delattr(classes, this_class);
+ break;
+ }
+ }
+ }
+
+ List *sorted_classes = SortedKeys(classes, Strcmp);
+ for (i = First(sorted_classes); i.item; i = Next(i)) {
+ if (Len(classtypes) > 0) Append(classtypes, "|");
+ Append(classtypes, prefix);
+ Append(classtypes, i.item);
+ }
+ Delete(sorted_classes);
+
+ // Make the mask 0 if there are only class names specified.
+ if (Len(result) == 0) {
+ Append(result, "0");
+ }
+ return result;
+ }
+
+public:
+ PHPTypes(Node *n)
+ : merged_types(NewList()),
+ byref(NULL),
+ num_required(INT_MAX) {
+ String *php_type_feature = Getattr(n, "feature:php:type");
+ php_type_flag = 0;
+ if (php_type_feature != NULL) {
+ if (Equal(php_type_feature, "1")) {
+ php_type_flag = 1;
+ } else if (!Equal(php_type_feature, "0")) {
+ php_type_flag = -1;
+ }
+ }
+ arginfo_id = Copy(Getattr(n, "sym:name"));
+ has_director_node = (Getattr(n, "directorNode") != NULL);
+ all_overloads_static = true;
+ }
+
+ ~PHPTypes() {
+ Delete(merged_types);
+ Delete(byref);
+ }
+
+ void not_all_static() { all_overloads_static = false; }
+
+ bool get_all_static() const { return all_overloads_static; }
+
+ void adjust(int num_required_, bool php_constructor) {
+ num_required = std::min(num_required, num_required_);
+ if (php_constructor) {
+ // Don't add a return type declaration for a PHP __construct method
+ // (because there it has no return type as far as PHP is concerned).
+ php_type_flag = 0;
+ }
+ }
+
+ String *get_arginfo_id() const {
+ return arginfo_id;
+ }
+
+ // key is 0 for return type, or >= 1 for parameters numbered from 1
+ List *process_phptype(Node *n, int key, const String_or_char *attribute_name);
+
+ // Merge entries from o_merge_list into merge_list, skipping any entries
+ // already present.
+ //
+ // Both merge_list and o_merge_list should be in sorted order.
+ static void merge_type_lists(List *merge_list, List *o_merge_list);
+
+ void merge_from(const PHPTypes* o);
+
+ void set_byref(int key) {
+ if (!byref) {
+ byref = NewList();
+ }
+ while (Len(byref) <= key) {
+ Append(byref, None);
+ }
+ // If any overload takes a particular parameter by reference then the
+ // dispatch function also needs to take that parameter by reference so
+ // we can just set unconditionally here.
+ Setitem(byref, key, ""); // Just needs to be something != None.
+ }
+
+ void emit_arginfo(DOH *item, String *key) {
+ Setmark(item, 1);
+ char *colon_ptr = Strchr(key, ':');
+ assert(colon_ptr);
+ int colon = (int)(colon_ptr - Char(key));
+ if (colon > 0 && Strcmp(colon_ptr + 1, "__construct") != 0) {
+ // See if there's a parent class which implements this method, and if so
+ // emit its arginfo and then merge its PHPTypes into ours as we need to
+ // be compatible with it (whether it is virtual or not).
+ String *this_class = NewStringWithSize(Char(key), colon);
+ String *parent = this_class;
+ while ((parent = Getattr(php_parent_class, parent)) != NULL) {
+ String *k = NewStringf("%s%s", parent, colon_ptr);
+ DOH *item = Getattr(all_phptypes, k);
+ if (item) {
+ PHPTypes *p = (PHPTypes*)Data(item);
+ if (!Getmark(item)) {
+ p->emit_arginfo(item, k);
+ }
+ merge_from(p);
+ Delete(k);
+ break;
+ }
+ Delete(k);
+ }
+ Delete(this_class);
+ }
+
+ // We want to only emit each different arginfo once, as that reduces the
+ // size of both the generated source code and the compiled extension
+ // module. The parameters at this level are just named arg1, arg2, etc
+ // so the arginfo will be the same for any function with the same number
+ // of parameters and (if present) PHP type declarations for parameters and
+ // return type.
+ //
+ // We generate the arginfo we want (taking care to normalise, e.g. the
+ // lists of types are unique and in sorted order), then use the
+ // arginfo_used Hash to see if we've already generated it.
+ String *out_phptype = NULL;
+ String *out_phpclasses = NewStringEmpty();
+
+ // We provide a simple way to generate PHP return type declarations
+ // except for directed methods. The point of directors is to allow
+ // subclassing in the target language, and if the wrapped method has
+ // a return type declaration then an overriding method in user code
+ // needs to have a compatible declaration.
+ //
+ // The upshot of this is that enabling return type declarations for
+ // existing bindings would break compatibility with user code written
+ // for an older version. For parameters however the situation is
+ // different because if the parent class declares types for parameters
+ // a subclass overriding the function will be compatible whether it
+ // declares them or not.
+ //
+ // directorNode being present seems to indicate if this method or one
+ // it inherits from is directed, which is what we care about here.
+ // Using (!is_member_director(n)) would get it wrong for testcase
+ // director_frob.
+ if (php_type_flag && (php_type_flag > 0 || !has_director_node)) {
+ if (!GetFlag(has_directed_descendent, key)) {
+ out_phptype = get_phptype(0, out_phpclasses, Getattr(parent_class_method_return_type, key));
+ }
+ }
+
+ // ### in arginfo_code will be replaced with the id once that is known.
+ String *arginfo_code = NewStringEmpty();
+ if (out_phptype) {
+ if (Len(out_phpclasses)) {
+ Replace(out_phpclasses, "\\", "\\\\", DOH_REPLACE_ANY);
+ Printf(arginfo_code, "ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(swig_arginfo_###, 0, %d, %s, %s)\n", num_required, out_phpclasses, out_phptype);
+ } else {
+ Printf(arginfo_code, "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(swig_arginfo_###, 0, %d, %s)\n", num_required, out_phptype);
+ }
+ } else {
+ Printf(arginfo_code, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_###, 0, 0, %d)\n", num_required);
+ }
+
+ int phptypes_size = size();
+ for (int param_count = 1; param_count < phptypes_size; ++param_count) {
+ String *phpclasses = NewStringEmpty();
+ String *phptype = get_phptype(param_count, phpclasses);
+
+ int byref = get_byref(param_count);
+
+ // FIXME: Should we be doing byref for return value as well?
+
+ if (phptype) {
+ if (Len(phpclasses)) {
+ // We need to double any backslashes (which are PHP namespace
+ // separators) in the PHP class names as they get turned into
+ // C strings by the ZEND_ARG_OBJ_TYPE_MASK macro.
+ Replace(phpclasses, "\\", "\\\\", DOH_REPLACE_ANY);
+ Printf(arginfo_code, " ZEND_ARG_OBJ_TYPE_MASK(%d,arg%d,%s,%s,NULL)\n", byref, param_count, phpclasses, phptype);
+ } else {
+ Printf(arginfo_code, " ZEND_ARG_TYPE_MASK(%d,arg%d,%s,NULL)\n", byref, param_count, phptype);
+ }
+ } else {
+ Printf(arginfo_code, " ZEND_ARG_INFO(%d,arg%d)\n", byref, param_count);
+ }
+ }
+ Printf(arginfo_code, "ZEND_END_ARG_INFO()\n");
+
+ String *arginfo_id_same = Getattr(arginfo_used, arginfo_code);
+ if (arginfo_id_same) {
+ Printf(s_arginfo, "#define swig_arginfo_%s swig_arginfo_%s\n", arginfo_id, arginfo_id_same);
+ } else {
+ // Not had this arginfo before.
+ Setattr(arginfo_used, arginfo_code, arginfo_id);
+ arginfo_code = Copy(arginfo_code);
+ Replace(arginfo_code, "###", arginfo_id, DOH_REPLACE_FIRST);
+ Append(s_arginfo, arginfo_code);
+ }
+ Delete(arginfo_code);
+ arginfo_code = NULL;
+ }
+};
+
+static PHPTypes *phptypes = NULL;
+
+class PHP : public Language {
+public:
+ PHP() {
+ directorLanguage();
+ }
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+ SWIG_library_directory("php");
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-noshadow") == 0)) {
+ shadow = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ }
+
+ Preprocessor_define("SWIGPHP 1", 0);
+ Preprocessor_define("SWIGPHP7 1", 0);
+ SWIG_config_file("php.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ String *filen;
+
+ /* Check if directors are enabled for this module. */
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options && Getattr(options, "directors")) {
+ allow_directors();
+ }
+ }
+
+ /* Set comparison with null for ConstructorToFunction */
+ setSubclassInstanceCheck(NewString("Z_TYPE_P($arg) != IS_NULL"));
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ /* main output file */
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewStringEmpty();
+
+ /* sections of the output file */
+ s_init = NewStringEmpty();
+ r_init = NewStringEmpty();
+ s_shutdown = NewStringEmpty();
+ r_shutdown = NewStringEmpty();
+ s_header = NewString("/* header section */\n");
+ s_wrappers = NewString("/* wrapper section */\n");
+ s_creation = NewStringEmpty();
+ /* subsections of the init section */
+ s_vdecl = NewString("/* vdecl subsection */\n");
+ s_cinit = NewString(" /* cinit subsection */\n");
+ s_oinit = NewString(" /* oinit subsection */\n");
+ pragma_phpinfo = NewStringEmpty();
+ f_directors_h = NewStringEmpty();
+ f_directors = NewStringEmpty();
+
+ if (Swig_directors_enabled()) {
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", s_init);
+ Swig_register_filebyname("rinit", r_init);
+ Swig_register_filebyname("shutdown", s_shutdown);
+ Swig_register_filebyname("rshutdown", r_shutdown);
+ Swig_register_filebyname("header", s_header);
+ Swig_register_filebyname("wrapper", s_wrappers);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "PHP");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ // We need to include php.h before string.h gets included, at least with
+ // PHP 8.2. Otherwise string.h is included without _GNU_SOURCE being
+ // included and memrchr() doesn't get declared, and then inline code in
+ // the PHP headers defines _GNU_SOURCE, includes string.h (which is a
+ // no op thanks to the include gaurds), then tries to use memrchr() and
+ // fails.
+ //
+ // We also need to suppress -Wdeclaration-after-statement if enabled
+ // since with PHP 8.2 zend_operators.h contains inline code which triggers
+ // this warning and our testsuite uses with option and -Werror. I don't
+ // see a good way to only do this within our testsuite, but disabling
+ // it globally like this shouldn't be problematic.
+ Append(f_runtime,
+ "\n"
+ "#if defined __GNUC__ && !defined __cplusplus\n"
+ "# if __GNUC__ >= 4\n"
+ "# pragma GCC diagnostic push\n"
+ "# pragma GCC diagnostic ignored \"-Wdeclaration-after-statement\"\n"
+ "# endif\n"
+ "#endif\n"
+ "#include \"php.h\"\n"
+ "#if defined __GNUC__ && !defined __cplusplus\n"
+ "# if __GNUC__ >= 4\n"
+ "# pragma GCC diagnostic pop\n"
+ "# endif\n"
+ "#endif\n\n");
+
+ /* Set the module name */
+ module = Copy(Getattr(n, "name"));
+ cap_module = NewStringf("%(upper)s", module);
+ if (!prefix)
+ prefix = NewStringEmpty();
+
+ if (Swig_directors_enabled()) {
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module);
+
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "\n#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ /* sub-sections of the php file */
+ pragma_code = NewStringEmpty();
+ pragma_incl = NewStringEmpty();
+ pragma_version = NULL;
+
+ /* Initialize the rest of the module */
+
+ /* start the header section */
+ Printf(s_header, "#define SWIG_name \"%s\"\n", module);
+ Printf(s_header, "#ifdef __cplusplus\n");
+ Printf(s_header, "extern \"C\" {\n");
+ Printf(s_header, "#endif\n");
+ Printf(s_header, "#include \"php_ini.h\"\n");
+ Printf(s_header, "#include \"ext/standard/info.h\"\n");
+ Printf(s_header, "#include \"php_%s.h\"\n", module);
+ Printf(s_header, "#ifdef __cplusplus\n");
+ Printf(s_header, "}\n");
+ Printf(s_header, "#endif\n\n");
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime
+ Swig_insert_file("director_common.swg", s_header);
+ Swig_insert_file("director.swg", s_header);
+ }
+
+ /* Create the .h file too */
+ filen = NewStringEmpty();
+ Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL);
+ f_h = NewFile(filen, "w", SWIG_output_files());
+ if (!f_h) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+
+ Swig_banner(f_h);
+
+ Printf(f_h, "\n");
+ Printf(f_h, "#ifndef PHP_%s_H\n", cap_module);
+ Printf(f_h, "#define PHP_%s_H\n\n", cap_module);
+ Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module);
+ Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module);
+ Printf(f_h, "#ifdef PHP_WIN32\n");
+ Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module);
+ Printf(f_h, "#else\n");
+ Printf(f_h, "# define PHP_%s_API\n", cap_module);
+ Printf(f_h, "#endif\n\n");
+
+ /* start the arginfo section */
+ s_arginfo = NewString("/* arginfo subsection */\n");
+ arginfo_used = NewHash();
+
+ /* start the function entry section */
+ s_entry = NewString("/* entry subsection */\n");
+
+ /* holds all the per-class function entry sections */
+ all_cs_entry = NewString("/* class entry subsection */\n");
+ cs_entry = NULL;
+ fake_cs_entry = NULL;
+
+ Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n");
+ Printf(s_entry, "static const zend_function_entry module_%s_functions[] = {\n", module);
+
+ /* Emit all of the code */
+ Language::top(n);
+
+ /* Emit all the arginfo. We sort the keys so the output order doesn't depend on
+ * hashkey order.
+ */
+ {
+ List *sorted_keys = SortedKeys(all_phptypes, Strcmp);
+ for (Iterator k = First(sorted_keys); k.item; k = Next(k)) {
+ DOH *val = Getattr(all_phptypes, k.item);
+ if (!Getmark(val)) {
+ PHPTypes *p = (PHPTypes*)Data(val);
+ p->emit_arginfo(val, k.item);
+ }
+ }
+ Delete(sorted_keys);
+ }
+
+ SwigPHP_emit_pointer_type_registrations();
+ Dump(s_creation, s_header);
+ Delete(s_creation);
+ s_creation = NULL;
+
+ /* start the init section */
+ {
+ String *s_init_old = s_init;
+ s_init = NewString("/* init section */\n");
+ Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL);
+ Printf(s_init, " STANDARD_MODULE_HEADER,\n");
+ Printf(s_init, " \"%s\",\n", module);
+ Printf(s_init, " module_%s_functions,\n", module);
+ Printf(s_init, " PHP_MINIT(%s),\n", module);
+ if (Len(s_shutdown) > 0) {
+ Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No MSHUTDOWN code */\n");
+ }
+ if (Len(r_init) > 0) {
+ Printf(s_init, " PHP_RINIT(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No RINIT code */\n");
+ }
+ if (Len(r_shutdown) > 0) {
+ Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No RSHUTDOWN code */\n");
+ }
+ if (Len(pragma_phpinfo) > 0) {
+ Printf(s_init, " PHP_MINFO(%s),\n", module);
+ } else {
+ Printf(s_init, " NULL, /* No MINFO code */\n");
+ }
+ if (Len(pragma_version) > 0) {
+ Printf(s_init, " \"%s\",\n", pragma_version);
+ } else {
+ Printf(s_init, " NO_VERSION_YET,\n");
+ }
+ Printf(s_init, " STANDARD_MODULE_PROPERTIES\n");
+ Printf(s_init, "};\n\n");
+
+ Printf(s_init, "#ifdef __cplusplus\n");
+ Printf(s_init, "extern \"C\" {\n");
+ Printf(s_init, "#endif\n");
+ // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but the definition
+ // of ZEND_GET_MODULE has "extern "C" { ... }" around it so we can't do
+ // that.
+ Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module);
+ Printf(s_init, "#ifdef __cplusplus\n");
+ Printf(s_init, "}\n");
+ Printf(s_init, "#endif\n\n");
+
+ Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n\n", module);
+
+ Printv(s_init, s_init_old, NIL);
+ Delete(s_init_old);
+ }
+
+ /* We have to register the constants before they are (possibly) used
+ * by the pointer typemaps. This all needs re-arranging really as
+ * things are being called in the wrong order
+ */
+
+ Printf(s_oinit, " /* end oinit subsection */\n");
+ Printf(s_init, "%s\n", s_oinit);
+
+ /* Constants generated during top call */
+ Printf(s_cinit, " /* end cinit subsection */\n");
+ Printf(s_init, "%s\n", s_cinit);
+ Clear(s_cinit);
+ Delete(s_cinit);
+
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+
+ // Now do REQUEST init which holds any user specified %rinit, and also vinit
+ if (Len(r_init) > 0) {
+ Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module);
+
+ Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module);
+ Printv(s_init,
+ "/* rinit section */\n",
+ r_init, "\n",
+ NIL);
+
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+ }
+
+ Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module);
+
+ if (Len(s_shutdown) > 0) {
+ Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module);
+
+ Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
+ "/* shutdown section */\n"
+ "{\n",
+ s_shutdown,
+ " return SUCCESS;\n"
+ "}\n\n", NIL);
+ }
+
+ if (Len(r_shutdown) > 0) {
+ Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module);
+
+ Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
+ Printf(s_init, "/* rshutdown section */\n");
+ Printf(s_init, "%s\n", r_shutdown);
+ Printf(s_init, " return SUCCESS;\n");
+ Printf(s_init, "}\n\n");
+ }
+
+ if (Len(pragma_phpinfo) > 0) {
+ Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n", module);
+
+ Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module);
+ Printf(s_init, "%s", pragma_phpinfo);
+ Printf(s_init, "}\n");
+ }
+
+ Printf(s_init, "/* end init section */\n");
+
+ Printf(f_h, "\n#endif /* PHP_%s_H */\n", cap_module);
+
+ Delete(f_h);
+
+ String *type_table = NewStringEmpty();
+ SwigType_emit_type_table(f_runtime, type_table);
+ Printf(s_header, "%s", type_table);
+ Delete(type_table);
+
+ /* Oh dear, more things being called in the wrong order. This whole
+ * function really needs totally redoing.
+ */
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ Delete(f_runtime_h);
+ }
+
+ Printf(s_header, "/* end header section */\n");
+ Printf(s_wrappers, "/* end wrapper section */\n");
+ Printf(s_vdecl, "/* end vdecl subsection */\n");
+
+ Dump(f_runtime, f_begin);
+ Printv(f_begin, s_header, NIL);
+ if (Swig_directors_enabled()) {
+ Dump(f_directors, f_begin);
+ }
+ Printv(f_begin, s_vdecl, s_wrappers, NIL);
+ Printv(f_begin, s_arginfo, "\n\n", all_cs_entry, "\n\n", s_entry,
+ " ZEND_FE_END\n};\n\n", NIL);
+ if (fake_cs_entry) {
+ Printv(f_begin, fake_cs_entry, " ZEND_FE_END\n};\n\n", NIL);
+ Delete(fake_cs_entry);
+ fake_cs_entry = NULL;
+ }
+ Printv(f_begin, s_init, NIL);
+ Delete(s_header);
+ Delete(s_wrappers);
+ Delete(s_init);
+ Delete(s_vdecl);
+ Delete(all_cs_entry);
+ Delete(s_entry);
+ Delete(s_arginfo);
+ Delete(f_runtime);
+ Delete(f_begin);
+ Delete(arginfo_used);
+
+ if (Len(pragma_incl) > 0 || Len(pragma_code) > 0) {
+ /* PHP module file */
+ String *php_filename = NewStringEmpty();
+ Printv(php_filename, SWIG_output_directory(), module, ".php", NIL);
+
+ File *f_phpcode = NewFile(php_filename, "w", SWIG_output_files());
+ if (!f_phpcode) {
+ FileErrorDisplay(php_filename);
+ Exit(EXIT_FAILURE);
+ }
+
+ Printf(f_phpcode, "<?php\n\n");
+
+ if (Len(pragma_incl) > 0) {
+ Printv(f_phpcode, pragma_incl, "\n", NIL);
+ }
+
+ if (Len(pragma_code) > 0) {
+ Printv(f_phpcode, pragma_code, "\n", NIL);
+ }
+
+ Delete(f_phpcode);
+ Delete(php_filename);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* Just need to append function names to function table to register with PHP. */
+ void create_command(String *cname, String *fname, Node *n, bool dispatch, String *modes) {
+ // This is for the single main zend_function_entry record
+ ParmList *l = Getattr(n, "parms");
+ if (cname && !Strstr(Getattr(n, "storage"), "friend")) {
+ Printf(f_h, "static PHP_METHOD(%s%s,%s);\n", prefix, cname, fname);
+ if (wrapperType != staticmemberfn &&
+ wrapperType != staticmembervar &&
+ !Equal(fname, "__construct")) {
+ // Skip the first entry in the parameter list which is the this pointer.
+ if (l) l = Getattr(l, "tmap:in:next");
+ // FIXME: does this throw the phptype key value off?
+ }
+ } else {
+ if (dispatch) {
+ Printf(f_h, "static ZEND_NAMED_FUNCTION(%s);\n", fname);
+ } else {
+ Printf(f_h, "static PHP_FUNCTION(%s);\n", fname);
+ }
+ }
+
+ phptypes->adjust(emit_num_required(l), Equal(fname, "__construct") ? true : false);
+
+ String *arginfo_id = phptypes->get_arginfo_id();
+ String *s = cs_entry;
+ if (!s) s = s_entry;
+ if (cname && !Strstr(Getattr(n, "storage"), "friend")) {
+ Printf(all_cs_entry, " PHP_ME(%s%s,%s,swig_arginfo_%s,%s)\n", prefix, cname, fname, arginfo_id, modes);
+ } else {
+ if (dispatch) {
+ if (wrap_nonclass_global) {
+ Printf(s, " ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", Getattr(n, "sym:name"), fname, arginfo_id);
+ }
+
+ if (wrap_nonclass_fake_class) {
+ (void)fake_class_name();
+ Printf(fake_cs_entry, " ZEND_NAMED_ME(%(lower)s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", Getattr(n, "sym:name"), fname, arginfo_id);
+ }
+ } else {
+ if (wrap_nonclass_global) {
+ Printf(s, " PHP_FE(%s,swig_arginfo_%s)\n", fname, arginfo_id);
+ }
+
+ if (wrap_nonclass_fake_class) {
+ String *fake_class = fake_class_name();
+ Printf(fake_cs_entry, " PHP_ME(%s,%s,swig_arginfo_%s,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)\n", fake_class, fname, arginfo_id);
+ }
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+ void dispatchFunction(Node *n, int constructor) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewStringEmpty();
+ String *dispatch = Swig_overload_dispatch(n, "%s(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *wname = NULL;
+ String *modes = NULL;
+ bool constructorRenameOverload = false;
+
+ if (constructor) {
+ if (!Equal(class_name, Getattr(n, "constructorHandler:sym:name"))) {
+ // Renamed constructor - turn into static factory method
+ constructorRenameOverload = true;
+ wname = Copy(Getattr(n, "constructorHandler:sym:name"));
+ } else {
+ wname = NewString("__construct");
+ }
+ } else if (class_name) {
+ wname = Getattr(n, "wrapper:method:name");
+ } else {
+ wname = Swig_name_wrapper(symname);
+ }
+
+ if (constructor) {
+ modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_CTOR");
+ if (constructorRenameOverload) {
+ Append(modes, " | ZEND_ACC_STATIC");
+ }
+ } else if (phptypes->get_all_static()) {
+ modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_STATIC");
+ } else {
+ modes = NewString("ZEND_ACC_PUBLIC");
+ }
+
+ create_command(class_name, wname, n, true, modes);
+
+ if (class_name && !Strstr(Getattr(n, "storage"), "friend")) {
+ Printv(f->def, "static PHP_METHOD(", prefix, class_name, ",", wname, ") {\n", NIL);
+ } else {
+ Printv(f->def, "static ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
+ }
+
+ Wrapper_add_local(f, "argc", "int argc");
+
+ Printf(tmp, "zval argv[%d]", maxargs);
+ Wrapper_add_local(f, "argv", tmp);
+
+ Printf(f->code, "argc = ZEND_NUM_ARGS();\n");
+
+ Printf(f->code, "zend_get_parameters_array_ex(argc, argv);\n");
+
+ Replaceall(dispatch, "$args", "self,args");
+
+ Printv(f->code, dispatch, "\n", NIL);
+
+ Printf(f->code, "zend_throw_exception(zend_ce_type_error, \"No matching function for overloaded '%s'\", 0);\n", symname);
+ Printv(f->code, "fail:\n", NIL);
+ Printv(f->code, "return;\n", NIL);
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, s_wrappers);
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ /* Helper function to check if class is wrapped */
+ bool is_class_wrapped(String *className) {
+ if (!className)
+ return false;
+ Node *n = symbolLookup(className);
+ return n && Getattr(n, "classtype") != NULL;
+ }
+
+ void generate_magic_property_methods(Node *class_node) {
+ String *swig_base = base_class;
+ if (Equal(swig_base, "Exception") || !is_class_wrapped(swig_base)) {
+ swig_base = NULL;
+ }
+
+ static bool generated_magic_arginfo = false;
+ if (!generated_magic_arginfo) {
+ // Create arginfo entries for __get, __set and __isset.
+ Append(s_arginfo,
+ "ZEND_BEGIN_ARG_INFO_EX(swig_magic_arginfo_get, 0, 0, 1)\n"
+ " ZEND_ARG_TYPE_MASK(0,arg1,MAY_BE_STRING,NULL)\n"
+ "ZEND_END_ARG_INFO()\n");
+ Append(s_arginfo,
+ "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(swig_magic_arginfo_set, 0, 1, MAY_BE_VOID)\n"
+ " ZEND_ARG_TYPE_MASK(0,arg1,MAY_BE_STRING,NULL)\n"
+ " ZEND_ARG_INFO(0,arg2)\n"
+ "ZEND_END_ARG_INFO()\n");
+ Append(s_arginfo,
+ "ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(swig_magic_arginfo_isset, 0, 1, MAY_BE_BOOL)\n"
+ " ZEND_ARG_TYPE_MASK(0,arg1,MAY_BE_STRING,NULL)\n"
+ "ZEND_END_ARG_INFO()\n");
+ generated_magic_arginfo = true;
+ }
+
+ Wrapper *f = NewWrapper();
+
+ Printf(f_h, "PHP_METHOD(%s%s,__set);\n", prefix, class_name);
+ Printf(all_cs_entry, " PHP_ME(%s%s,__set,swig_magic_arginfo_set,ZEND_ACC_PUBLIC)\n", prefix, class_name);
+ Printf(f->code, "PHP_METHOD(%s%s,__set) {\n", prefix, class_name);
+
+ Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n");
+ Printf(f->code, " zval args[2];\n zend_string *arg2 = 0;\n\n");
+ Printf(f->code, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n");
+ Printf(f->code, "\tWRONG_PARAM_COUNT;\n}\n\n");
+ Printf(f->code, " if (!arg) {\n");
+ Printf(f->code, " zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n");
+ Printf(f->code, " return;\n");
+ Printf(f->code, " }\n");
+ Printf(f->code, " arg2 = Z_STR(args[0]);\n\n");
+
+ Printf(f->code, "if (!arg2) {\n RETVAL_NULL();\n}\n");
+ if (magic_set) {
+ Append(f->code, magic_set);
+ }
+ Printf(f->code, "\nelse if (strcmp(ZSTR_VAL(arg2),\"thisown\") == 0) {\n");
+ Printf(f->code, "arg->newobject = zval_get_long(&args[1]);\n");
+ if (Swig_directorclass(class_node)) {
+ Printv(f->code, "if (arg->newobject == 0) {\n",
+ " Swig::Director *director = SWIG_DIRECTOR_CAST((", Getattr(class_node, "classtype"), "*)(arg->ptr));\n",
+ " if (director) director->swig_disown();\n",
+ "}\n", NIL);
+ }
+ if (swig_base) {
+ Printf(f->code, "} else {\nPHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n", prefix, swig_base);
+ } else if (GetFlag(class_node, "feature:php:allowdynamicproperties")) {
+ Printf(f->code, "} else {\nadd_property_zval_ex(ZEND_THIS, ZSTR_VAL(arg2), ZSTR_LEN(arg2), &args[1]);\n");
+ }
+ Printf(f->code, "}\n");
+
+ Printf(f->code, "fail:\n");
+ Printf(f->code, "return;\n");
+ Printf(f->code, "}\n\n\n");
+
+
+ Printf(f_h, "PHP_METHOD(%s%s,__get);\n", prefix, class_name);
+ Printf(all_cs_entry, " PHP_ME(%s%s,__get,swig_magic_arginfo_get,ZEND_ACC_PUBLIC)\n", prefix, class_name);
+ Printf(f->code, "PHP_METHOD(%s%s,__get) {\n",prefix, class_name);
+
+ Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n");
+ Printf(f->code, " zval args[1];\n zend_string *arg2 = 0;\n\n");
+ Printf(f->code, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n");
+ Printf(f->code, "\tWRONG_PARAM_COUNT;\n}\n\n");
+ Printf(f->code, " if (!arg) {\n");
+ Printf(f->code, " zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n");
+ Printf(f->code, " return;\n");
+ Printf(f->code, " }\n");
+ Printf(f->code, " arg2 = Z_STR(args[0]);\n\n");
+
+ Printf(f->code, "if (!arg2) {\n RETVAL_NULL();\n}\n");
+ if (magic_get) {
+ Append(f->code, magic_get);
+ }
+ Printf(f->code, "\nelse if (strcmp(ZSTR_VAL(arg2),\"thisown\") == 0) {\n");
+ Printf(f->code, "if(arg->newobject) {\nRETVAL_LONG(1);\n}\nelse {\nRETVAL_LONG(0);\n}\n}\n\n");
+ Printf(f->code, "else {\n");
+ if (swig_base) {
+ Printf(f->code, "PHP_MN(%s%s___get)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base);
+ } else {
+ // __get is only called if the property isn't set on the zend_object.
+ Printf(f->code, "RETVAL_NULL();\n}\n");
+ }
+
+ Printf(f->code, "fail:\n");
+ Printf(f->code, "return;\n");
+ Printf(f->code, "}\n\n\n");
+
+
+ Printf(f_h, "PHP_METHOD(%s%s,__isset);\n", prefix, class_name);
+ Printf(all_cs_entry, " PHP_ME(%s%s,__isset,swig_magic_arginfo_isset,ZEND_ACC_PUBLIC)\n", prefix, class_name);
+ Printf(f->code, "PHP_METHOD(%s%s,__isset) {\n",prefix, class_name);
+
+ Printf(f->code, " swig_object_wrapper *arg = SWIG_Z_FETCH_OBJ_P(ZEND_THIS);\n");
+ Printf(f->code, " zval args[1];\n zend_string *arg2 = 0;\n\n");
+ Printf(f->code, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n");
+ Printf(f->code, "\tWRONG_PARAM_COUNT;\n}\n\n");
+ Printf(f->code, " if(!arg) {\n");
+ Printf(f->code, " zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n");
+ Printf(f->code, " return;\n");
+ Printf(f->code, " }\n");
+ Printf(f->code, " arg2 = Z_STR(args[0]);\n\n");
+
+ Printf(f->code, "if (!arg2) {\n RETVAL_FALSE;\n}\n");
+ Printf(f->code, "\nelse if (strcmp(ZSTR_VAL(arg2),\"thisown\") == 0) {\n");
+ Printf(f->code, "RETVAL_TRUE;\n}\n\n");
+ if (magic_isset) {
+ Append(f->code, magic_isset);
+ }
+ Printf(f->code, "else {\n");
+ if (swig_base) {
+ Printf(f->code, "PHP_MN(%s%s___isset)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base);
+ } else {
+ // __isset is only called if the property isn't set on the zend_object.
+ Printf(f->code, "RETVAL_FALSE;\n}\n");
+ }
+
+ Printf(f->code, "fail:\n");
+ Printf(f->code, "return;\n");
+ Printf(f->code, "}\n\n\n");
+
+ Wrapper_print(f, s_wrappers);
+ DelWrapper(f);
+ f = NULL;
+
+ Delete(magic_set);
+ Delete(magic_get);
+ Delete(magic_isset);
+ magic_set = NULL;
+ magic_get = NULL;
+ magic_isset = NULL;
+ }
+
+ String *getAccessMode(String *access) {
+ if (Cmp(access, "protected") == 0) {
+ return NewString("ZEND_ACC_PROTECTED");
+ } else if (Cmp(access, "private") == 0) {
+ return NewString("ZEND_ACC_PRIVATE");
+ }
+ return NewString("ZEND_ACC_PUBLIC");
+ }
+
+ bool is_setter_method(Node *n) {
+ const char *p = GetChar(n, "sym:name");
+ if (strlen(p) > 4) {
+ p += strlen(p) - 4;
+ if (strcmp(p, "_set") == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool is_getter_method(Node *n) {
+ const char *p = GetChar(n, "sym:name");
+ if (strlen(p) > 4) {
+ p += strlen(p) - 4;
+ if (strcmp(p, "_get") == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual int functionWrapper(Node *n) {
+ if (wrapperType == directordisown) {
+ // Handled via __set magic method - no explicit wrapper method wanted.
+ return SWIG_OK;
+ }
+ String *name = GetChar(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *nodeType = Getattr(n, "nodeType");
+ int newobject = GetFlag(n, "feature:new");
+ int constructor = (Cmp(nodeType, "constructor") == 0);
+
+ Parm *p;
+ int i;
+ int numopt;
+ String *tm;
+ Wrapper *f;
+
+ String *wname = NewStringEmpty();
+ String *overloadwname = NULL;
+ int overloaded = 0;
+ String *modes = NULL;
+ bool static_setter = false;
+ bool static_getter = false;
+
+ modes = getAccessMode(Getattr(n, "access"));
+
+ if (constructor) {
+ Append(modes, " | ZEND_ACC_CTOR");
+ }
+ if (wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"), "static") == 0) {
+ Append(modes, " | ZEND_ACC_STATIC");
+ }
+ if (GetFlag(n, "abstract") && Swig_directorclass(Swig_methodclass(n)) && !is_member_director(n))
+ Append(modes, " | ZEND_ACC_ABSTRACT");
+
+ if (Getattr(n, "sym:overloaded")) {
+ overloaded = 1;
+ overloadwname = NewString(Swig_name_wrapper(iname));
+ Printf(overloadwname, "%s", Getattr(n, "sym:overname"));
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ if (constructor) {
+ if (!Equal(class_name, Getattr(n, "constructorHandler:sym:name"))) {
+ // Renamed constructor - turn into static factory method
+ wname = Copy(Getattr(n, "constructorHandler:sym:name"));
+ } else {
+ wname = NewString("__construct");
+ }
+ } else if (wrapperType == membervar) {
+ wname = Copy(Getattr(n, "membervariableHandler:sym:name"));
+ if (is_setter_method(n)) {
+ Append(wname, "_set");
+ } else if (is_getter_method(n)) {
+ Append(wname, "_get");
+ }
+ } else if (wrapperType == memberfn) {
+ wname = Getattr(n, "memberfunctionHandler:sym:name");
+ } else if (wrapperType == staticmembervar) {
+ // Shape::nshapes -> nshapes
+ wname = Getattr(n, "staticmembervariableHandler:sym:name");
+
+ /* We get called twice for getter and setter methods. But to maintain
+ compatibility, Shape::nshapes() is being used for both setter and
+ getter methods. So using static_setter and static_getter variables
+ to generate half of the code each time.
+ */
+ static_setter = is_setter_method(n);
+
+ if (is_getter_method(n)) {
+ // This is to overcome types that can't be set and hence no setter.
+ if (!Equal(Getattr(n, "feature:immutable"), "1"))
+ static_getter = true;
+ }
+ } else if (wrapperType == staticmemberfn) {
+ wname = Getattr(n, "staticmemberfunctionHandler:sym:name");
+ } else {
+ if (class_name) {
+ if (Strstr(Getattr(n, "storage"), "friend") && Cmp(Getattr(n, "view"), "globalfunctionHandler") == 0) {
+ wname = iname;
+ } else {
+ wname = Getattr(n, "destructorHandler:sym:name");
+ }
+ } else {
+ wname = iname;
+ }
+ }
+
+ if (wrapperType == destructor) {
+ // We don't explicitly wrap the destructor for PHP - Zend manages the
+ // reference counting, and the user can just do `$obj = null;' or similar
+ // to remove a reference to an object.
+ Setattr(n, "wrap:name", wname);
+ (void)emit_action(n);
+ return SWIG_OK;
+ }
+
+ if (!static_getter) {
+ // Create or find existing PHPTypes.
+ phptypes = NULL;
+
+ String *key;
+ if (class_name && !Strstr(Getattr(n, "storage"), "friend")) {
+ key = NewStringf("%s:%s", class_name, wname);
+ } else {
+ key = NewStringf(":%s", wname);
+ }
+
+ PHPTypes *p = (PHPTypes*)GetVoid(all_phptypes, key);
+ if (p) {
+ // We already have an entry so use it.
+ phptypes = p;
+ Delete(key);
+ } else {
+ phptypes = new PHPTypes(n);
+ SetVoid(all_phptypes, key, phptypes);
+ }
+ if (!(wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"), "static") == 0)) {
+ phptypes->not_all_static();
+ }
+ }
+
+ f = NewWrapper();
+
+ if (static_getter) {
+ Printf(f->def, "{\n");
+ }
+
+ String *outarg = NewStringEmpty();
+ String *cleanup = NewStringEmpty();
+
+ if (!overloaded) {
+ if (!static_getter) {
+ if (class_name && !Strstr(Getattr(n, "storage"), "friend")) {
+ Printv(f->def, "static PHP_METHOD(", prefix, class_name, ",", wname, ") {\n", NIL);
+ } else {
+ if (wrap_nonclass_global) {
+ Printv(f->def, "static PHP_METHOD(", fake_class_name(), ",", wname, ") {\n",
+ " PHP_FN(", wname, ")(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n",
+ "}\n\n", NIL);
+ }
+
+ if (wrap_nonclass_fake_class) {
+ Printv(f->def, "static PHP_FUNCTION(", wname, ") {\n", NIL);
+ }
+ }
+ }
+ } else {
+ Printv(f->def, "static ZEND_NAMED_FUNCTION(", overloadwname, ") {\n", NIL);
+ }
+
+ emit_parameter_variables(l, f);
+ /* Attach standard typemaps */
+
+ emit_attach_parmmaps(l, f);
+
+ if (wrapperType == memberfn || wrapperType == membervar) {
+ // Assign "this" to arg1 and remove first entry from ParmList l.
+ Printf(f->code, "arg1 = (%s)SWIG_Z_FETCH_OBJ_P(ZEND_THIS)->ptr;\n", SwigType_lstr(Getattr(l, "type"), ""));
+ l = nextSibling(l);
+ }
+
+ // wrap:parms is used by overload resolution.
+ Setattr(n, "wrap:parms", l);
+
+ int num_arguments = emit_num_arguments(l);
+ int num_required = emit_num_required(l);
+ numopt = num_arguments - num_required;
+
+ if (num_arguments > 0) {
+ String *args = NewStringEmpty();
+ Printf(args, "zval args[%d]", num_arguments);
+ Wrapper_add_local(f, "args", args);
+ Delete(args);
+ args = NULL;
+ }
+ if (wrapperType == directorconstructor) {
+ Wrapper_add_local(f, "arg0", "zval *arg0 = ZEND_THIS");
+ }
+
+ // This generated code may be called:
+ // 1) as an object method, or
+ // 2) as a class-method/function (without a "this_ptr")
+ // Option (1) has "this_ptr" for "this", option (2) needs it as
+ // first parameter
+
+ // NOTE: possible we ignore this_ptr as a param for native constructor
+
+ if (numopt > 0) { // membervariable wrappers do not have optional args
+ Wrapper_add_local(f, "arg_count", "int arg_count");
+ Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n");
+ Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments);
+ Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n");
+ Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n");
+ } else if (static_setter || static_getter) {
+ if (num_arguments == 0) {
+ Printf(f->code, "if(ZEND_NUM_ARGS() == 0) {\n");
+ } else {
+ Printf(f->code, "if(ZEND_NUM_ARGS() == %d && zend_get_parameters_array_ex(%d, args) == SUCCESS) {\n", num_arguments, num_arguments);
+ }
+ } else {
+ if (num_arguments == 0) {
+ Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n");
+ } else {
+ Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments);
+ }
+ Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n");
+ }
+
+ /* Now convert from PHP to C variables */
+ // At this point, argcount if used is the number of deliberately passed args
+ // not including this_ptr even if it is used.
+ // It means error messages may be out by argbase with error
+ // reports. We can either take argbase into account when raising
+ // errors, or find a better way of dealing with _thisptr.
+ // I would like, if objects are wrapped, to assume _thisptr is always
+ // _this and not the first argument.
+ // This may mean looking at Language::memberfunctionHandler
+
+ for (i = 0, p = l; i < num_arguments; i++) {
+ /* Skip ignored arguments */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ /* Check if optional */
+ if (i >= num_required) {
+ Printf(f->code, "\tif(arg_count > %d) {\n", i);
+ }
+
+ tm = Getattr(p, "tmap:in");
+ if (!tm) {
+ SwigType *pt = Getattr(p, "type");
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ continue;
+ }
+
+ phptypes->process_phptype(p, i + 1, "tmap:in:phptype");
+ if (GetFlag(p, "tmap:in:byref")) phptypes->set_byref(i + 1);
+
+ String *source = NewStringf("args[%d]", i);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+ Printf(f->code, "%s\n", tm);
+ if (i == 0 && Getattr(p, "self")) {
+ Printf(f->code, "\tif(!arg1) {\n");
+ Printf(f->code, "\t zend_throw_exception(zend_ce_type_error, \"this pointer is NULL\", 0);\n");
+ Printf(f->code, "\t return;\n");
+ Printf(f->code, "\t}\n");
+ }
+
+ if (i >= num_required) {
+ Printf(f->code, "}\n");
+ }
+
+ p = Getattr(p, "tmap:in:next");
+
+ Delete(source);
+ }
+
+ if (is_member_director(n)) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Printf(f->code, "upcall = (director && (director->swig_get_self()==Z_OBJ_P(ZEND_THIS)));\n");
+ }
+
+ Swig_director_emit_dynamic_cast(n, f);
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (i = 0, p = l; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout")) && Len(tm)) {
+ Replaceall(tm, "$result", "return_value");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ if (!overloaded) {
+ Setattr(n, "wrap:name", wname);
+ } else {
+ Setattr(n, "wrap:name", overloadwname);
+ }
+ Setattr(n, "wrapper:method:name", wname);
+
+ bool php_constructor = (constructor && Cmp(class_name, Getattr(n, "constructorHandler:sym:name")) == 0);
+
+ /* emit function call */
+ String *actioncode = emit_action(n);
+
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", php_constructor ? "ZEND_THIS" : "return_value");
+ Replaceall(tm, "$owner", newobject ? "1" : "0");
+ Printf(f->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), name);
+ }
+ emit_return_variable(n, returntype, f);
+
+ List *return_types = phptypes->process_phptype(n, 0, "tmap:out:phptype");
+
+ if (class_name && !Strstr(Getattr(n, "storage"), "friend")) {
+ if (is_member_director(n)) {
+ String *parent = class_name;
+ while ((parent = Getattr(php_parent_class, parent)) != NULL) {
+ // Mark this method name as having no return type declaration for all
+ // classes we're derived from.
+ SetFlag(has_directed_descendent, NewStringf("%s:%s", parent, wname));
+ }
+ } else if (return_types) {
+ String *parent = class_name;
+ while ((parent = Getattr(php_parent_class, parent)) != NULL) {
+ String *key = NewStringf("%s:%s", parent, wname);
+ // The parent class method needs to have a superset of the possible
+ // return types of methods with the same name in subclasses.
+ List *v = Getattr(parent_class_method_return_type, key);
+ if (!v) {
+ // New entry.
+ Setattr(parent_class_method_return_type, key, Copy(return_types));
+ } else {
+ // Update existing entry.
+ PHPTypes::merge_type_lists(v, return_types);
+ }
+ }
+ }
+ }
+
+ if (outarg) {
+ Printv(f->code, outarg, NIL);
+ }
+
+ if (static_setter && cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ if (static_getter) {
+ Printf(f->code, "}\n");
+ }
+
+ if (static_setter || static_getter) {
+ Printf(f->code, "}\n");
+ }
+
+ if (!static_setter) {
+ Printf(f->code, "fail:\n");
+ Printv(f->code, cleanup, NIL);
+ Printf(f->code, "return;\n");
+ Printf(f->code, "}\n");
+ }
+
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(f->code, "$symname", iname);
+
+ Wrapper_print(f, s_wrappers);
+ DelWrapper(f);
+ f = NULL;
+
+ if (overloaded) {
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n, constructor);
+ }
+ } else {
+ if (!static_setter) {
+ create_command(class_name, wname, n, false, modes);
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * globalvariableHandler()
+ * ------------------------------------------------------------ */
+
+ /* PHP doesn't support intercepting reads and writes to global variables
+ * (nor static property reads and writes so we can't wrap them as static
+ * properties on a dummy class) so just let SWIG do its default thing and
+ * wrap them as name_get() and name_set().
+ */
+ //virtual int globalvariableHandler(Node *n) {
+ //}
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = GetChar(n, "name");
+ String *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ SwigType_remember(type);
+
+ String *wrapping_member_constant = Getattr(n, "memberconstantHandler:sym:name");
+ if (!wrapping_member_constant) {
+ {
+ tm = Swig_typemap_lookup("consttab", n, name, 0);
+ Replaceall(tm, "$value", value);
+ if (Getattr(n, "tmap:consttab:rinit")) {
+ Printf(r_init, "%s\n", tm);
+ } else {
+ Printf(s_cinit, "%s\n", tm);
+ }
+ }
+
+ {
+ tm = Swig_typemap_lookup("classconsttab", n, name, 0);
+
+ Replaceall(tm, "$class", fake_class_name());
+ Replaceall(tm, "$const_name", iname);
+ Replaceall(tm, "$value", value);
+ if (Getattr(n, "tmap:classconsttab:rinit")) {
+ Printf(r_init, "%s\n", tm);
+ } else {
+ Printf(s_cinit, "%s\n", tm);
+ }
+ }
+ } else {
+ tm = Swig_typemap_lookup("classconsttab", n, name, 0);
+ Replaceall(tm, "$class", class_name);
+ Replaceall(tm, "$const_name", wrapping_member_constant);
+ Replaceall(tm, "$value", value);
+ if (Getattr(n, "tmap:classconsttab:rinit")) {
+ Printf(r_init, "%s\n", tm);
+ } else {
+ Printf(s_cinit, "%s\n", tm);
+ }
+ }
+
+ wrapperType = standard;
+ return SWIG_OK;
+ }
+
+ /*
+ * PHP::pragma()
+ *
+ * Pragma directive.
+ *
+ * %pragma(php) code="String" # Includes a string in the .php file
+ * %pragma(php) include="file.php" # Includes a file in the .php file
+ */
+
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *type = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "php") == 0) {
+ if (Strcmp(type, "code") == 0) {
+ if (value) {
+ Printf(pragma_code, "%s\n", value);
+ }
+ } else if (Strcmp(type, "include") == 0) {
+ if (value) {
+ Printf(pragma_incl, "include '%s';\n", value);
+ }
+ } else if (Strcmp(type, "phpinfo") == 0) {
+ if (value) {
+ Printf(pragma_phpinfo, "%s\n", value);
+ }
+ } else if (Strcmp(type, "version") == 0) {
+ if (value) {
+ pragma_version = value;
+ }
+ } else {
+ Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type);
+ }
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ return Language::classDeclaration(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ class_name = symname;
+ base_class = NULL;
+ destructor_action = NULL;
+
+ Printf(all_cs_entry, "static const zend_function_entry class_%s_functions[] = {\n", class_name);
+
+ // namespace code to introduce namespaces into wrapper classes.
+ //if (nameSpace != NULL)
+ //Printf(s_oinit, "INIT_CLASS_ENTRY(internal_ce, \"%s\\\\%s\", class_%s_functions);\n", nameSpace, class_name, class_name);
+ //else
+ Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s%s\", class_%s_functions);\n", prefix, class_name, class_name);
+
+ if (shadow) {
+ char *rename = GetChar(n, "sym:name");
+
+ if (!addSymbol(rename, n))
+ return SWIG_ERROR;
+
+ /* Deal with inheritance */
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item) {
+ if (!GetFlag(base.item, "feature:ignore")) {
+ if (!base_class) {
+ base_class = Getattr(base.item, "sym:name");
+ } else {
+ /* Warn about multiple inheritance for additional base class(es) */
+ String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
+ String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
+ Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number,
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname);
+ }
+ }
+ base = Next(base);
+ }
+ }
+ }
+
+ if (GetFlag(n, "feature:exceptionclass") && Getattr(n, "feature:except")) {
+ /* PHP requires thrown objects to be instances of or derived from
+ * Exception, so that really needs to take priority over any
+ * explicit base class.
+ */
+ if (base_class) {
+ String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
+ Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number,
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, base_class);
+ }
+ base_class = NewString("Exception");
+ }
+
+ if (!base_class) {
+ Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", class_name);
+ } else if (Equal(base_class, "Exception")) {
+ Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, zend_ce_exception);\n", class_name);
+ } else if (is_class_wrapped(base_class)) {
+ Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, SWIG_Php_ce_%s);\n", class_name, base_class);
+ Setattr(php_parent_class, class_name, base_class);
+ } else {
+ Printf(s_oinit, " {\n");
+ Printf(s_oinit, " swig_type_info *type_info = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, \"_p_%s\");\n", base_class);
+ Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class_ex(&internal_ce, (zend_class_entry*)(type_info ? type_info->clientdata : NULL));\n", class_name);
+ Printf(s_oinit, " }\n");
+ }
+
+ if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) {
+ Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;\n", class_name);
+ }
+ if (GetFlag(n, "feature:php:allowdynamicproperties")) {
+ Append(s_oinit, "#ifdef ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES\n");
+ Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;\n", class_name);
+ Append(s_oinit, "#endif\n");
+ } else {
+ Append(s_oinit, "#ifdef ZEND_ACC_NO_DYNAMIC_PROPERTIES\n");
+ Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_NO_DYNAMIC_PROPERTIES;\n", class_name);
+ Append(s_oinit, "#endif\n");
+ }
+ String *swig_wrapped = swig_wrapped_interface_ce();
+ Printv(s_oinit, " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", &", swig_wrapped, ");\n", NIL);
+
+ {
+ Node *node = NewHash();
+ Setattr(node, "type", Getattr(n, "name"));
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ String *interfaces = Swig_typemap_lookup("phpinterfaces", node, "", 0);
+ Replaceall(interfaces, " ", "");
+ if (interfaces && Len(interfaces) > 0) {
+ // It seems we need to wait until RINIT time to look up class entries
+ // for interfaces by name. The downside is that this then happens for
+ // every request.
+ //
+ // Most pre-defined interfaces are accessible via zend_class_entry*
+ // variables declared in the PHP C API - these we can use at MINIT
+ // time, so we special case them. This will also be a little faster
+ // than looking up by name.
+ Printv(s_header,
+ "#ifdef __cplusplus\n",
+ "extern \"C\" {\n",
+ "#endif\n",
+ NIL);
+
+ String *r_init_prefix = NewStringEmpty();
+
+ List *interface_list = Split(interfaces, ',', -1);
+ int num_interfaces = Len(interface_list);
+ for (int i = 0; i < num_interfaces; ++i) {
+ String *interface = Getitem(interface_list, i);
+ // We generate conditional code in both minit and rinit - then we or the user
+ // just need to define SWIG_PHP_INTERFACE_xxx_CE (and optionally
+ // SWIG_PHP_INTERFACE_xxx_HEADER) to handle interface `xxx` at minit-time.
+ Printv(s_header,
+ "#ifdef SWIG_PHP_INTERFACE_", interface, "_HEADER\n",
+ "# include SWIG_PHP_INTERFACE_", interface, "_HEADER\n",
+ "#endif\n",
+ NIL);
+ Printv(s_oinit,
+ "#ifdef SWIG_PHP_INTERFACE_", interface, "_CE\n",
+ " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", SWIG_PHP_INTERFACE_", interface, "_CE);\n",
+ "#endif\n",
+ NIL);
+ Printv(r_init_prefix,
+ "#ifndef SWIG_PHP_INTERFACE_", interface, "_CE\n",
+ " {\n",
+ " zend_class_entry *swig_interface_ce = zend_lookup_class(zend_string_init(\"", interface, "\", sizeof(\"", interface, "\") - 1, 0));\n",
+ " if (swig_interface_ce)\n",
+ " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", swig_interface_ce);\n",
+ " else\n",
+ " zend_throw_exception(zend_ce_error, \"Interface \\\"", interface, "\\\" not found\", 0);\n",
+ " }\n",
+ "#endif\n",
+ NIL);
+ }
+
+ // Handle interfaces at the start of rinit so that they're added
+ // before any potential constant objects, etc which might be created
+ // later in rinit.
+ Insert(r_init, 0, r_init_prefix);
+ Delete(r_init_prefix);
+
+ Printv(s_header,
+ "#ifdef __cplusplus\n",
+ "}\n",
+ "#endif\n",
+ NIL);
+ }
+ Delete(interfaces);
+ }
+
+ Language::classHandler(n);
+
+ static bool emitted_base_object_handlers = false;
+ if (!emitted_base_object_handlers) {
+ Printf(s_creation, "static zend_object_handlers Swig_Php_base_object_handlers;\n\n");
+
+ // Set up a base zend_object_handlers structure which we can use as-is
+ // for classes without a destructor, and copy as the basis for other
+ // classes.
+ Printf(s_oinit, " Swig_Php_base_object_handlers = *zend_get_std_object_handlers();\n");
+ Printf(s_oinit, " Swig_Php_base_object_handlers.offset = XtOffsetOf(swig_object_wrapper, std);\n");
+ Printf(s_oinit, " Swig_Php_base_object_handlers.clone_obj = NULL;\n");
+ emitted_base_object_handlers = true;
+ }
+
+ Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n", class_name);
+
+ if (Getattr(n, "has_destructor")) {
+ if (destructor_action ? Equal(destructor_action, "free((char *) arg1);") : !CPlusPlus) {
+ // We can use a single function if the destructor action calls free()
+ // (either explicitly or as the default in C-mode) since free() doesn't
+ // care about the object's type. We currently only check for the exact
+ // code that Swig_cdestructor_call() emits.
+ static bool emitted_common_cdestructor = false;
+ if (!emitted_common_cdestructor) {
+ Printf(s_creation, "static zend_object_handlers Swig_Php_common_c_object_handlers;\n\n");
+ Printf(s_creation, "static void SWIG_Php_common_c_free_obj(zend_object *object) {free(SWIG_Php_free_obj(object));}\n\n");
+ Printf(s_creation, "static zend_object *SWIG_Php_common_c_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &Swig_Php_common_c_object_handlers);}\n");
+
+ Printf(s_oinit, " Swig_Php_common_c_object_handlers = Swig_Php_base_object_handlers;\n");
+ Printf(s_oinit, " Swig_Php_common_c_object_handlers.free_obj = SWIG_Php_common_c_free_obj;\n");
+
+ emitted_common_cdestructor = true;
+ }
+
+ Printf(s_oinit, " SWIG_Php_ce_%s->create_object = SWIG_Php_common_c_create_object;\n", class_name);
+ } else {
+ Printf(s_creation, "static zend_object_handlers %s_object_handlers;\n", class_name);
+ Printf(s_creation, "static zend_object *SWIG_Php_create_object_%s(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &%s_object_handlers);}\n", class_name, class_name);
+
+ Printf(s_creation, "static void SWIG_Php_free_obj_%s(zend_object *object) {",class_name);
+ String *type = Getattr(n, "classtype");
+ // Special case handling the delete call generated by
+ // Swig_cppdestructor_call() and generate simpler code.
+ if (destructor_action && !Equal(destructor_action, "delete arg1;")) {
+ Printv(s_creation, "\n"
+ " ", type, " *arg1 = (" , type, " *)SWIG_Php_free_obj(object);\n"
+ " if (arg1) {\n"
+ " ", destructor_action, "\n"
+ " }\n", NIL);
+ } else {
+ Printf(s_creation, "delete (%s *)SWIG_Php_free_obj(object);", type);
+ }
+ Printf(s_creation, "}\n\n");
+
+ Printf(s_oinit, " SWIG_Php_ce_%s->create_object = SWIG_Php_create_object_%s;\n", class_name, class_name);
+ Printf(s_oinit, " %s_object_handlers = Swig_Php_base_object_handlers;\n", class_name);
+ Printf(s_oinit, " %s_object_handlers.free_obj = SWIG_Php_free_obj_%s;\n", class_name, class_name);
+ }
+ } else {
+ static bool emitted_destructorless_create_object = false;
+ if (!emitted_destructorless_create_object) {
+ emitted_destructorless_create_object = true;
+ Printf(s_creation, "static zend_object *SWIG_Php_create_object(zend_class_entry *ce) {return SWIG_Php_do_create_object(ce, &Swig_Php_base_object_handlers);}\n", class_name);
+ }
+
+ Printf(s_oinit, " SWIG_Php_ce_%s->create_object = SWIG_Php_create_object;\n", class_name);
+ }
+
+ // If not defined we aren't wrapping any functions which use this type as a
+ // parameter or return value, in which case we don't need the clientdata
+ // set.
+ Printf(s_oinit, "#ifdef SWIGTYPE_p%s\n", SwigType_manglestr(Getattr(n, "classtypeobj")));
+ Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE_p%s,SWIG_Php_ce_%s);\n", SwigType_manglestr(Getattr(n, "classtypeobj")), class_name);
+ Printf(s_oinit, "#endif\n");
+ Printf(s_oinit, "\n");
+
+ generate_magic_property_methods(n);
+ Printf(all_cs_entry, " ZEND_FE_END\n};\n\n");
+
+ class_name = NULL;
+ base_class = NULL;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ wrapperType = memberfn;
+ Language::memberfunctionHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ if (magic_set == NULL) {
+ magic_set = NewStringEmpty();
+ magic_get = NewStringEmpty();
+ magic_isset = NewStringEmpty();
+ }
+
+ String *v_name = GetChar(n, "name");
+
+ Printf(magic_set, "\nelse if (strcmp(ZSTR_VAL(arg2),\"%s\") == 0) {\n", v_name);
+ Printf(magic_set, "zend_string *swig_funcname = ZSTR_INIT_LITERAL(\"%s_set\", 0);\n", v_name);
+ Append(magic_set, "zend_function *swig_zend_func = zend_std_get_method(&Z_OBJ_P(ZEND_THIS), swig_funcname, NULL);\n");
+ Append(magic_set, "zend_string_release(swig_funcname);\n");
+ Printf(magic_set, "zend_call_known_instance_method(swig_zend_func, Z_OBJ_P(ZEND_THIS), return_value, 1, &args[1]);\n");
+ Printf(magic_set, "}\n");
+
+ Printf(magic_get, "\nelse if (strcmp(ZSTR_VAL(arg2),\"%s\") == 0) {\n", v_name);
+ Printf(magic_get, "zend_string *swig_funcname = ZSTR_INIT_LITERAL(\"%s_get\", 0);\n", v_name);
+ Append(magic_get, "zend_function *swig_zend_func = zend_std_get_method(&Z_OBJ_P(ZEND_THIS), swig_funcname, NULL);\n");
+ Append(magic_get, "zend_string_release(swig_funcname);\n");
+ Printf(magic_get, "zend_call_known_instance_method(swig_zend_func, Z_OBJ_P(ZEND_THIS), return_value, 0, NULL);\n");
+ Printf(magic_get, "}\n");
+
+ Printf(magic_isset, "\nelse if (strcmp(ZSTR_VAL(arg2),\"%s\") == 0) {\n", v_name);
+ Printf(magic_isset, "RETVAL_TRUE;\n}\n");
+
+ wrapperType = membervar;
+ Language::membervariableHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ wrapperType = staticmembervar;
+ Language::staticmembervariableHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ wrapperType = staticmemberfn;
+ Language::staticmemberfunctionHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ int abstractConstructorHandler(Node *) {
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ if (Swig_directorclass(n)) {
+ String *ctype = GetChar(Swig_methodclass(n), "classtype");
+ String *sname = GetChar(Swig_methodclass(n), "sym:name");
+ String *args = NewStringEmpty();
+ ParmList *p = Getattr(n, "parms");
+ int i;
+
+ for (i = 0; p; p = nextSibling(p), i++) {
+ if (i) {
+ Printf(args, ", ");
+ }
+ if (Strcmp(GetChar(p, "type"), SwigType_str(GetChar(p, "type"), 0))) {
+ SwigType *t = Getattr(p, "type");
+ Printf(args, "%s", SwigType_rcaststr(t, 0));
+ if (SwigType_isreference(t)) {
+ Append(args, "*");
+ }
+ }
+ Printf(args, "arg%d", i+1);
+ }
+
+ /* director ctor code is specific for each class */
+ Delete(director_ctor_code);
+ director_ctor_code = NewStringEmpty();
+ director_prot_ctor_code = NewStringEmpty();
+ Printf(director_ctor_code, "if (Z_OBJCE_P(arg0) == SWIG_Php_ce_%s) { /* not subclassed */\n", class_name);
+ Printf(director_prot_ctor_code, "if (Z_OBJCE_P(arg0) == SWIG_Php_ce_%s) { /* not subclassed */\n", class_name);
+ Printf(director_ctor_code, " %s = new %s(%s);\n", Swig_cresult_name(), ctype, args);
+ Printf(director_prot_ctor_code,
+ " zend_throw_exception(zend_ce_type_error, \"accessing abstract class or protected constructor\", 0);\n"
+ " return;\n");
+ if (i) {
+ Insert(args, 0, ", ");
+ }
+ Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args);
+ Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args);
+ Delete(args);
+
+ wrapperType = directorconstructor;
+ } else {
+ wrapperType = constructor;
+ }
+ Language::constructorHandler(n);
+ wrapperType = standard;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+ virtual int destructorHandler(Node *n) {
+ wrapperType = destructor;
+ Language::destructorHandler(n);
+ destructor_action = Getattr(n, "wrap:action");
+ wrapperType = standard;
+ return SWIG_OK;
+ }
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewStringEmpty();
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("zval");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ // There should always be a "self" parameter first.
+ assert(ParmList_len(parms) > 0);
+
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call);
+ Append(w->def, "}");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+ return Language::classDirectorConstructor(n);
+ }
+
+ int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ SwigType *returntype = Getattr(n, "type");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewStringEmpty();
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewStringEmpty();
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (Cmp(returntype, "void") == 0 && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> PHP) */
+ Swig_director_parms_fixup(l);
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+
+ /* build argument list and type conversion string */
+ idx = 0;
+ p = l;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ String *parse = Getattr(p, "tmap:directorin:parse");
+ if (!parse) {
+ String *input = NewStringf("&args[%d]", idx++);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ Printv(wrap_args, tm, "\n", NIL);
+ } else {
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ p = nextSibling(p);
+ }
+
+ if (!idx) {
+ Printf(w->code, "zval *args = NULL;\n");
+ } else {
+ Printf(w->code, "zval args[%d];\n", idx);
+ }
+ // typemap_directorout testcase requires that 0 can be assigned to the
+ // variable named after the result of Swig_cresult_name(), so that can't
+ // be a zval - make it a pointer to one instead.
+ Printf(w->code, "zval swig_zval_result;\n");
+ Printf(w->code, "zval * SWIGUNUSED %s = &swig_zval_result;\n", Swig_cresult_name());
+
+ /* wrap complex arguments to zvals */
+ Append(w->code, wrap_args);
+
+ const char *funcname = GetChar(n, "sym:name");
+ Append(w->code, "{\n");
+ Printf(w->code, "zend_string *swig_funcname = zend_string_init(\"%s\", %d, 0);\n", funcname, strlen(funcname));
+ Append(w->code, "zend_function *swig_zend_func = zend_std_get_method(&Z_OBJ(swig_self), swig_funcname, NULL);\n");
+ Append(w->code, "zend_string_release(swig_funcname);\n");
+ Printf(w->code, "if (swig_zend_func) zend_call_known_instance_method(swig_zend_func, Z_OBJ(swig_self), &swig_zval_result, %d, args);\n", idx);
+
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ if (!tm || Len(tm) == 0 || Equal(tm, "1")) {
+ // Skip marshalling the return value as there isn't one.
+ tm = NewString("if ($error) SWIG_fail;");
+ }
+
+ Replaceall(tm, "$error", "EG(exception)");
+ Printv(w->code, Str(tm), "\n}\n{\n", NIL);
+ Delete(tm);
+
+ /* marshal return value from PHP to C/C++ type */
+
+ String *cleanup = NewStringEmpty();
+ String *outarg = NewStringEmpty();
+
+ idx = 0;
+
+ /* marshal return value */
+ if (!is_void) {
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ char temp[24];
+ sprintf(temp, "%d", idx);
+ Replaceall(tm, "$argnum", temp);
+
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ Append(w->code, "fail: ;\n");
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewStringEmpty();
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ int classDirectorDisown(Node *n) {
+ wrapperType = directordisown;
+ int result = Language::classDirectorDisown(n);
+ wrapperType = standard;
+ return result;
+ }
+}; /* class PHP */
+
+static PHP *maininstance = 0;
+
+List *PHPTypes::process_phptype(Node *n, int key, const String_or_char *attribute_name) {
+
+ while (Len(merged_types) <= key) {
+ Append(merged_types, NewList());
+ }
+
+ String *phptype = Getattr(n, attribute_name);
+ if (!phptype || Len(phptype) == 0) {
+ // There's no type declaration, so any merged version has no type declaration.
+ //
+ // Use a DOH None object as a marker to indicate there's no type
+ // declaration for this parameter/return value (you can't store NULL as a
+ // value in a DOH List).
+ Setitem(merged_types, key, None);
+ return NULL;
+ }
+
+ DOH *merge_list = Getitem(merged_types, key);
+ if (merge_list == None) return NULL;
+
+ List *types = Split(phptype, '|', -1);
+ String *first_type = Getitem(types, 0);
+ if (Char(first_type)[0] == '?') {
+ if (Len(types) > 1) {
+ Printf(stderr, "warning: Invalid phptype: '%s' (can't use ? and | together)\n", phptype);
+ }
+ // Treat `?foo` just like `foo|null`.
+ Append(types, "null");
+ Setitem(types, 0, NewString(Char(first_type) + 1));
+ }
+
+ SortList(types, NULL);
+ String *prev = NULL;
+ for (Iterator i = First(types); i.item; i = Next(i)) {
+ if (prev && Equal(prev, i.item)) {
+ Printf(stderr, "warning: Invalid phptype: '%s' (duplicate entry for '%s')\n", phptype, i.item);
+ continue;
+ }
+
+ if (key > 0 && Equal(i.item, "void")) {
+ // Reject void for parameter type.
+ Printf(stderr, "warning: Invalid phptype: '%s' ('%s' can't be used as a parameter phptype)\n", phptype, i.item);
+ continue;
+ }
+
+ if (Equal(i.item, "SWIGTYPE")) {
+ String *type = Getattr(n, "type");
+ Node *class_node = maininstance->classLookup(type);
+ if (class_node) {
+ // FIXME: Prefix classname with a backslash to prevent collisions
+ // with built-in types? Or are non of those valid anyway and so will
+ // have been renamed at this point?
+ Append(merge_list, Getattr(class_node, "sym:name"));
+ } else {
+ // SWIG wraps a pointer to a non-object type as an object in a PHP
+ // class named based on the SWIG-mangled C/C++ type.
+ //
+ // FIXME: We should check this is actually a known pointer to
+ // non-object type so we complain about `phptype="SWIGTYPE"` being
+ // used for PHP types like `int` or `string` (currently this only
+ // fails at runtime and the error isn't very helpful). We could
+ // check the condition
+ //
+ // raw_pointer_types && Getattr(raw_pointer_types, SwigType_manglestr(type))
+ //
+ // except that raw_pointer_types may not have been fully filled in when
+ // we are called.
+ Append(merge_list, NewStringf("SWIG\\%s", SwigType_manglestr(type)));
+ }
+ } else {
+ Append(merge_list, i.item);
+ }
+ prev = i.item;
+ }
+ SortList(merge_list, NULL);
+ return merge_list;
+}
+
+void PHPTypes::merge_type_lists(List *merge_list, List *o_merge_list) {
+ int i = 0, j = 0;
+ while (j < Len(o_merge_list)) {
+ String *candidate = Getitem(o_merge_list, j);
+ while (i < Len(merge_list)) {
+ int cmp = Cmp(Getitem(merge_list, i), candidate);
+ if (cmp == 0)
+ goto handled;
+ if (cmp > 0)
+ break;
+ ++i;
+ }
+ Insert(merge_list, i, candidate);
+ ++i;
+handled:
+ ++j;
+ }
+}
+
+void PHPTypes::merge_from(const PHPTypes* o) {
+ num_required = std::min(num_required, o->num_required);
+
+ if (o->byref) {
+ if (byref == NULL) {
+ byref = Copy(o->byref);
+ } else {
+ int len = std::min(Len(byref), Len(o->byref));
+ // Start at 1 because we only want to merge parameter types, and key 0 is
+ // the return type.
+ for (int key = 1; key < len; ++key) {
+ if (Getitem(byref, key) == None &&
+ Getitem(o->byref, key) != None) {
+ Setitem(byref, key, "");
+ }
+ }
+ for (int key = len; key < Len(o->byref); ++key) {
+ Append(byref, Getitem(o->byref, key));
+ }
+ }
+ }
+
+ int len = std::min(Len(merged_types), Len(o->merged_types));
+ for (int key = 0; key < len; ++key) {
+ DOH *merge_list = Getitem(merged_types, key);
+ // None trumps anything else in the merge.
+ if (merge_list == None) continue;
+ DOH *o_merge_list = Getitem(o->merged_types, key);
+ if (o_merge_list == None) {
+ Setitem(merged_types, key, None);
+ continue;
+ }
+ merge_type_lists(merge_list, o_merge_list);
+ }
+ // Copy over any additional entries.
+ for (int key = len; key < Len(o->merged_types); ++key) {
+ Append(merged_types, Copy(Getitem(o->merged_types, key)));
+ }
+}
+
+// Collect non-class pointer types from the type table so we can set up PHP
+// classes for them later.
+//
+// NOTE: it's a function NOT A PHP::METHOD
+extern "C" {
+static void typetrace(const SwigType *ty, String *mangled, String *clientdata) {
+ if (maininstance->classLookup(ty) == NULL) {
+ // a non-class pointer
+ if (!raw_pointer_types) {
+ raw_pointer_types = NewHash();
+ }
+ Setattr(raw_pointer_types, mangled, mangled);
+ }
+ if (r_prevtracefunc)
+ (*r_prevtracefunc) (ty, mangled, clientdata);
+}
+}
+
+/* -----------------------------------------------------------------------------
+ * new_swig_php() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_php() {
+ maininstance = new PHP;
+ if (!r_prevtracefunc) {
+ r_prevtracefunc = SwigType_remember_trace(typetrace);
+ } else {
+ Printf(stderr, "php Typetrace vector already saved!\n");
+ assert(0);
+ }
+ return maininstance;
+}
+
+extern "C" Language *swig_php(void) {
+ return new_swig_php();
+}
diff --git a/contrib/tools/swig/Source/Modules/python.cxx b/contrib/tools/swig/Source/Modules/python.cxx
new file mode 100644
index 00000000000..f9a2db61c62
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/python.cxx
@@ -0,0 +1,5927 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * python.cxx
+ *
+ * Python language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdint.h>
+#include "pydoc.h"
+
+#define PYSHADOW_MEMBER 0x2
+#define WARN_PYTHON_MULTIPLE_INH 405
+
+#define PYTHON_INT_MAX (2147483647)
+#define PYTHON_INT_MIN (-2147483647-1)
+
+static String *const_code = 0;
+static String *module = 0;
+static String *package = 0;
+static String *mainmodule = 0;
+static String *interface = 0;
+static String *global_name = 0;
+static int shadow = 1;
+static int use_kw = 0;
+static int director_method_index = 0;
+static int builtin = 0;
+
+static File *f_begin = 0;
+static File *f_runtime = 0;
+static File *f_runtime_h = 0;
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_directors = 0;
+static File *f_directors_h = 0;
+static File *f_init = 0;
+static File *f_shadow_py = 0;
+static String *f_shadow = 0;
+static String *f_shadow_begin = 0;
+static Hash *f_shadow_imports = 0;
+static String *f_shadow_after_begin = 0;
+static String *f_shadow_stubs = 0;
+static Hash *builtin_getset = 0;
+static Hash *builtin_closures = 0;
+static Hash *class_members = 0;
+static File *f_builtins = 0;
+static String *builtin_tp_init = 0;
+static String *builtin_methods = 0;
+static String *builtin_default_unref = 0;
+static String *builtin_closures_code = 0;
+static String *f_varlinks = 0;
+
+static String *methods;
+static String *methods_proxydocs;
+static String *class_name;
+static String *shadow_indent = 0;
+static int in_class = 0;
+static int no_header_file = 0;
+static int max_bases = 0;
+static int builtin_bases_needed = 0;
+
+/* C++ Support + Shadow Classes */
+
+static int have_constructor = 0;
+static int have_repr = 0;
+static bool have_builtin_static_member_method_callback = false;
+static bool have_fast_proxy_static_member_method_callback = false;
+static String *real_classname;
+
+/* Thread Support */
+static int threads = 0;
+static int nothreads = 0;
+
+/* Other options */
+static int dirvtable = 0;
+static int doxygen = 0;
+static int fastunpack = 1;
+static int fastproxy = 0;
+static int olddefs = 0;
+static int castmode = 0;
+static int extranative = 0;
+static int nortti = 0;
+static int relativeimport = 0;
+static int flat_static_method = 0;
+
+/* flags for the make_autodoc function */
+namespace {
+enum autodoc_t {
+ AUTODOC_CLASS,
+ AUTODOC_CTOR,
+ AUTODOC_DTOR,
+ AUTODOC_STATICFUNC,
+ AUTODOC_FUNC,
+ AUTODOC_METHOD,
+ AUTODOC_CONST,
+ AUTODOC_VAR
+};
+}
+
+static const char *usage1 = "\
+Python Options (available with -python)\n\
+ -builtin - Create Python built-in types rather than proxy classes, for better performance\n\
+ -castmode - Enable the casting mode, which allows implicit cast between types in Python\n\
+ -debug-doxygen-parser - Display doxygen parser module debugging information\n\
+ -debug-doxygen-translator - Display doxygen translator module debugging information\n\
+ -dirvtable - Generate a pseudo virtual table for directors for faster dispatch\n\
+ -doxygen - Convert C++ doxygen comments to pydoc comments in proxy classes\n\
+ -extranative - Return extra native wrappers for C++ std containers wherever possible\n\
+ -fastproxy - Use fast proxy mechanism for member methods\n\
+ -flatstaticmethod - Generate additional flattened Python methods for C++ static methods\n\
+ -globals <name> - Set <name> used to access C global variable (default: 'cvar')\n\
+ -interface <mod>- Set low-level C/C++ module name to <mod> (default: module name prefixed by '_')\n\
+ -keyword - Use keyword arguments\n";
+static const char *usage2 = "\
+ -nofastunpack - Use traditional UnpackTuple method to parse the argument functions\n\
+ -noh - Don't generate the output header file\n";
+static const char *usage3 = "\
+ -noproxy - Don't generate proxy classes\n\
+ -nortti - Disable the use of the native C++ RTTI with directors\n\
+ -nothreads - Disable thread support for the entire interface\n\
+ -olddefs - Keep the old method definitions when using -fastproxy\n\
+ -relativeimport - Use relative Python imports\n\
+ -threads - Add thread support for all the interface\n\
+ -O - Enable the following optimization options:\n\
+ -fastdispatch -fastproxy -fvirtual\n\
+\n";
+
+static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_slot = NULL) {
+ static String *zero = NewString("0");
+ String *val = n && key && *key ? Getattr(n, key) : NULL;
+ return val ? val : default_slot ? default_slot : zero;
+}
+
+static void printSlot(File *f, String *slotval, const char *slotname, const char *functype = NULL) {
+ String *slotval_override = 0;
+ if (functype && Strcmp(slotval, "0") == 0)
+ slotval = slotval_override = NewStringf("(%s) %s", functype, slotval);
+ int len = Len(slotval);
+ int fieldwidth = len >= 39 ? 1 : 39 - len;
+ Printf(f, " %s,%*s/* %s */\n", slotval, fieldwidth, "", slotname);
+ Delete(slotval_override);
+}
+
+static void printSlot2(File *f, String *slotval, const char *slotname, const char *functype = NULL) {
+ String *slotval_override = 0;
+ if (functype && Strcmp(slotval, "0") == 0)
+ slotval = slotval_override = NewStringf("(%s) %s", functype, slotval);
+ int len = Len(slotname);
+ int fieldwidth = len >= 30 ? 1 : 30 - len;
+ Printf(f, " { Py_%s,%*s(void *)%s },\n", slotname, fieldwidth, "", slotval);
+ Delete(slotval_override);
+}
+
+static String *getClosure(String *functype, String *wrapper, int funpack = 0) {
+ static const char *functypes[] = {
+ "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE",
+ "destructor", "SWIGPY_DESTRUCTOR_CLOSURE",
+ "inquiry", "SWIGPY_INQUIRY_CLOSURE",
+ "getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE",
+ "binaryfunc", "SWIGPY_BINARYFUNC_CLOSURE",
+ "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE",
+ "ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE",
+ "lenfunc", "SWIGPY_LENFUNC_CLOSURE",
+ "ssizeargfunc", "SWIGPY_SSIZEARGFUNC_CLOSURE",
+ "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE",
+ "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE",
+ "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE",
+ "objobjproc", "SWIGPY_OBJOBJPROC_CLOSURE",
+ "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE",
+ "reprfunc", "SWIGPY_REPRFUNC_CLOSURE",
+ "hashfunc", "SWIGPY_HASHFUNC_CLOSURE",
+ "iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE",
+ NULL
+ };
+
+ static const char *funpack_functypes[] = {
+ "unaryfunc", "SWIGPY_UNARYFUNC_CLOSURE",
+ "destructor", "SWIGPY_DESTRUCTOR_CLOSURE",
+ "inquiry", "SWIGPY_INQUIRY_CLOSURE",
+ "getiterfunc", "SWIGPY_GETITERFUNC_CLOSURE",
+ "ternaryfunc", "SWIGPY_TERNARYFUNC_CLOSURE",
+ "ternarycallfunc", "SWIGPY_TERNARYCALLFUNC_CLOSURE",
+ "lenfunc", "SWIGPY_LENFUNC_CLOSURE",
+ "ssizeargfunc", "SWIGPY_FUNPACK_SSIZEARGFUNC_CLOSURE",
+ "ssizessizeargfunc", "SWIGPY_SSIZESSIZEARGFUNC_CLOSURE",
+ "ssizeobjargproc", "SWIGPY_SSIZEOBJARGPROC_CLOSURE",
+ "ssizessizeobjargproc", "SWIGPY_SSIZESSIZEOBJARGPROC_CLOSURE",
+ "objobjproc", "SWIGPY_FUNPACK_OBJOBJPROC_CLOSURE",
+ "objobjargproc", "SWIGPY_OBJOBJARGPROC_CLOSURE",
+ "reprfunc", "SWIGPY_REPRFUNC_CLOSURE",
+ "hashfunc", "SWIGPY_HASHFUNC_CLOSURE",
+ "iternextfunc", "SWIGPY_ITERNEXTFUNC_CLOSURE",
+ NULL
+ };
+
+ if (!functype)
+ return NULL;
+ char *c = Char(functype);
+ int i;
+ if (funpack) {
+ for (i = 0; funpack_functypes[i] != NULL; i += 2) {
+ if (!strcmp(c, funpack_functypes[i]))
+ return NewStringf("%s(%s)", funpack_functypes[i + 1], wrapper);
+ }
+ } else {
+ for (i = 0; functypes[i] != NULL; i += 2) {
+ if (!strcmp(c, functypes[i]))
+ return NewStringf("%s(%s)", functypes[i + 1], wrapper);
+ }
+ }
+ return NULL;
+}
+
+class PYTHON:public Language {
+public:
+ PYTHON() {
+ /* Add code to manage protected constructors and directors */
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing abstract class or protected constructor\"); \n", " SWIG_fail;\n", "}\n", NIL);
+ director_multiple_inheritance = 1;
+ directorLanguage();
+ }
+
+ ~PYTHON() {
+ delete doxygenTranslator;
+ }
+
+ /* ------------------------------------------------------------
+ * Thread Implementation
+ * ------------------------------------------------------------ */
+ int threads_enable(Node *n) const {
+ return threads && !GetFlagAttr(n, "feature:nothread");
+ }
+
+ int initialize_threads(String *f_init) {
+ if (!threads) {
+ return SWIG_OK;
+ }
+ Printf(f_init, "\n");
+ Printf(f_init, "/* Initialize threading */\n");
+ Printf(f_init, "SWIG_PYTHON_INITIALIZE_THREADS;\n");
+
+ return SWIG_OK;
+ }
+
+ virtual void thread_begin_block(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadblock")) {
+ String *bb = Getattr(n, "feature:threadbeginblock");
+ if (bb) {
+ Append(f, bb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_BEGIN_BLOCK;\n");
+ }
+ }
+ }
+
+ virtual void thread_end_block(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadblock")) {
+ String *eb = Getattr(n, "feature:threadendblock");
+ if (eb) {
+ Append(f, eb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_END_BLOCK;\n");
+ }
+ }
+ }
+
+ virtual void thread_begin_allow(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadallow")) {
+ String *bb = Getattr(n, "feature:threadbeginallow");
+ Append(f, "{\n");
+ if (bb) {
+ Append(f, bb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_BEGIN_ALLOW;\n");
+ }
+ }
+ }
+
+ virtual void thread_end_allow(Node *n, String *f) {
+ if (!GetFlag(n, "feature:nothreadallow")) {
+ String *eb = Getattr(n, "feature:threadendallow");
+ Append(f, "\n");
+ if (eb) {
+ Append(f, eb);
+ } else {
+ Append(f, "SWIG_PYTHON_THREAD_END_ALLOW;");
+ }
+ Append(f, "\n}");
+ }
+ }
+
+
+ /* ------------------------------------------------------------
+ * main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("python");
+
+ int doxygen_translator_flags = 0;
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-interface") == 0) {
+ if (argv[i + 1]) {
+ interface = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-globals") == 0) {
+ if (argv[i + 1]) {
+ global_name = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
+ shadow = 1;
+ Swig_mark_arg(i);
+ } else if ((strcmp(argv[i], "-noproxy") == 0)) {
+ shadow = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-keyword") == 0) {
+ use_kw = 1;
+ SWIG_cparse_set_compact_default_args(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nortti") == 0) {
+ nortti = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-threads") == 0) {
+ threads = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nothreads") == 0) {
+ /* Turn off thread support mode */
+ nothreads = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-dirvtable") == 0) {
+ dirvtable = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-doxygen") == 0) {
+ doxygen = 1;
+ scan_doxygen_comments = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-doxygen-translator") == 0) {
+ doxygen_translator_flags |= DoxygenTranslator::debug_translator;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-debug-doxygen-parser") == 0) {
+ doxygen_translator_flags |= DoxygenTranslator::debug_parser;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nofastunpack") == 0) {
+ fastunpack = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-fastproxy") == 0) {
+ fastproxy = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-olddefs") == 0) {
+ olddefs = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-castmode") == 0) {
+ castmode = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-extranative") == 0) {
+ extranative = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-flatstaticmethod") == 0) {
+ flat_static_method = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noh") == 0) {
+ no_header_file = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-newvwm") == 0) {
+ /* Turn on new value wrapper mode */
+ /* Undocumented option, did have -help text: New value wrapper mode, use only when everything else fails */
+ Swig_value_wrapper_mode(1);
+ no_header_file = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-O") == 0) {
+ fastproxy = 1;
+ Wrapper_fast_dispatch_mode_set(1);
+ Wrapper_virtual_elimination_mode_set(1);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage1, stdout);
+ fputs(usage2, stdout);
+ fputs(usage3, stdout);
+ } else if (strcmp(argv[i], "-builtin") == 0) {
+ builtin = 1;
+ Preprocessor_define("SWIGPYTHON_BUILTIN", 0);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-relativeimport") == 0) {
+ relativeimport = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppcast") == 0 ||
+ strcmp(argv[i], "-fastinit") == 0 ||
+ strcmp(argv[i], "-fastquery") == 0 ||
+ strcmp(argv[i], "-fastunpack") == 0 ||
+ strcmp(argv[i], "-modern") == 0 ||
+ strcmp(argv[i], "-modernargs") == 0 ||
+ strcmp(argv[i], "-noproxydel") == 0 ||
+ strcmp(argv[i], "-safecstrings") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. Ignored, this option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-py3") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. Ignored, this option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-aliasobj0") == 0 ||
+ strcmp(argv[i], "-buildnone") == 0 ||
+ strcmp(argv[i], "-classic") == 0 ||
+ strcmp(argv[i], "-classptr") == 0 ||
+ strcmp(argv[i], "-new_repr") == 0 ||
+ strcmp(argv[i], "-new_vwm") == 0 ||
+ strcmp(argv[i], "-newrepr") == 0 ||
+ strcmp(argv[i], "-noaliasobj0") == 0 ||
+ strcmp(argv[i], "-nobuildnone") == 0 ||
+ strcmp(argv[i], "-nocastmode") == 0 ||
+ strcmp(argv[i], "-nocppcast") == 0 ||
+ strcmp(argv[i], "-nodirvtable") == 0 ||
+ strcmp(argv[i], "-noextranative") == 0 ||
+ strcmp(argv[i], "-nofastinit") == 0 ||
+ strcmp(argv[i], "-nofastproxy") == 0 ||
+ strcmp(argv[i], "-nofastquery") == 0 ||
+ strcmp(argv[i], "-nomodern") == 0 ||
+ strcmp(argv[i], "-nomodernargs") == 0 ||
+ strcmp(argv[i], "-noolddefs") == 0 ||
+ strcmp(argv[i], "-nooutputtuple") == 0 ||
+ strcmp(argv[i], "-noproxyimport") == 0 ||
+ strcmp(argv[i], "-nosafecstrings") == 0 ||
+ strcmp(argv[i], "-old_repr") == 0 ||
+ strcmp(argv[i], "-oldrepr") == 0 ||
+ strcmp(argv[i], "-outputtuple") == 0 ||
+ strcmp(argv[i], "-proxydel") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer available.\n", argv[i]);
+ Swig_mark_arg(i);
+ Exit(EXIT_FAILURE);
+ }
+
+ }
+ }
+
+ if (builtin && !shadow) {
+ Printf(stderr, "Incompatible options -builtin and -noproxy specified.\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ if (fastproxy) {
+ Preprocessor_define("SWIGPYTHON_FASTPROXY", 0);
+ }
+
+ if (doxygen)
+ doxygenTranslator = new PyDocConverter(doxygen_translator_flags);
+
+ if (!global_name)
+ global_name = NewString("cvar");
+ Preprocessor_define("SWIGPYTHON 1", 0);
+ SWIG_config_file("python.swg");
+ allow_overloading();
+ }
+
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ /* check if directors are enabled for this module. note: this
+ * is a "master" switch, without which no director code will be
+ * emitted. %feature("director") statements are also required
+ * to enable directors for individual classes or methods.
+ *
+ * use %module(directors="1") modulename at the start of the
+ * interface file to enable director generation.
+ */
+ String *mod_docstring = NULL;
+ String *moduleimport = NULL;
+ {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ Node *options = Getattr(mod, "options");
+ if (options) {
+ int dirprot = 0;
+ if (Getattr(options, "dirprot")) {
+ dirprot = 1;
+ }
+ if (Getattr(options, "nodirprot")) {
+ dirprot = 0;
+ }
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ if (dirprot)
+ allow_dirprot();
+ }
+ if (Getattr(options, "threads")) {
+ threads = 1;
+ }
+ if (Getattr(options, "castmode")) {
+ castmode = 1;
+ }
+ if (Getattr(options, "nocastmode")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "nocastmode");
+ Exit(EXIT_FAILURE);
+ }
+ if (Getattr(options, "extranative")) {
+ extranative = 1;
+ }
+ if (Getattr(options, "noextranative")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "noextranative");
+ Exit(EXIT_FAILURE);
+ }
+ if (Getattr(options, "outputtuple")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "outputtuple");
+ Exit(EXIT_FAILURE);
+ }
+ if (Getattr(options, "nooutputtuple")) {
+ Printf(stderr, "Deprecated module option: %s. This option is no longer supported.\n", "nooutputtuple");
+ Exit(EXIT_FAILURE);
+ }
+ mod_docstring = Getattr(options, "docstring");
+ package = Getattr(options, "package");
+ moduleimport = Getattr(options, "moduleimport");
+ }
+ }
+ }
+
+ /* Set comparison with none for ConstructorToFunction */
+ setSubclassInstanceCheck(NewString("$arg != Py_None"));
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = !no_header_file ? Getattr(n, "outfile_h") : 0;
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+ builtin_getset = NewHash();
+ builtin_closures = NewHash();
+ builtin_closures_code = NewString("");
+ class_members = NewHash();
+ builtin_methods = NewString("");
+ builtin_default_unref = NewString("delete $self;");
+ f_varlinks = NewString("");
+
+ if (builtin) {
+ f_builtins = NewString("");
+ }
+
+ if (Swig_directors_enabled()) {
+ if (!no_header_file) {
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ } else {
+ f_runtime_h = f_runtime;
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ const_code = NewString("");
+ methods = NewString("");
+ methods_proxydocs = NewString("");
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "PYTHON");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ if (nothreads) {
+ Printf(f_runtime, "#define SWIG_PYTHON_NO_THREADS\n");
+ } else if (threads) {
+ Printf(f_runtime, "#define SWIG_PYTHON_THREADS\n");
+ }
+
+ if (!dirvtable) {
+ Printf(f_runtime, "#define SWIG_PYTHON_DIRECTOR_NO_VTABLE\n");
+ }
+
+ if (nortti) {
+ Printf(f_runtime, "#ifndef SWIG_DIRECTOR_NORTTI\n");
+ Printf(f_runtime, "#define SWIG_DIRECTOR_NORTTI\n");
+ Printf(f_runtime, "#endif\n");
+ }
+
+ if (castmode) {
+ Printf(f_runtime, "#define SWIG_CASTRANK_MODE\n");
+ Printf(f_runtime, "#define SWIG_PYTHON_CAST_MODE\n");
+ }
+
+ if (extranative) {
+ Printf(f_runtime, "#define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS\n");
+ }
+
+ if (builtin) {
+ Printf(f_runtime, "#define SWIGPYTHON_BUILTIN\n");
+ }
+
+ if (fastproxy) {
+ Printf(f_runtime, "#define SWIGPYTHON_FASTPROXY\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ Printf(f_header, "#ifdef SWIG_TypeQuery\n");
+ Printf(f_header, "# undef SWIG_TypeQuery\n");
+ Printf(f_header, "#endif\n");
+ Printf(f_header, "#define SWIG_TypeQuery SWIG_Python_TypeQuery\n");
+
+
+ /* Set module name */
+ module = Copy(Getattr(n, "name"));
+ mainmodule = Getattr(n, "name");
+
+ if (Swig_directors_enabled()) {
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module);
+ if (dirprot_mode()) {
+ Printf(f_directors_h, "#include <map>\n");
+ Printf(f_directors_h, "#include <string>\n\n");
+ }
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+ }
+
+ /* If shadow classing is enabled, we're going to change the module name to "_module" */
+ String *default_import_code = NewString("");
+ if (shadow) {
+ String *filen = NewStringf("%s%s.py", SWIG_output_directory(), Char(module));
+ // If we don't have an interface then change the module name X to _X
+ if (interface)
+ module = interface;
+ else
+ Insert(module, 0, "_");
+ if ((f_shadow_py = NewFile(filen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(filen);
+ filen = NULL;
+
+ f_shadow = NewString("");
+ f_shadow_begin = NewString("");
+ f_shadow_imports = NewHash();
+ f_shadow_after_begin = NewString("");
+ f_shadow_stubs = NewString("");
+
+ Swig_register_filebyname("shadow", f_shadow);
+ Swig_register_filebyname("python", f_shadow);
+
+ if (!builtin) {
+ /* Import the low-level C/C++ module. This should be a relative import,
+ * since the shadow module may also have been imported by a relative
+ * import, and there is thus no guarantee that the low-level C/C++ module is on
+ * sys.path. Relative imports must be explicitly specified from 2.6.0
+ * onwards (implicit relative imports raised a DeprecationWarning in 2.6,
+ * and fail in 2.7 onwards).
+ *
+ * First check for __package__ which is available from 2.6 onwards, see PEP366.
+ * Next try determine the shadow wrapper's package based on the __name__ it
+ * was given by the importer that loaded it.
+ * If the module is in a package, load the low-level C/C++ module from the
+ * same package, otherwise load it as a global module.
+ */
+ Printv(default_import_code, "# Import the low-level C/C++ module\n", NULL);
+ Printv(default_import_code, "if __package__ or \".\" in __name__:\n", NULL);
+ Printv(default_import_code, tab4, "from . import ", module, "\n", NULL);
+ Printv(default_import_code, "else:\n", NULL);
+ Printv(default_import_code, tab4, "import ", module, "\n", NULL);
+ } else {
+ Printv(default_import_code, "# Pull in all the attributes from the low-level C/C++ module\n", NULL);
+ Printv(default_import_code, "if __package__ or \".\" in __name__:\n", NULL);
+ Printv(default_import_code, tab4, "from .", module, " import *\n", NULL);
+ Printv(default_import_code, "else:\n", NULL);
+ Printv(default_import_code, tab4, "from ", module, " import *\n", NULL);
+ }
+
+ if (!builtin) {
+ /* Need builtins to qualify names like Exception that might also be
+ defined in this module (try both Python 3 and Python 2 names) */
+ Printv(f_shadow, "try:\n", tab4, "import builtins as __builtin__\n", "except ImportError:\n", tab4, "import __builtin__\n", NULL);
+ }
+
+ if (!builtin && fastproxy) {
+ Printf(f_shadow, "\n");
+ Printf(f_shadow, "_swig_new_instance_method = %s.SWIG_PyInstanceMethod_New\n", module);
+ Printf(f_shadow, "_swig_new_static_method = %s.SWIG_PyStaticMethod_New\n", module);
+ }
+
+ if (!builtin) {
+ Printv(f_shadow, "\n",
+ "def _swig_repr(self):\n",
+ tab4, "try:\n",
+ tab4, tab4, "strthis = \"proxy of \" + self.this.__repr__()\n",
+ tab4, "except __builtin__.Exception:\n",
+ tab4, tab4, "strthis = \"\"\n",
+ tab4, "return \"<%s.%s; %s >\" % (self.__class__.__module__, self.__class__.__name__, strthis,)\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "def _swig_setattr_nondynamic_instance_variable(set):\n",
+ tab4, "def set_instance_attr(self, name, value):\n",
+ tab4, tab4, "if name == \"this\":\n",
+ tab4, tab4, tab4, "set(self, name, value)\n",
+ tab4, tab4, "elif name == \"thisown\":\n",
+ tab4, tab4, tab4, "self.this.own(value)\n",
+ tab4, tab4, "elif hasattr(self, name) and isinstance(getattr(type(self), name), property):\n",
+ tab4, tab4, tab4, "set(self, name, value)\n",
+ tab4, tab4, "else:\n",
+ tab4, tab4, tab4, "raise AttributeError(\"You cannot add instance attributes to %s\" % self)\n",
+ tab4, "return set_instance_attr\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "def _swig_setattr_nondynamic_class_variable(set):\n",
+ tab4, "def set_class_attr(cls, name, value):\n",
+ tab4, tab4, "if hasattr(cls, name) and not isinstance(getattr(cls, name), property):\n",
+ tab4, tab4, tab4, "set(cls, name, value)\n",
+ tab4, tab4, "else:\n",
+ tab4, tab4, tab4, "raise AttributeError(\"You cannot add class attributes to %s\" % cls)\n",
+ tab4, "return set_class_attr\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "def _swig_add_metaclass(metaclass):\n",
+ tab4, "\"\"\"Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass\"\"\"\n",
+ tab4, "def wrapper(cls):\n",
+ tab4, tab4, "return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())\n",
+ tab4, "return wrapper\n\n", NIL);
+
+ Printv(f_shadow, "\n",
+ "class _SwigNonDynamicMeta(type):\n",
+ tab4, "\"\"\"Meta class to enforce nondynamic attributes (no new attributes) for a class\"\"\"\n",
+ tab4, "__setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)\n",
+ "\n", NIL);
+
+ Printv(f_shadow, "\n", NIL);
+
+ if (Swig_directors_enabled())
+ Printv(f_shadow, "import weakref\n\n", NIL);
+ }
+ }
+ // Include some information in the code
+ Printf(f_header, "\n/*-----------------------------------------------\n @(target):= %s.so\n\
+ ------------------------------------------------*/\n", module);
+
+ Printf(f_header, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_header, "# define SWIG_init PyInit_%s\n\n", module);
+ Printf(f_header, "#else\n");
+ Printf(f_header, "# define SWIG_init init%s\n\n", module);
+ Printf(f_header, "#endif\n");
+ Printf(f_runtime, "#define SWIG_name \"%s\"\n", module);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n");
+ Append(const_code, "static swig_const_info swig_const_table[] = {\n");
+ Append(methods, "static PyMethodDef SwigMethods[] = {\n");
+ Append(methods_proxydocs, "static PyMethodDef SwigMethods_proxydocs[] = {\n");
+
+ /* the method exported for replacement of new.instancemethod in Python 3 */
+ add_pyinstancemethod_new();
+ add_pystaticmethod_new();
+
+ if (builtin) {
+ SwigType *s = NewString("SwigPyObject");
+ SwigType_add_pointer(s);
+ SwigType_remember(s);
+ Delete(s);
+ }
+
+ /* emit code */
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director_py_mutex.swg", f_runtime);
+ Swig_insert_file("director_guard.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ /* Close language module */
+ Append(methods, "\t { NULL, NULL, 0, NULL }\n");
+ Append(methods, "};\n");
+ Printf(f_wrappers, "%s\n", methods);
+ Append(methods_proxydocs, "\t { NULL, NULL, 0, NULL }\n");
+ Append(methods_proxydocs, "};\n");
+ if ((fastproxy && !builtin) || have_fast_proxy_static_member_method_callback)
+ Printf(f_wrappers, "%s\n", methods_proxydocs);
+
+ if (builtin) {
+ Dump(f_builtins, f_wrappers);
+ }
+
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Append(const_code, "{0, 0, 0, 0.0, 0, 0}};\n");
+ Printf(f_wrappers, "%s\n", const_code);
+
+ if (have_fast_proxy_static_member_method_callback)
+ Printf(f_init, " SWIG_Python_FixMethods(SwigMethods_proxydocs, swig_const_table, swig_types, swig_type_initial);\n\n");
+
+ initialize_threads(f_init);
+
+ Dump(f_varlinks, f_init);
+
+ Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_init, " return m;\n");
+ Printf(f_init, "#else\n");
+ Printf(f_init, " return;\n");
+ Printf(f_init, "#endif\n");
+ Printf(f_init, "}\n");
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ if (shadow) {
+ Swig_banner_target_lang(f_shadow_py, "#");
+
+ if (mod_docstring) {
+ if (Len(mod_docstring)) {
+ const char *triple_double = "\"\"\"";
+ // follow PEP257 rules: https://www.python.org/dev/peps/pep-0257/
+ // reported by pep257: https://github.com/GreenSteam/pep257
+ bool multi_line_ds = Strchr(mod_docstring, '\n') != 0;
+ Printv(f_shadow_py, "\n", triple_double, multi_line_ds ? "\n":"", mod_docstring, multi_line_ds ? "\n":"", triple_double, "\n", NIL);
+ }
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ if (Len(f_shadow_begin) > 0)
+ Printv(f_shadow_py, "\n", f_shadow_begin, "\n", NIL);
+
+ Printv(f_shadow_py, "\nfrom sys import version_info as _swig_python_version_info\n", NULL);
+
+ if (Len(f_shadow_after_begin) > 0)
+ Printv(f_shadow_py, f_shadow_after_begin, "\n", NIL);
+
+ if (moduleimport) {
+ Replaceall(moduleimport, "$module", module);
+ Printv(f_shadow_py, moduleimport, "\n", NIL);
+ } else {
+ Printv(f_shadow_py, default_import_code, NIL);
+ }
+
+ if (Len(f_shadow) > 0)
+ Printv(f_shadow_py, "\n", f_shadow, "\n", NIL);
+ if (Len(f_shadow_stubs) > 0)
+ Printv(f_shadow_py, f_shadow_stubs, "\n", NIL);
+ Delete(f_shadow_py);
+ }
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ if (f_runtime_h != f_begin)
+ Delete(f_runtime_h);
+ Dump(f_directors, f_begin);
+ }
+
+ Dump(f_wrappers, f_begin);
+ if (builtin && builtin_bases_needed)
+ Printf(f_begin, "static PyTypeObject *builtin_bases[%d];\n\n", max_bases + 2);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(default_import_code);
+ Delete(f_shadow_after_begin);
+ Delete(f_shadow_imports);
+ Delete(f_shadow_begin);
+ Delete(f_shadow);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_builtins);
+ Delete(f_init);
+ Delete(f_directors);
+ Delete(f_directors_h);
+ Delete(f_runtime);
+ Delete(f_begin);
+ Delete(f_varlinks);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * Emit the wrapper for PyInstanceMethod_New to MethodDef array.
+ * This wrapper is used to implement -fastproxy,
+ * as a replacement of new.instancemethod in Python 3.
+ * ------------------------------------------------------------ */
+ int add_pyinstancemethod_new() {
+ if (!builtin && fastproxy) {
+ String *name = NewString("SWIG_PyInstanceMethod_New");
+ String *line = NewString("");
+ Printf(line, "\t { \"%s\", %s, METH_O, NULL},\n", name, name);
+ Append(methods, line);
+ Append(methods_proxydocs, line);
+ Delete(line);
+ Delete(name);
+ }
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * Emit the wrapper for PyStaticMethod_New to MethodDef array.
+ * This wrapper is used to ensure the correct documentation is
+ * generated for static methods when using -fastproxy
+ * ------------------------------------------------------------ */
+ int add_pystaticmethod_new() {
+ if (!builtin && fastproxy) {
+ String *name = NewString("SWIG_PyStaticMethod_New");
+ String *line = NewString("");
+ Printf(line, "\t { \"%s\", %s, METH_O, NULL},\n", name, name);
+ Append(methods, line);
+ Append(methods_proxydocs, line);
+ Delete(line);
+ Delete(name);
+ }
+ return 0;
+ }
+
+ /* ------------------------------------------------------------
+ * subpkg_tail()
+ *
+ * Return the name of 'other' package relative to 'base'.
+ *
+ * 1. If 'other' is a sub-package of 'base', returns the 'other' relative to
+ * 'base'.
+ * 2. If 'other' and 'base' are equal, returns empty string "".
+ * 3. In any other case, NULL pointer is returned.
+ *
+ * The 'base' and 'other' are expected to be fully qualified names.
+ *
+ * NOTE: none of 'base' nor 'other' can be null.
+ *
+ * Examples:
+ *
+ * # base other tail
+ * -- ---- ----- ----
+ * 1 "Foo" "Foo.Bar" -> "Bar"
+ * 2 "Foo" "Foo." -> ""
+ * 3 "Foo" "FooB.ar" -> NULL
+ * 4 "Foo.Bar" "Foo.Bar" -> ""
+ * 5 "Foo.Bar" "Foo" -> NULL
+ * 6 "Foo.Bar" "Foo.Gez" -> NULL
+ *
+ * NOTE: the example #2 is actually a syntax error (at input). I believe
+ * swig parser prevents us from this case happening here.
+ * ------------------------------------------------------------ */
+
+ static String *subpkg_tail(const String *base, const String *other) {
+ int baselen = Len(base);
+ int otherlen = Len(other);
+
+ if (Strncmp(other, base, baselen) == 0) {
+ if ((baselen < otherlen) && (Char(other))[baselen] == '.') {
+ return NewString((Char(other)) + baselen + 1);
+ } else if (baselen == otherlen) {
+ return NewString("");
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * abs_import_directive_string()
+ *
+ * Return a string containing python code to import module.
+ *
+ * pkg package name or the module being imported
+ * mod module name of the module being imported
+ * pfx optional prefix to module name
+ *
+ * NOTE: keep this function consistent with abs_import_name_string().
+ * ------------------------------------------------------------ */
+
+ static String *abs_import_directive_string(const String *pkg, const String *mod, const char *pfx = "") {
+ String *out = NewString("");
+
+ if (pkg && *Char(pkg)) {
+ Printf(out, "import %s.%s%s\n", pkg, pfx, mod);
+ } else {
+ Printf(out, "import %s%s\n", pfx, mod);
+ }
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * rel_import_directive_string()
+ *
+ * Return a string containing python code to import module that
+ * is potentially within a package.
+ *
+ * mainpkg package name of the module which imports the other module
+ * pkg package name or the module being imported
+ * mod module name of the module being imported
+ * pfx optional prefix to module name
+ *
+ * NOTE: keep this function consistent with rel_import_name_string().
+ * ------------------------------------------------------------ */
+
+ static String *rel_import_directive_string(const String *mainpkg, const String *pkg, const String *mod, const char *pfx = "") {
+
+ /* NOTE: things are not so trivial. This is what we do here (by examples):
+ *
+ * 0. To import module 'foo', which is not in any package, we do absolute
+ * import:
+ *
+ * import foo
+ *
+ * 1. To import 'pkg1.pkg2.foo', when mainpkg != "pkg1" and
+ * mainpkg != "pkg1.pkg2" or when mainpkg is not given we do absolute
+ * import:
+ *
+ * import pkg1.pkg2.foo
+ *
+ * 2. To import module pkg1.foo, when mainpkg == "pkg1", we do:
+ *
+ * - for py3 = 0:
+ *
+ * import foo
+ *
+ * - for py3 = 1:
+ *
+ * from . import foo
+ *
+ * 3. To import "pkg1.pkg2.pkg3.foo", when mainpkg = "pkg1", we do:
+ *
+ * - for py3 == 0:
+ *
+ * import pkg2.pkg3.foo
+ *
+ * - for py3 == 1:
+ *
+ * from . import pkg2 # [1]
+ * import pkg1.pkg2.pkg3.foo
+ *
+ * NOTE: [1] is necessary for pkg2.foo to be present in the importing module
+ */
+
+ String *apkg = 0; // absolute (FQDN) package name of pkg
+ String *rpkg = 0; // relative package name
+ int py3_rlen1 = 0; // length of 1st level sub-package name, used by py3
+ String *out = NewString("");
+
+ if (pkg && *Char(pkg)) {
+ if (mainpkg) {
+ String *tail = subpkg_tail(mainpkg, pkg);
+ if (tail) {
+ if (*Char(tail)) {
+ rpkg = NewString(tail);
+ const char *py3_end1 = Strchr(rpkg, '.');
+ if (!py3_end1)
+ py3_end1 = (Char(rpkg)) + Len(rpkg);
+ py3_rlen1 = (int)(py3_end1 - Char(rpkg));
+ } else {
+ rpkg = NewString("");
+ }
+ Delete(tail);
+ } else {
+ apkg = NewString(pkg);
+ }
+ } else {
+ apkg = NewString(pkg);
+ }
+ } else {
+ apkg = NewString("");
+ }
+
+ if (apkg) {
+ Printf(out, "import %s%s%s%s\n", apkg, *Char(apkg) ? "." : "", pfx, mod);
+ Delete(apkg);
+ } else {
+ if (py3_rlen1)
+ Printf(out, "from . import %.*s\n", py3_rlen1, rpkg);
+ Printf(out, "from .%s import %s%s\n", rpkg, pfx, mod);
+ Delete(rpkg);
+ }
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * import_directive_string()
+ * ------------------------------------------------------------ */
+
+ static String *import_directive_string(const String *mainpkg, const String *pkg, const String *mod, const char *pfx = "") {
+ if (!relativeimport) {
+ return abs_import_directive_string(pkg, mod, pfx);
+ } else {
+ return rel_import_directive_string(mainpkg, pkg, mod, pfx);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * abs_import_name_string()
+ *
+ * Return a string with the name of a symbol (perhaps imported
+ * from external module by absolute import directive).
+ *
+ * mainpkg package name of current module
+ * mainmod module name of current module
+ * pkg package name of (perhaps other) module
+ * mod module name of (perhaps other) module
+ * sym symbol name
+ *
+ * NOTE: mainmod, mod, and sym can't be NULL.
+ * NOTE: keep this function consistent with abs_import_directive_string()
+ * ------------------------------------------------------------ */
+
+ static String *abs_import_name_string(const String *mainpkg, const String *mainmod, const String *pkg, const String *mod, const String *sym) {
+ String *out = NewString("");
+ if (pkg && *Char(pkg)) {
+ if (mainpkg && *Char(mainpkg)) {
+ if (Strcmp(mainpkg,pkg) != 0 || Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.%s.", pkg, mod);
+ }
+ } else {
+ Printf(out, "%s.%s.", pkg, mod);
+ }
+ } else if ((mainpkg && *Char(mainpkg)) || Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.", mod);
+ }
+ Append(out, sym);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * rel_import_name_string()
+ *
+ * Return a string with the name of a symbol (perhaps imported
+ * from external module by relative import directive).
+ *
+ * mainpkg package name of current module
+ * mainmod module name of current module
+ * pkg package name of (perhaps other) module
+ * mod module name of (perhaps other) module
+ * sym symbol name
+ *
+ * NOTE: mainmod, mod, and sym can't be NULL.
+ * NOTE: keep this function consistent with rel_import_directive_string()
+ * ------------------------------------------------------------ */
+
+ static String *rel_import_name_string(const String *mainpkg, const String *mainmod, const String *pkg, const String *mod, const String *sym) {
+ String *out = NewString("");
+ if (pkg && *Char(pkg)) {
+ String *tail = 0;
+ if (mainpkg)
+ tail = subpkg_tail(mainpkg, pkg);
+ if (!tail)
+ tail = NewString(pkg);
+ if (*Char(tail)) {
+ Printf(out, "%s.%s.", tail, mod);
+ } else if (Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.", mod);
+ }
+ Delete(tail);
+ } else if ((mainpkg && *Char(mainpkg)) || Strcmp(mainmod, mod) != 0) {
+ Printf(out, "%s.", mod);
+ }
+ Append(out, sym);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * import_name_string()
+ * ------------------------------------------------------------ */
+
+ static String *import_name_string(const String *mainpkg, const String *mainmod, const String *pkg, const String *mod, const String *sym) {
+ if (!relativeimport) {
+ return abs_import_name_string(mainpkg,mainmod,pkg,mod,sym);
+ } else {
+ return rel_import_name_string(mainpkg,mainmod,pkg,mod,sym);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ if (shadow) {
+ String *modname = Getattr(n, "module");
+
+ if (modname) {
+ // Find the module node for this imported module. It should be the
+ // first child but search just in case.
+ Node *mod = firstChild(n);
+ while (mod && Strcmp(nodeType(mod), "module") != 0)
+ mod = nextSibling(mod);
+
+ Node *options = Getattr(mod, "options");
+ String *pkg = options ? Getattr(options, "package") : 0;
+
+ if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) {
+ String *_import = import_directive_string(package, pkg, modname, "_");
+ if (!GetFlagAttr(f_shadow_imports, _import)) {
+ String *import = import_directive_string(package, pkg, modname);
+ Printf(builtin ? f_shadow_after_begin : f_shadow, "%s", import);
+ Delete(import);
+ SetFlag(f_shadow_imports, _import);
+ }
+ Delete(_import);
+ }
+
+ }
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ------------------------------------------------------------
+ * funcCall()
+ *
+ * Emit shadow code to call a function in the extension
+ * module. Using proper argument and calling style for
+ * given node n.
+ * ------------------------------------------------------------ */
+ String *funcCall(String *name, String *parms) {
+ String *str = NewString("");
+
+ Printv(str, module, ".", name, "(", parms, ")", NIL);
+ return str;
+ }
+
+ /* ------------------------------------------------------------
+ * indent_pythoncode()
+ *
+ * Format (indent) Python code.
+ * Remove leading whitespace from 'code' and re-indent using
+ * the indentation string in 'indent'.
+ * ------------------------------------------------------------ */
+
+ String *indent_pythoncode(const String *code, const_String_or_char_ptr indent, String *file, int line, const char *directive_name) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+
+ // Line number within the pythoncode.
+ int py_line = 0;
+
+ String *initial = 0;
+ Iterator si;
+
+ /* Get the initial indentation. Skip lines which only contain whitespace
+ * and/or a comment, as the indentation of those doesn't matter:
+ *
+ * A logical line that contains only spaces, tabs, formfeeds and
+ * possibly a comment, is ignored (i.e., no NEWLINE token is
+ * generated).
+ *
+ * see:
+ * https://docs.python.org/2/reference/lexical_analysis.html#blank-lines
+ * https://docs.python.org/3/reference/lexical_analysis.html#blank-lines
+ */
+ for (si = First(clist); si.item; si = Next(si), ++py_line) {
+ const char *c = Char(si.item);
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (ch && ch != '#') {
+ // Found a line with actual content.
+ initial = NewStringWithSize(c, i);
+ break;
+ }
+ if (ch) {
+ Printv(out, indent, c, NIL);
+ }
+ Putc('\n', out);
+ }
+
+ // Process remaining lines.
+ for ( ; si.item; si = Next(si), ++py_line) {
+ const char *c = Char(si.item);
+ // If no prefixed line was found, the above loop should have completed.
+ assert(initial);
+
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (!ch) {
+ // Line is just whitespace - emit an empty line.
+ Putc('\n', out);
+ continue;
+ }
+
+ if (ch == '#') {
+ // Comment - the indentation doesn't matter to python, but try to
+ // adjust the whitespace for the benefit of human readers (though SWIG
+ // currently seems to always remove any whitespace before a '#' before
+ // we get here, in which case we'll just leave the comment at the start
+ // of the line).
+ if (i >= Len(initial)) {
+ Printv(out, indent, NIL);
+ }
+
+ Printv(out, c + i, "\n", NIL);
+ continue;
+ }
+
+ if (i < Len(initial)) {
+ // There's non-whitespace in the initial prefix of this line.
+ Swig_error(file, line, "Line indented less than expected (line %d of %s) as no line should be indented less than the indentation in line 1\n", py_line, directive_name);
+ Printv(out, indent, c, "\n", NIL);
+ } else {
+ if (memcmp(c, Char(initial), Len(initial)) == 0) {
+ // Prefix matches initial, so just remove it.
+ Printv(out, indent, c + Len(initial), "\n", NIL);
+ continue;
+ }
+ Swig_warning(WARN_PYTHON_INDENT_MISMATCH,
+ file, line, "Whitespace indentation is inconsistent compared to earlier lines (line %d of %s)\n", py_line, directive_name);
+ // To avoid gratuitously breaking interface files which worked with
+ // SWIG <= 3.0.5, we remove a prefix of the same number of bytes for
+ // lines which start with different whitespace to the line we got
+ // 'initial' from.
+ Printv(out, indent, c + Len(initial), "\n", NIL);
+ }
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * indent_docstring()
+ *
+ * Format (indent) a Python docstring.
+ * Remove leading whitespace from 'code' and re-indent using
+ * the indentation string in 'indent'.
+ * ------------------------------------------------------------ */
+
+ String *indent_docstring(const String *code, const char *indent) {
+ String *out = NewString("");
+ String *temp;
+ char *t;
+ if (!indent)
+ indent = "";
+
+ temp = NewString(code);
+
+ t = Char(temp);
+ if (*t == '{') {
+ Delitem(temp, 0);
+ Delitem(temp, DOH_END);
+ }
+
+ /* Split the input text into lines */
+ List *clist = SplitLines(temp);
+ Delete(temp);
+
+ Iterator si;
+
+ int truncate_characters_count = INT_MAX;
+ for (si = First(clist); si.item; si = Next(si)) {
+ const char *c = Char(si.item);
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (ch) {
+ // Found a line which isn't just whitespace
+ if (i < truncate_characters_count)
+ truncate_characters_count = i;
+ }
+ }
+
+ if (truncate_characters_count == INT_MAX)
+ truncate_characters_count = 0;
+
+ for (si = First(clist); si.item; si = Next(si)) {
+ const char *c = Char(si.item);
+
+ int i;
+ for (i = 0; isspace((unsigned char)c[i]); i++) {
+ // Scan forward until we find a non-space (which may be a null byte).
+ }
+ char ch = c[i];
+ if (!ch) {
+ // Line is just whitespace - emit an empty line.
+ Putc('\n', out);
+ continue;
+ }
+
+ Printv(out, indent, c + truncate_characters_count, "\n", NIL);
+ }
+ Delete(clist);
+ return out;
+ }
+
+ /* ------------------------------------------------------------
+ * autodoc level declarations
+ * ------------------------------------------------------------ */
+
+ enum autodoc_l {
+ NO_AUTODOC = -2, // no autodoc
+ STRING_AUTODOC = -1, // use provided string
+ NAMES_AUTODOC = 0, // only parameter names
+ TYPES_AUTODOC = 1, // parameter names and types
+ EXTEND_AUTODOC = 2, // extended documentation and parameter names
+ EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names
+ };
+
+
+ autodoc_l autodoc_level(String *autodoc) {
+ autodoc_l dlevel = NO_AUTODOC;
+ char *c = Char(autodoc);
+ if (c) {
+ if (isdigit(c[0])) {
+ dlevel = (autodoc_l) atoi(c);
+ } else {
+ if (strcmp(c, "extended") == 0) {
+ dlevel = EXTEND_AUTODOC;
+ } else {
+ dlevel = STRING_AUTODOC;
+ }
+ }
+ }
+ return dlevel;
+ }
+
+
+ /* ------------------------------------------------------------
+ * have_docstring()
+ *
+ * Check if there is a docstring directive and it has text,
+ * or there is an autodoc flag set
+ * ------------------------------------------------------------ */
+
+ bool have_docstring(Node *n) {
+ String *str = Getattr(n, "feature:docstring");
+ return ((str && Len(str) > 0)
+ || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"))
+ || (doxygen && doxygenTranslator->hasDocumentation(n))
+ );
+ }
+
+ /* ------------------------------------------------------------
+ * find_overload_with_docstring()
+ *
+ * This function should be called with the node pointing to the
+ * last element of an overload set and returns an overload with
+ * a docstring or null if there are none.
+ *
+ * The idea is that, because the Python docstring is shared by
+ * all overloads, it's this function return value and not the
+ * node itself which needs to be passes to docstring() later.
+ * ------------------------------------------------------------ */
+ Node *find_overload_with_docstring(Node *n) {
+ for (Node *node_with_doc = n; node_with_doc; node_with_doc = Getattr(node_with_doc, "sym:previousSibling")) {
+ if (have_docstring(node_with_doc))
+ return node_with_doc;
+ }
+
+ return NULL;
+ }
+
+ /* ------------------------------------------------------------
+ * build_combined_docstring()
+ *
+ * Build the full docstring:
+ * Use the docstring if there is one present otherwise
+ * use the Doxygen comment if there is one present.
+ * Ignore autodoc if there is a Doxygen comment, otherwise
+ * create the autodoc string and append to any docstring.
+ *
+ * Return new string to be deleted by caller (never NIL but
+ * may be empty if there is no docstring).
+ * ------------------------------------------------------------ */
+
+ String *build_combined_docstring(Node *n, autodoc_t ad_type, const char *indent = "", bool low_level = false) {
+ bool add_autodoc = true;
+ String *docstr = Getattr(n, "feature:docstring");
+ if (docstr) {
+ // Simplify the code below by just ignoring empty docstrings.
+ if (!Len(docstr))
+ docstr = NULL;
+ else
+ docstr = Copy(docstr);
+ }
+
+ if (docstr) {
+ char *t = Char(docstr);
+ if (*t == '{') {
+ Delitem(docstr, 0);
+ Delitem(docstr, DOH_END);
+ }
+ }
+
+ if (!docstr) {
+ if (doxygen && doxygenTranslator->hasDocumentation(n)) {
+ docstr = Getattr(n, "python:docstring");
+ if (!docstr) {
+ docstr = doxygenTranslator->getDocumentation(n, 0);
+
+ // Avoid rebuilding it again the next time: notice that we can't do
+ // this for the combined doc string as autodoc part of it depends on
+ // the sym:name of the node and it is changed while handling it, so
+ // the cached results become incorrect. But Doxygen docstring only
+ // depends on the comment which is not going to change, so we can
+ // safely cache it.
+ Setattr(n, "python:docstring", Copy(docstr));
+ } else {
+ // Must copy here since if the docstring is multi-line, the String*
+ // here will get Deleted below, which is bad if it is a pointer to
+ // the cached object!
+ docstr = Copy(docstr);
+ }
+ add_autodoc = false;
+ }
+ }
+
+ if (add_autodoc && Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc")) {
+ String *autodoc = make_autodoc(n, ad_type, low_level);
+ if (autodoc && Len(autodoc) > 0) {
+ if (docstr) {
+ Append(autodoc, "\n");
+ Append(autodoc, docstr);
+ }
+
+ String *tmp = autodoc;
+ autodoc = docstr;
+ docstr = tmp;
+ }
+
+ Delete(autodoc);
+ }
+
+ if (!docstr)
+ docstr = NewString("");
+
+ // If there is more than one line then make docstrings like this:
+ //
+ // """
+ // This is line1
+ // And here is line2 followed by the rest of them
+ // """
+ //
+ // otherwise, put it all on a single line
+ if (Strchr(docstr, '\n')) {
+ String *tmp = NewString("");
+ Append(tmp, "\n");
+ Append(tmp, indent_docstring(docstr, indent));
+ Append(tmp, indent);
+ Delete(docstr);
+ docstr = tmp;
+ } else {
+ // Removing leading and trailing whitespace for single line docstrings
+ Chop(docstr);
+ const char *c = Char(docstr);
+ if (isspace((int)*c)) {
+ while(isspace((int)*(++c))) {
+ }
+ String *old_docstr = docstr;
+ docstr = NewString(c);
+ Delete(old_docstr);
+ }
+ }
+
+ return docstr;
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ *
+ * Get the docstring text, stripping off {} if necessary,
+ * and enclose in triple double quotes. If autodoc is also
+ * set then it will build a combined docstring.
+ * ------------------------------------------------------------ */
+
+ String *docstring(Node *n, autodoc_t ad_type, const char *indent, bool low_level = false) {
+ String *docstr = build_combined_docstring(n, ad_type, indent, low_level);
+ const int len = Len(docstr);
+ if (!len)
+ return docstr;
+
+ // Notice that all comments are created as raw strings (prefix "r"),
+ // because '\' is used often in comments, but may break Python module from
+ // loading. For example, in doxy comment one may write path in quotes:
+ //
+ // This is path to file "C:\x\file.txt"
+ //
+ // Python will not load the module with such comment because of illegal
+ // escape '\x'. '\' may additionally appear in verbatim or htmlonly sections
+ // of doxygen doc, Latex expressions, ...
+ String *doc = NewString("");
+
+ // Determine which kind of quotes to use as delimiters: for single line
+ // strings we can avoid problems with having a quote as the last character
+ // of the docstring by using different kind of quotes as delimiters. For
+ // multi-line strings this problem doesn't arise, as we always have a new
+ // line or spaces at the end of it, but it still does no harm to do it for
+ // them too.
+ //
+ // Note: we use double quotes by default, i.e. if there is no reason to
+ // prefer using single ones, for consistency with the older SWIG versions.
+ const bool useSingleQuotes = (Char(docstr))[len - 1] == '"';
+
+ Append(doc, useSingleQuotes ? "r'''" : "r\"\"\"");
+
+ // We also need to avoid having triple quotes of whichever type we use, as
+ // this would break Python doc string syntax too. Unfortunately there is no
+ // way to have triple quotes inside of raw-triple-quoted string, so we have
+ // to break the string in parts and rely on concatenation of the adjacent
+ // string literals.
+ if (useSingleQuotes)
+ Replaceall(docstr, "'''", "''' \"'''\" '''");
+ else
+ Replaceall(docstr, "\"\"\"", "\"\"\" '\"\"\"' \"\"\"");
+
+ Append(doc, docstr);
+ Append(doc, useSingleQuotes ? "'''" : "\"\"\"");
+ Delete(docstr);
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * cdocstring()
+ *
+ * Get the docstring text as it would appear in C-language
+ * source code (but without quotes around it).
+ * ------------------------------------------------------------ */
+
+ String *cdocstring(Node *n, autodoc_t ad_type, bool low_level = false) {
+ String *ds = build_combined_docstring(n, ad_type, "", low_level);
+ Replaceall(ds, "\\", "\\\\");
+ Replaceall(ds, "\"", "\\\"");
+ Replaceall(ds, "\n", "\\n\"\n\t\t\"");
+ return ds;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addMissingParameterNames()
+ *
+ * For functions that have not had nameless parameters set in the Language class.
+ *
+ * Inputs:
+ * plist - entire parameter list
+ * arg_num - the number to start from when naming arguments
+ * Side effects:
+ * The "lname" attribute in each parameter in plist will be contain a parameter name
+ * ----------------------------------------------------------------------------- */
+
+ void addMissingParameterNames(Node *n, ParmList *plist, int arg_num) {
+ Parm *p = plist;
+ int i = arg_num;
+ while (p) {
+ if (!Getattr(p, "lname")) {
+ String *name = makeParameterName(n, p, i);
+ Setattr(p, "lname", name);
+ Delete(name);
+ }
+ i++;
+ p = nextSibling(p);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodocParmList()
+ *
+ * Generate the documentation for the function parameters
+ * Parameters:
+ * arg_num: The number to start assigning unnamed arguments from
+ * func_annotation: Function annotation support
+ * ------------------------------------------------------------ */
+
+ String *make_autodocParmList(Node *n, bool showTypes, int arg_num = 1, bool calling = false, bool func_annotation = false) {
+
+ String *doc = NewString("");
+ String *pdocs = 0;
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+
+ if (calling)
+ func_annotation = false;
+
+ addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ if (Strcmp(ParmList_protostr(plist), "void") == 0) {
+ //No parameters actually
+ return doc;
+ }
+
+ for (p = plist; p; p = pnext) {
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *pdoc = Getattr(p, "tmap:doc");
+ if (pdoc) {
+ name = Getattr(p, "tmap:doc:name");
+ type = Getattr(p, "tmap:doc:type");
+ value = Getattr(p, "tmap:doc:value");
+ }
+
+ // Skip the "self" argument - it is added to the parameter list automatically
+ // and shouldn't be included in the Parameters block
+ if (Getattr(p, "self")) {
+ continue;
+ }
+
+ // Note: the generated name should be consistent with that in kwnames[]
+ String *made_name = 0;
+ if (!name) {
+ name = made_name = makeParameterName(n, p, arg_num);
+ }
+
+ // Increment the argument number once we are sure this is a real argument to count
+ arg_num++;
+
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ if (SwigType_isvarargs(type)) {
+ Delete(made_name);
+ break;
+ }
+
+ if (Len(doc)) {
+ // add a comma to the previous one if any
+ Append(doc, ", ");
+ }
+
+ // Do the param type too?
+ Node *nn = classLookup(Getattr(p, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ if (showTypes)
+ Printf(doc, "%s ", type_str);
+
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ // numpydoc style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+ pdocs = NewString("\nParameters\n----------\n");
+ Printf(pdocs, "%s\n", pdoc);
+ }
+ // Write the function annotation
+ if (func_annotation)
+ Printf(doc, ": \"%s\"", type_str);
+
+ // Write default value
+ if (value && !calling) {
+ String *new_value = convertValue(value, Getattr(p, "numval"), Getattr(p, "stringval"), Getattr(p, "type"));
+ if (new_value) {
+ value = new_value;
+ } else {
+ // Even if the value is not representable in the target language, still use it in the documentation, for compatibility with the previous SWIG versions
+ // and because it can still be useful to see the C++ expression there.
+ Node *lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(doc, "=%s", value);
+
+ if (new_value)
+ Delete(new_value);
+ }
+ Delete(type_str);
+ Delete(made_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodoc()
+ *
+ * Build a docstring for the node, using parameter and other
+ * info in the parse tree. If the value of the autodoc
+ * attribute is "0" then do not include parameter types, if
+ * it is "1" (the default) then do. If it has some other
+ * value then assume it is supplied by the extension writer
+ * and use it directly.
+ * ------------------------------------------------------------ */
+
+ String *make_autodoc(Node *n, autodoc_t ad_type, bool low_level = false) {
+ int extended = 0;
+ bool first_func = true;
+ // If the function is overloaded then this function is called
+ // for the last one. Rewind to the first so the docstrings are
+ // in order.
+ while (Getattr(n, "sym:previousSibling"))
+ n = Getattr(n, "sym:previousSibling");
+
+ String *doc = NewString("");
+ while (n) {
+ bool showTypes = false;
+ bool skipAuto = false;
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+ switch (dlevel) {
+ case NO_AUTODOC:
+ break;
+ case NAMES_AUTODOC:
+ showTypes = false;
+ break;
+ case TYPES_AUTODOC:
+ showTypes = true;
+ break;
+ case EXTEND_AUTODOC:
+ extended = 1;
+ showTypes = false;
+ break;
+ case EXTEND_TYPES_AUTODOC:
+ extended = 1;
+ showTypes = true;
+ break;
+ case STRING_AUTODOC:
+ Append(doc, autodoc);
+ skipAuto = true;
+ break;
+ }
+
+ if (!skipAuto) {
+ /* Check if a documentation name was given for either the low-level C API or high-level Python shadow API */
+ String *symname = Getattr(n, low_level ? "doc:low:name" : "doc:high:name");
+ if (!symname) {
+ symname = Getattr(n, "sym:name");
+ }
+
+ SwigType *type = Getattr(n, "type");
+ String *type_str = NULL;
+
+ // If the function has default arguments, then that documentation covers this version too
+ if (Getattr(n, "defaultargs") != NULL) {
+ n = Getattr(n, "sym:nextSibling");
+ continue;
+ }
+
+ if (!first_func)
+ Append(doc, "\n");
+
+ if (type) {
+ if (Strcmp(type, "void") == 0) {
+ type_str = NULL;
+ } else {
+ Node *nn = classLookup(type);
+ type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ }
+ }
+
+ /* Treat the low-level C API functions for getting/setting variables as methods for documentation purposes */
+ String *kind = Getattr(n, "kind");
+ if (kind && Strcmp(kind, "variable") == 0) {
+ if (ad_type == AUTODOC_FUNC) {
+ ad_type = AUTODOC_METHOD;
+ }
+ }
+ /* Treat destructors as methods for documentation purposes */
+ String *nodeType = Getattr(n, "nodeType");
+ if (nodeType && Strcmp(nodeType, "destructor") == 0) {
+ if (ad_type == AUTODOC_FUNC) {
+ ad_type = AUTODOC_METHOD;
+ }
+ }
+
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ {
+ // Only do the autodoc if there isn't a docstring for the class
+ String *str = Getattr(n, "feature:docstring");
+ if (!str || Len(str) == 0) {
+ if (builtin) {
+ SwigType *name = Getattr(n, "name");
+ SwigType *sname = add_explicit_scope(name);
+ String *rname = SwigType_namestr(sname);
+ Printf(doc, "%s", rname);
+ Delete(sname);
+ Delete(rname);
+ } else {
+ String *classname_str = SwigType_namestr(real_classname);
+ if (CPlusPlus) {
+ Printf(doc, "Proxy of C++ %s class.", classname_str);
+ } else {
+ Printf(doc, "Proxy of C %s struct.", classname_str);
+ }
+ Delete(classname_str);
+ }
+ }
+ }
+ break;
+ case AUTODOC_CTOR:
+ if (Strcmp(class_name, symname) == 0) {
+ String *paramList = make_autodocParmList(n, showTypes, 2);
+ Printf(doc, "__init__(");
+ if (showTypes)
+ Printf(doc, "%s ", class_name);
+ if (Len(paramList))
+ Printf(doc, "self, %s) -> %s", paramList, class_name);
+ else
+ Printf(doc, "self) -> %s", class_name);
+ } else
+ Printf(doc, "%s(%s) -> %s", symname, make_autodocParmList(n, showTypes), class_name);
+ break;
+
+ case AUTODOC_DTOR:
+ if (showTypes)
+ Printf(doc, "__del__(%s self)", class_name);
+ else
+ Printf(doc, "__del__(self)");
+ break;
+
+ case AUTODOC_STATICFUNC:
+ Printf(doc, "%s(%s)", symname, make_autodocParmList(n, showTypes));
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+
+ case AUTODOC_FUNC:
+ Printf(doc, "%s(%s)", symname, make_autodocParmList(n, showTypes));
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+
+ case AUTODOC_METHOD:
+ {
+ String *paramList = make_autodocParmList(n, showTypes, 2);
+ Printf(doc, "%s(", symname);
+ if (showTypes)
+ Printf(doc, "%s ", class_name);
+ if (Len(paramList))
+ Printf(doc, "self, %s)", paramList);
+ else
+ Printf(doc, "self)");
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ }
+ break;
+
+ case AUTODOC_CONST:
+ // There is no autodoc support for constants currently, this enum
+ // element only exists to allow calling docstring() with it.
+ return NULL;
+ case AUTODOC_VAR:
+ // Variables can also be documented (e.g. through the property() function in python)
+ Printf(doc, "%s", symname);
+ if (showTypes) {
+ String *type = Getattr(n, "tmap:doc:type");
+ if (!type)
+ type = Getattr(n, "membervariableHandler:type");
+ if (!type)
+ type = Getattr(n, "type");
+ Printf(doc, " : %s", type);
+ }
+ break;
+ }
+ Delete(type_str);
+
+ // Special case: wrapper functions to get a variable should have no parameters.
+ // Because the node is re-used for the setter and getter, the feature:pdocs field will
+ // exist for the getter function, so explicitly avoid printing parameters in this case.
+ bool variable_getter = kind && Strcmp(kind, "variable") == 0 && Getattr(n, "memberget");
+ if (extended && ad_type != AUTODOC_VAR && !variable_getter) {
+ String *pdocs = Getattr(n, "feature:pdocs");
+ if (pdocs) {
+ Printv(doc, "\n", pdocs, NULL);
+ }
+ }
+ }
+ // if it's overloaded then get the next decl and loop around again
+ n = Getattr(n, "sym:nextSibling");
+ if (n)
+ first_func = false;
+ }
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * convertIntegerValue()
+ *
+ * Check if string v is an integer and can be represented in
+ * Python. If so, return an appropriate Python representation,
+ * otherwise (or if we are unsure), return NIL.
+ * ------------------------------------------------------------ */
+ String *convertIntegerValue(String *v, SwigType *resolved_type) {
+ const char *const s = Char(v);
+ char *end;
+
+ // Check if this is an integer number in any base.
+ errno = 0;
+ long value = strtol(s, &end, 0);
+ if (errno == ERANGE || end == s || *end != '\0') {
+ return NIL;
+ }
+ // So now we are certain that we are indeed dealing with an integer
+ // that has a representation as long given by value.
+
+ // Restrict to guaranteed supported range in Python, see maxint docs: https://docs.python.org/2/library/sys.html#sys.maxint
+ // Don't do this pointless check when long is 32 bits or smaller as strtol will have already failed with ERANGE
+#if LONG_MAX > PYTHON_INT_MAX || LONG_MIN < PYTHON_INT_MIN
+ if (value > PYTHON_INT_MAX || value < PYTHON_INT_MIN) {
+ return NIL;
+ }
+#endif
+
+ if (Equal(resolved_type, "bool"))
+ // Allow integers as the default value for a bool parameter.
+ return NewString(value ? "True" : "False");
+
+ if (value == 0)
+ return NewString(SwigType_ispointer(resolved_type) ? "None" : "0");
+
+ return Copy(v);
+ }
+
+ /* ------------------------------------------------------------
+ * convertDoubleValue()
+ *
+ * Check if the given string looks like a decimal floating point constant
+ * and return it if it does, otherwise return NIL.
+ * ------------------------------------------------------------ */
+ String *convertDoubleValue(String *v) {
+ const char *const s = Char(v);
+ char *end;
+
+ errno = 0;
+ double value = strtod(s, &end);
+ (void) value;
+ if (errno != ERANGE && end != s) {
+ // An added complication: at least some versions of strtod() recognize
+ // hexadecimal floating point numbers which don't exist in Python, so
+ // detect them ourselves and refuse to convert them (this can't be done
+ // without loss of precision in general).
+ //
+ // Also don't accept neither "NAN" nor "INFINITY" (both of which
+ // conveniently contain "n").
+ if (strpbrk(s, "xXnN"))
+ return NIL;
+
+ // Disregard optional "f" suffix, it can be just dropped in Python as it
+ // uses doubles for everything anyhow.
+ for (char * p = end; *p != '\0'; ++p) {
+ switch (*p) {
+ case 'f':
+ case 'F':
+ break;
+
+ default:
+ return NIL;
+ }
+ }
+
+ // Avoid unnecessary string allocation in the common case when we don't
+ // need to remove any suffix.
+ return *end == '\0' ? Copy(v) : NewStringWithSize(s, (int)(end - s));
+ }
+
+ return NIL;
+ }
+
+ /* ------------------------------------------------------------
+ * convertValue()
+ *
+ * Check if string v can be a Python value literal or a
+ * constant. Return an equivalent Python representation,
+ * or NIL if it isn't, or we are unsure.
+ * ------------------------------------------------------------ */
+ String *convertValue(String *v, String *numval, String *stringval, SwigType *type) {
+ if (stringval) {
+ return NIL;
+ // FIXME: This needs more careful testing.
+ // return NewStringf("'%(escape)s'", stringval);
+ }
+ SwigType *resolved_type = SwigType_typedef_resolve_all(type);
+ SwigType *unqualified_type = SwigType_strip_qualifiers(resolved_type);
+ if (numval) {
+ if (Equal(unqualified_type, "bool")) {
+ Delete(resolved_type);
+ Delete(unqualified_type);
+ return NewString(*Char(numval) == '0' ? "False" : "True");
+ }
+ String *result = convertIntegerValue(numval, unqualified_type);
+ Delete(resolved_type);
+ Delete(unqualified_type);
+ return result;
+ }
+
+ String *result = convertDoubleValue(v);
+ if (!result) {
+ if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
+ result = SwigType_ispointer(unqualified_type) ? NewString("None") : NewString("0");
+ // This could also be an enum type, default value of which could be
+ // representable in Python if it doesn't include any scope (which could,
+ // but currently is not, translated).
+ else if (!Strchr(v, ':')) {
+ Node *lookup = Swig_symbol_clookup(v, 0);
+ if (lookup) {
+ if (Cmp(Getattr(lookup, "nodeType"), "enumitem") == 0)
+ result = Copy(Getattr(lookup, "sym:name"));
+ }
+ }
+ }
+
+ Delete(resolved_type);
+ Delete(unqualified_type);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * is_representable_as_pyargs()
+ *
+ * Check if the function parameters default argument values
+ * can be represented in Python.
+ *
+ * If this method returns false, the parameters will be translated
+ * to a generic "*args" which allows us to deal with default values
+ * at C++ code level where they can always be handled.
+ * ------------------------------------------------------------ */
+ bool is_representable_as_pyargs(Node *n) {
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Swig_typemap_attach_parms("default", plist, NULL);
+
+ Parm *p;
+ Parm *pnext;
+
+ for (p = plist; p; p = pnext) {
+ pnext = nextSibling(p);
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ Parm *in_next = Getattr(p, "tmap:in:next");
+ if (in_next)
+ pnext = in_next;
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ }
+
+ // "default" typemap can contain arbitrary C++ code, so while it could, in
+ // principle, be possible to examine it and check if it's just something
+ // simple of the form "$1 = expression" and then use convertValue() to
+ // check if expression can be used in Python, but for now we just
+ // pessimistically give up and prefer to handle this at C++ level only.
+ if (Getattr(p, "tmap:default"))
+ return false;
+
+ String *value = Getattr(p, "value");
+ if (value) {
+ String *convertedValue = convertValue(value, Getattr(p, "numval"), Getattr(p, "stringval"), Getattr(p, "type"));
+ if (!convertedValue)
+ return false;
+ Delete(convertedValue);
+ }
+ }
+
+ return true;
+ }
+
+
+ /* ------------------------------------------------------------
+ * is_real_overloaded()
+ *
+ * Check if the function is overloaded, but not just have some
+ * siblings generated due to the original function having
+ * default arguments.
+ * ------------------------------------------------------------ */
+ bool is_real_overloaded(Node *n) {
+ Node *h = Getattr(n, "sym:overloaded");
+ Node *i;
+ if (!h)
+ return false;
+
+ i = Getattr(h, "sym:nextSibling");
+ while (i) {
+ Node *nn = Getattr(i, "defaultargs");
+ if (nn != h) {
+ /* Check if overloaded function has defaultargs and
+ * pointed to the first overloaded. */
+ return true;
+ }
+ i = Getattr(i, "sym:nextSibling");
+ }
+
+ return false;
+ }
+
+ /* ------------------------------------------------------------
+ * make_pyParmList()
+ *
+ * Generate parameter list for Python functions or methods,
+ * reuse make_autodocParmList() to do so.
+ * ------------------------------------------------------------ */
+ String *make_pyParmList(Node *n, bool in_class, bool is_calling, int kw, bool has_self_for_count = false) {
+ /* Get the original function for a defaultargs copy,
+ * see default_arguments() in parser.y. */
+ Node *nn = Getattr(n, "defaultargs");
+ if (nn)
+ n = nn;
+
+ Parm *parms = Getattr(n, "parms");
+ int varargs = parms ? emit_isvarargs(parms) : 0;
+
+ /* We prefer to explicitly list all parameters of the C function in the
+ generated Python code as this makes the function more convenient to use,
+ however in some cases we must replace the real parameters list with just
+ the catch all "*args". This happens when:
+
+ 1. The function is overloaded as Python doesn't support this.
+ 2. We were explicitly asked to use the "compact" arguments form.
+ 3. We were explicitly asked to use default args from C via the "python:cdefaultargs" feature.
+ 4. One of the default argument values can't be represented in Python.
+ 5. Varargs that haven't been forced to use a fixed number of arguments with %varargs.
+ */
+ if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || GetFlag(n, "feature:python:cdefaultargs") || !is_representable_as_pyargs(n) || varargs) {
+ String *parms = NewString("");
+ if (in_class)
+ Printf(parms, "self, ");
+ Printf(parms, "*args");
+ if (kw)
+ Printf(parms, ", **kwargs");
+ return parms;
+ }
+
+ bool funcanno = Equal(Getattr(n, "feature:python:annotations"), "c") ? true : false;
+ String *params = NewString("");
+ String *_params = make_autodocParmList(n, false, ((in_class || has_self_for_count)? 2 : 1), is_calling, funcanno);
+
+ if (in_class) {
+ Printf(params, "self");
+ if (Len(_params) > 0)
+ Printf(params, ", ");
+ }
+
+ Printv(params, _params, NULL);
+
+ return params;
+ }
+
+ /* ------------------------------------------------------------
+ * have_pythonprepend()
+ *
+ * Check if there is a %pythonprepend directive and it has text
+ * ------------------------------------------------------------ */
+
+ bool have_pythonprepend(Node *n) {
+ String *str = Getattr(n, "feature:pythonprepend");
+ return (str && Len(str) > 0);
+ }
+
+ /* ------------------------------------------------------------
+ * pythonprepend()
+ *
+ * Get the %pythonprepend code, stripping off {} if necessary
+ * ------------------------------------------------------------ */
+
+ String *pythonprepend(Node *n) {
+ String *str = Getattr(n, "feature:pythonprepend");
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+ return str;
+ }
+
+ /* ------------------------------------------------------------
+ * have_pythonappend()
+ *
+ * Check if there is a %pythonappend directive and it has text
+ * ------------------------------------------------------------ */
+
+ bool have_pythonappend(Node *n) {
+ String *str = Getattr(n, "feature:pythonappend");
+ if (!str)
+ str = Getattr(n, "feature:addtofunc");
+ return (str && Len(str) > 0);
+ }
+
+ /* ------------------------------------------------------------
+ * pythonappend()
+ *
+ * Get the %pythonappend code, stripping off {} if necessary
+ * ------------------------------------------------------------ */
+
+ String *pythonappend(Node *n) {
+ String *str = Getattr(n, "feature:pythonappend");
+ if (!str)
+ str = Getattr(n, "feature:addtofunc");
+
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+ return str;
+ }
+
+ /* ------------------------------------------------------------
+ * have_addtofunc()
+ *
+ * Check if there is a %addtofunc directive and it has text
+ * ------------------------------------------------------------ */
+
+ bool have_addtofunc(Node *n) {
+ return have_pythonappend(n) || have_pythonprepend(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * returnTypeAnnotation()
+ *
+ * Helper function for constructing the function annotation
+ * of the returning type, return a empty string for Python 2.x
+ * ------------------------------------------------------------ */
+ String *returnTypeAnnotation(Node *n) {
+ String *ret = 0;
+ Parm *p = Getattr(n, "parms");
+ String *tm;
+ /* Try to guess the returning type by argout typemap,
+ * however the result may not accurate. */
+ while (p) {
+ if ((tm = Getattr(p, "tmap:argout:match_type"))) {
+ tm = SwigType_str(tm, 0);
+ if (ret)
+ Printv(ret, ", ", tm, NULL);
+ else
+ ret = tm;
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ /* If no argout typemap, then get the returning type from
+ * the function prototype. */
+ if (!ret) {
+ ret = Getattr(n, "type");
+ if (ret)
+ ret = SwigType_str(ret, 0);
+ }
+ bool funcanno = Equal(Getattr(n, "feature:python:annotations"), "c") ? true : false;
+ return (ret && funcanno) ? NewStringf(" -> \"%s\"", ret) : NewString("");
+ }
+
+ /* ------------------------------------------------------------
+ * variableAnnotation()
+ *
+ * Helper function for constructing a variable annotation
+ * ------------------------------------------------------------ */
+
+ String *variableAnnotation(Node *n) {
+ String *type = Getattr(n, "type");
+ if (type)
+ type = SwigType_str(type, 0);
+ bool anno = Equal(Getattr(n, "feature:python:annotations"), "c") ? true : false;
+ anno = GetFlag(n, "feature:python:annotations:novar") ? false : anno;
+ String *annotation = (type && anno) ? NewStringf(": \"%s\"", type) : NewString("");
+ Delete(type);
+ return annotation;
+ }
+
+ /* ------------------------------------------------------------
+ * emitFunctionShadowHelper()
+ *
+ * Refactoring some common code out of functionWrapper and
+ * dispatchFunction that writes the proxy code for non-member
+ * functions.
+ * ------------------------------------------------------------ */
+
+ void emitFunctionShadowHelper(Node *n, File *f_dest, String *name, int kw) {
+ String *parms = make_pyParmList(n, false, false, kw);
+ String *callParms = make_pyParmList(n, false, true, kw);
+
+ // Callbacks need the C function in order to extract the pointer from the swig_ptr: string
+ bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback");
+
+ if (!fast || olddefs) {
+ /* Make a wrapper function to insert the code into */
+ Printv(f_dest, "\n", "def ", name, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+
+ // When handling the last overloaded function in an overload set (and we're only called for the last one if the function is overloaded at all), we need to
+ // output the docstring if any of the overloads has any documentation, not just this last one.
+ if (Node *node_with_doc = find_overload_with_docstring(n))
+ Printv(f_dest, tab4, docstring(node_with_doc, AUTODOC_FUNC, tab4, true), "\n", NIL);
+
+ if (have_pythonprepend(n))
+ Printv(f_dest, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_dest, tab4 "val = ", funcCall(name, callParms), "\n", NIL);
+ Printv(f_dest, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_dest, tab4 "return val\n", NIL);
+ } else {
+ Printv(f_dest, tab4 "return ", funcCall(name, callParms), "\n", NIL);
+ }
+ }
+
+ // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first.
+ if (fast) {
+ /* If there is no addtofunc directive then just assign from the extension module (for speed up) */
+ Printv(f_dest, name, " = ", module, ".", name, "\n", NIL);
+ }
+ }
+
+
+ /* ------------------------------------------------------------
+ * check_kwargs()
+ *
+ * check if using kwargs is allowed for this Node
+ * ------------------------------------------------------------ */
+
+ int check_kwargs(Node *n) const {
+ return (use_kw || GetFlag(n, "feature:kwargs"))
+ && !GetFlag(n, "memberset") && !GetFlag(n, "memberget");
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * add_method()
+ * ------------------------------------------------------------ */
+
+ void add_method(String *name, String *function, int kw, Node *n = 0, int funpack = 0, int num_required = -1, int num_arguments = -1) {
+ String * meth_str = NewString("");
+ if (!kw) {
+ if (funpack) {
+ if (num_required == 0 && num_arguments == 0) {
+ Printf(meth_str, "\t { \"%s\", %s, METH_NOARGS, ", name, function);
+ } else if (num_required == 1 && num_arguments == 1) {
+ Printf(meth_str, "\t { \"%s\", %s, METH_O, ", name, function);
+ } else {
+ Printf(meth_str, "\t { \"%s\", %s, METH_VARARGS, ", name, function);
+ }
+ } else {
+ Printf(meth_str, "\t { \"%s\", %s, METH_VARARGS, ", name, function);
+ }
+ } else {
+ // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning.
+ // Python should always call the function correctly, but the Python C API
+ // requires us to store it in function pointer of a different type.
+ Printf(meth_str, "\t { \"%s\", (PyCFunction)(void(*)(void))%s, METH_VARARGS|METH_KEYWORDS, ", name, function);
+ }
+ Append(methods, meth_str);
+ if (fastproxy) {
+ Append(methods_proxydocs, meth_str);
+ }
+ Delete(meth_str);
+
+ if (!n) {
+ Append(methods, "NULL");
+ if (fastproxy) {
+ Append(methods_proxydocs, "NULL");
+ }
+ } else if (Node *node_with_doc = find_overload_with_docstring(n)) {
+ /* Use the low-level docstring here since this is the docstring that will be used for the C API */
+ String *ds = cdocstring(node_with_doc, Getattr(n, "memberfunction") ? AUTODOC_METHOD : AUTODOC_FUNC, true);
+ Printf(methods, "\"%s\"", ds);
+ if (fastproxy) {
+ /* In the fastproxy case, we must also record the high-level docstring for use in the Python shadow API */
+ Delete(ds);
+ ds = cdocstring(node_with_doc, Getattr(n, "memberfunction") ? AUTODOC_METHOD : AUTODOC_FUNC);
+ Printf(methods_proxydocs, "\"%s\"", ds);
+ }
+ Delete(ds);
+ } else if (Getattr(n, "feature:callback")) {
+ Printf(methods, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
+ if (fastproxy) {
+ Printf(methods_proxydocs, "\"swig_ptr: %s\"", Getattr(n, "feature:callback:name"));
+ have_fast_proxy_static_member_method_callback = true;
+ }
+ } else {
+ Append(methods, "NULL");
+ if (fastproxy) {
+ Append(methods_proxydocs, "NULL");
+ }
+ }
+
+ Append(methods, "},\n");
+ if (fastproxy) {
+ Append(methods_proxydocs, "},\n");
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+ void dispatchFunction(Node *n, String *linkage, int funpack = 0, bool builtin_self = false, bool builtin_ctor = false, bool director_class = false, bool use_static_method = false) {
+ /* Last node in overloaded chain */
+
+ bool add_self = builtin_self && (!builtin_ctor || director_class);
+
+ int maxargs;
+
+ String *tmp = NewString("");
+ String *dispatch;
+
+ const char *dispatch_call = funpack ? "%s(self, argc, argv);" : (builtin_ctor ? "%s(self, args, NULL);" : "%s(self, args);");
+ String *dispatch_code = NewStringf("return %s", dispatch_call);
+
+ if (castmode) {
+ dispatch = Swig_overload_dispatch_cast(n, dispatch_code, &maxargs);
+ } else {
+ String *fastdispatch_code;
+ if (builtin_ctor)
+ fastdispatch_code = NewStringf("int retval = %s\nif (retval == 0 || !SWIG_Python_TypeErrorOccurred(NULL)) return retval;\nSWIG_fail;", dispatch_call);
+ else
+ fastdispatch_code = NewStringf("PyObject *retobj = %s\nif (!SWIG_Python_TypeErrorOccurred(retobj)) return retobj;\nSWIG_fail;", dispatch_call);
+ if (!CPlusPlus) {
+ Insert(fastdispatch_code, 0, "{\n");
+ Append(fastdispatch_code, "\n}");
+ }
+ dispatch = Swig_overload_dispatch(n, dispatch_code, &maxargs, fastdispatch_code);
+ Delete(fastdispatch_code);
+ }
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(symname);
+
+ const char *builtin_kwargs = builtin_ctor ? ", PyObject *kwargs" : "";
+ Printv(f->def, linkage, builtin_ctor ? "int " : "PyObject *", wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
+
+ if (builtin) {
+ /* Avoid warning if the self parameter is not used. */
+ Append(f->code, "(void)self;\n");
+ }
+
+ Wrapper_add_local(f, "argc", "Py_ssize_t argc");
+ Printf(tmp, "PyObject *argv[%d] = {0}", maxargs + 1);
+ Wrapper_add_local(f, "argv", tmp);
+
+ if (!fastunpack) {
+ Wrapper_add_local(f, "ii", "Py_ssize_t ii");
+
+ if (builtin_ctor)
+ Printf(f->code, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", symname);
+
+ if (maxargs - (add_self ? 1 : 0) > 0) {
+ Append(f->code, "if (!PyTuple_Check(args)) SWIG_fail;\n");
+ Append(f->code, "argc = PyObject_Length(args);\n");
+ } else {
+ Append(f->code, "argc = args ? PyObject_Length(args) : 0;\n");
+ }
+
+ if (add_self)
+ Append(f->code, "argv[0] = self;\n");
+ Printf(f->code, "for (ii = 0; (ii < %d) && (ii < argc); ii++) {\n", add_self ? maxargs - 1 : maxargs);
+ Printf(f->code, "argv[ii%s] = PyTuple_GET_ITEM(args,ii);\n", add_self ? " + 1" : "");
+ Append(f->code, "}\n");
+ if (add_self)
+ Append(f->code, "argc++;\n");
+ } else {
+ if (builtin_ctor)
+ Printf(f->code, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", symname);
+ Printf(f->code, "if (!(argc = SWIG_Python_UnpackTuple(args, \"%s\", 0, %d, argv%s))) SWIG_fail;\n", symname, maxargs, add_self ? "+1" : "");
+ if (add_self)
+ Append(f->code, "argv[0] = self;\n");
+ else
+ Append(f->code, "--argc;\n");
+ }
+
+ Replaceall(dispatch, "$args", "self, args");
+
+ Printv(f->code, dispatch, "\n", NIL);
+
+ if (GetFlag(n, "feature:python:maybecall")) {
+ Append(f->code, "fail:\n");
+ Append(f->code, " SWIG_Py_INCREF(Py_NotImplemented);\n");
+ Append(f->code, " return Py_NotImplemented;\n");
+ } else {
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Append(f->code, "fail:\n");
+ Printf(f->code, " SWIG_Python_RaiseOrModifyTypeError("
+ "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
+ Printf(f->code, "return %s;\n", builtin_ctor ? "-1" : "0");
+ Delete(protoTypes);
+ }
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+ if (!builtin_self && (use_static_method || !builtin))
+ add_method(symname, wname, 0, Getattr(n, "sym:previousSibling") ? n : NULL);
+
+ /* Create a shadow for this function (if enabled and not in a member function) */
+ if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER) && use_static_method) {
+ emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, symname, 0);
+ }
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(dispatch_code);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ /*
+ A note about argument marshalling with built-in types.
+ There are three distinct cases for member (non-static) methods:
+
+ 1) An ordinary member function. In this case, the first param in
+ the param list is 'this'. For builtin types, 'this' is taken from
+ the first argument to the wrapper (usually called 'self); it's not
+ extracted from the second argument (which is usually a tuple).
+
+ 2) A constructor for a non-director class. In this case, the
+ param list doesn't contain an entry for 'this', but the first ('self')
+ argument to the wrapper *does* contain the newly-allocated,
+ uninitialized object.
+
+ 3) A constructor for a director class. In this case, the param
+ list contains a 'self' param, which comes from the first argument
+ to the wrapper function.
+ */
+
+ const char *get_implicitconv_flag(Node *klass) {
+ int conv = 0;
+ if (klass && GetFlag(klass, "feature:implicitconv")) {
+ conv = 1;
+ }
+ return conv ? "SWIG_POINTER_IMPLICIT_CONV" : "0";
+ }
+
+
+ virtual int functionWrapper(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ Node *parent = Swig_methodclass(n);
+
+ int director_method = 0;
+
+ Parm *p;
+ int i;
+ char source[64];
+ Wrapper *f;
+ String *self_parse;
+ String *parse_args;
+ String *arglist;
+ String *get_pointers;
+ String *cleanup;
+ String *outarg;
+ String *kwargs;
+ String *tm;
+ String *overname = 0;
+
+ int num_required;
+ int num_arguments;
+ int num_fixed_arguments;
+ int tuple_required;
+ int tuple_arguments;
+ int varargs = 0;
+ int allow_kwargs = check_kwargs(n);
+
+ String *nodeType = Getattr(n, "nodeType");
+ int constructor = (!Cmp(nodeType, "constructor"));
+ int destructor = (!Cmp(nodeType, "destructor"));
+ String *storage = Getattr(n, "storage");
+ int isfriend = Strstr(storage, "friend") != NULL;
+ /* Only the first constructor is handled as init method. Others
+ constructor can be emitted via %rename */
+ int handled_as_init = 0;
+ if (!have_constructor && (constructor || Getattr(n, "handled_as_constructor"))
+ && ((shadow & PYSHADOW_MEMBER))) {
+ String *nname = Getattr(n, "sym:name");
+ String *sname = Getattr(getCurrentClass(), "sym:name");
+ String *cname = Swig_name_construct(NSPACE_TODO, sname);
+ handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
+ Delete(cname);
+ }
+ bool builtin_self = builtin && in_class && (constructor || (l && Getattr(l, "self")));
+ bool builtin_ctor = false;
+ if (builtin_self && constructor) {
+ String *class_mname = Getattr(getCurrentClass(), "sym:name");
+ String *mrename = Swig_name_construct(getNSpace(), class_mname);
+ if (Cmp(iname, mrename))
+ builtin_self = false;
+ else
+ builtin_ctor = true;
+ Delete(mrename);
+ }
+ bool director_class = (getCurrentClass() && Swig_directorclass(getCurrentClass()));
+ bool add_self = builtin_self && (!builtin_ctor || director_class);
+ bool builtin_getter = (builtin && GetFlag(n, "memberget"));
+ bool builtin_setter = (builtin && GetFlag(n, "memberset") && !builtin_getter);
+ char const *wrap_return = builtin_ctor ? "int " : "PyObject *";
+ String *linkage = NewString("SWIGINTERN ");
+ String *wrapper_name = Swig_name_wrapper(iname);
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ f = NewWrapper();
+ self_parse = NewString("");
+ parse_args = NewString("");
+ arglist = NewString("");
+ get_pointers = NewString("");
+ cleanup = NewString("");
+ outarg = NewString("");
+ kwargs = NewString("");
+
+ int allow_thread = threads_enable(n);
+
+ Wrapper_add_local(f, "resultobj", "PyObject *resultobj = 0");
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+ Setattr(n, "wrap:parms", l);
+ /* Get number of required and total arguments */
+ tuple_arguments = num_arguments = emit_num_arguments(l);
+ tuple_required = num_required = emit_num_required(l);
+ if (add_self) {
+ --tuple_arguments;
+ --tuple_required;
+ }
+ num_fixed_arguments = tuple_required;
+
+ // builtin handles/checks kwargs by default except in constructor wrappers so we need to explicitly handle them in the C constructor wrapper
+ // The check below is for zero arguments. Sometimes (eg directors) self is the first argument for a method with zero arguments.
+ if (((num_arguments == 0) && (num_required == 0)) || ((num_arguments == 1) && (num_required == 1) && Getattr(l, "self")))
+ if (!builtin_ctor)
+ allow_kwargs = 0;
+ varargs = emit_isvarargs(l);
+
+ String *wname = Copy(wrapper_name);
+ if (overname) {
+ Append(wname, overname);
+ }
+
+ const char *builtin_kwargs = builtin_ctor ? ", PyObject *kwargs" : "";
+ if (!allow_kwargs || overname) {
+ if (!varargs) {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *self, PyObject *args, PyObject *varargs", builtin_kwargs, ") {", NIL);
+ }
+ if (allow_kwargs) {
+ Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions (%s).\n", Swig_name_decl(n));
+ allow_kwargs = 0;
+ }
+ } else {
+ if (varargs) {
+ Swig_warning(WARN_LANG_VARARGS_KEYWORD, input_file, line_number, "Can't wrap varargs with keyword arguments enabled\n");
+ varargs = 0;
+ }
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, PyObject *args, PyObject *kwargs) {", NIL);
+ /* Avoid warning if the self parameter is not used. */
+ Append(f->def, "(void)self;\n");
+ }
+
+ if (!builtin) {
+ /* Avoid warning if the self parameter is not used. */
+ Append(f->code, "(void)self;\n");
+ }
+
+ if (!builtin || !in_class || tuple_arguments > 0 || builtin_ctor) {
+ if (!allow_kwargs) {
+ Append(parse_args, " if (!PyArg_ParseTuple(args, \"");
+ } else {
+ Append(parse_args, " if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"");
+ Append(arglist, ", kwnames");
+ }
+ }
+
+ bool over_varargs = emit_isvarargs_function(n);
+
+ int funpack = fastunpack && !varargs && !over_varargs && !allow_kwargs;
+ int noargs = funpack && (tuple_required == 0 && tuple_arguments == 0);
+ int onearg = funpack && (tuple_required == 1 && tuple_arguments == 1);
+
+ if (builtin && funpack && !overname && !builtin_ctor) {
+ int compactdefargs = ParmList_is_compactdefargs(l);
+ if (!(compactdefargs && (tuple_arguments > tuple_required || varargs))) {
+ String *argattr = NewStringf("%d", tuple_arguments);
+ Setattr(n, "python:argcount", argattr);
+ Delete(argattr);
+ }
+ }
+
+ /* Generate code for argument marshalling */
+ if (funpack) {
+ if (num_arguments > (builtin_self && !constructor ? 1 : 0) && !overname) {
+ sprintf(source, "PyObject *swig_obj[%d]", num_arguments);
+ Wrapper_add_localv(f, "swig_obj", source, NIL);
+ }
+ }
+
+
+ if (constructor && num_arguments == 1 && num_required == 1) {
+ if (Cmp(storage, "explicit") == 0) {
+ if (GetFlag(parent, "feature:implicitconv")) {
+ String *desc = NewStringf("SWIGTYPE%s", SwigType_manglestr(Getattr(n, "type")));
+ Printf(f->code, "if (SWIG_CheckImplicit(%s)) SWIG_fail;\n", desc);
+ Delete(desc);
+ }
+ }
+ }
+
+ if (builtin_ctor && checkAttribute(n, "access", "protected")) {
+ String *tmp_none_comparison = Copy(none_comparison);
+ Replaceall(tmp_none_comparison, "$arg", "self");
+ Printf(self_parse, "if (!(%s)) {\n", tmp_none_comparison);
+ Printv(self_parse, " SWIG_SetErrorMsg(PyExc_RuntimeError, \"accessing abstract class or protected constructor\");\n SWIG_fail;\n}\n", NIL);
+ Delete(tmp_none_comparison);
+ }
+
+ int use_parse = 0;
+ Append(kwargs, "{");
+ for (i = 0, p = l; i < num_arguments; i++) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ bool parse_from_tuple = (i > 0 || !add_self);
+ if (SwigType_type(pt) == T_VARARGS) {
+ parse_from_tuple = false;
+ num_fixed_arguments -= atoi(Char(Getattr(p, "tmap:in:numinputs")));
+ }
+ if (!parse_from_tuple)
+ sprintf(source, "self");
+ else if (funpack)
+ sprintf(source, "swig_obj[%d]", add_self && !overname ? i - 1 : i);
+ else
+ sprintf(source, "obj%d", builtin_ctor ? i + 1 : i);
+
+ if (parse_from_tuple) {
+ Printf(arglist, ", ");
+ if (i == num_required)
+ Putc('|', parse_args); /* Optional argument separator */
+ }
+
+ /* Keyword argument handling */
+ if (allow_kwargs && parse_from_tuple) {
+ String *name = makeParameterName(n, p, i + 1);
+ Printf(kwargs, " (char *)\"%s\", ", name);
+ Delete(name);
+ }
+
+ /* Look for an input typemap */
+ if ((tm = Getattr(p, "tmap:in"))) {
+ String *parse = Getattr(p, "tmap:in:parse");
+ if (!parse) {
+ if (builtin_self) {
+ Replaceall(tm, "$self", "self");
+ } else if (funpack) {
+ Replaceall(tm, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(tm, "$self", "obj0");
+ }
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source); /* Save the location of the object */
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ if (Getattr(p, "tmap:in:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ Replaceall(tm, "$implicitconv", convflag);
+ Setattr(p, "implicitconv", convflag);
+ }
+
+ if (parse_from_tuple)
+ Putc('O', parse_args);
+ if (!funpack && parse_from_tuple) {
+ Wrapper_add_localv(f, source, "PyObject *", source, "= 0", NIL);
+ Printf(arglist, "&%s", source);
+ }
+ if (i >= num_required)
+ Printv(get_pointers, "if (", source, ") {\n", NIL);
+ Printv(get_pointers, tm, "\n", NIL);
+ if (i >= num_required)
+ Printv(get_pointers, "}\n", NIL);
+
+ } else {
+ use_parse = 1;
+ Append(parse_args, parse);
+ if (parse_from_tuple)
+ Printf(arglist, "&%s", ln);
+ }
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ break;
+ }
+ }
+
+ /* finish argument marshalling */
+ Append(kwargs, " NULL }");
+ if (allow_kwargs) {
+ Printv(f->locals, " char * kwnames[] = ", kwargs, ";\n", NIL);
+ }
+
+ if (use_parse || allow_kwargs) {
+ Printf(parse_args, ":%s\"", iname);
+ Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL);
+ funpack = 0;
+ } else {
+ Clear(parse_args);
+
+ if (funpack) {
+ Clear(f->def);
+ if (overname) {
+ if (noargs) {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {", NIL);
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
+ }
+ /* Avoid warning if the self parameter is not used. */
+ Append(f->def, "(void)self;\n");
+ Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments);
+ } else {
+ int is_tp_call = Equal(Getattr(n, "feature:python:slot"), "tp_call");
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
+ /* Avoid warning if the self parameter is not used. */
+ Append(f->def, "(void)self;\n");
+ if (builtin_ctor)
+ Printf(parse_args, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", iname);
+ if (onearg && !builtin_ctor && !is_tp_call) {
+ Printf(parse_args, "if (!args) SWIG_fail;\n");
+ Append(parse_args, "swig_obj[0] = args;\n");
+ } else if (!noargs) {
+ Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args, \"%s\", %d, %d, swig_obj)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments);
+ } else if (noargs) {
+ Printf(parse_args, "if (!SWIG_Python_UnpackTuple(args, \"%s\", %d, %d, 0)) SWIG_fail;\n", iname, num_fixed_arguments, tuple_arguments);
+ }
+ }
+ } else {
+ if (builtin_ctor)
+ Printf(parse_args, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", iname);
+ if (builtin && in_class && tuple_arguments == 0) {
+ Printf(parse_args, " if (args && PyTuple_Check(args) && PyTuple_GET_SIZE(args) > 0) SWIG_exception_fail(SWIG_TypeError, \"%s takes no arguments\");\n", iname);
+ } else {
+ Printf(parse_args, "if (!PyArg_UnpackTuple(args, \"%s\", %d, %d", iname, num_fixed_arguments, tuple_arguments);
+ Printv(parse_args, arglist, ")) SWIG_fail;\n", NIL);
+ }
+ }
+ }
+
+ /* Now piece together the first part of the wrapper function */
+ Printv(f->code, self_parse, parse_args, get_pointers, NIL);
+
+ /* Check for trailing varargs */
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", "varargs");
+ Printv(f->code, tm, "\n", NIL);
+ }
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if (!Getattr(p, "tmap:in:parse") && (tm = Getattr(p, "tmap:freearg"))) {
+ if (Getattr(p, "tmap:freearg:implicitconv")) {
+ const char *convflag = "0";
+ if (!Getattr(p, "hidden")) {
+ SwigType *ptype = Getattr(p, "type");
+ convflag = get_implicitconv_flag(classLookup(ptype));
+ }
+ if (strcmp(convflag, "0") == 0) {
+ tm = 0;
+ }
+ }
+ if (tm && (Len(tm) != 0)) {
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* if the object is a director, and the method call originated from its
+ * underlying python object, resolve the call by going up the c++
+ * inheritance chain. otherwise try to resolve the method in python.
+ * without this check an infinite loop is set up between the director and
+ * shadow class method calls.
+ */
+
+ // NOTE: this code should only be inserted if this class is the
+ // base class of a director class. however, in general we haven't
+ // yet analyzed all classes derived from this one to see if they are
+ // directors. furthermore, this class may be used as the base of
+ // a director class defined in a completely different module at a
+ // later time, so this test must be included whether or not directorbase
+ // is true. we do skip this code if directors have not been enabled
+ // at the command line to preserve source-level compatibility with
+ // non-polymorphic swig. also, if this wrapper is for a smart-pointer
+ // method, there is no need to perform the test since the calling object
+ // (the smart-pointer) and the director object (the "pointee") are
+ // distinct.
+
+ director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Append(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n");
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name);
+ Printf(f->code, "SWIG_SetErrorMsg(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
+ Append(f->code, "SWIG_fail;\n");
+ Append(f->code, "}\n");
+ }
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ if (funpack) {
+ const char *self_parm = builtin_self ? "self" : "swig_obj[0]";
+ Printf(f->code, "upcall = (director && (director->swig_get_self()==%s));\n", self_parm);
+ } else {
+ const char *self_parm = builtin_self ? "self" : "obj0";
+ Printf(f->code, "upcall = (director && (director->swig_get_self()==%s));\n", self_parm);
+ }
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Append(f->code, "try {\n");
+ } else {
+ if (allow_thread) {
+ String *preaction = NewString("");
+ thread_begin_allow(n, preaction);
+ Setattr(n, "wrap:preaction", preaction);
+
+ String *postaction = NewString("");
+ thread_end_allow(n, postaction);
+ Setattr(n, "wrap:postaction", postaction);
+ }
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (director_method) {
+ Append(actioncode, "} catch (Swig::DirectorException&) {\n");
+ Append(actioncode, " SWIG_fail;\n");
+ Append(actioncode, "}\n");
+ }
+
+ /* This part below still needs cleanup */
+
+ /* Return the function value */
+ tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+
+ if (tm) {
+ if (builtin_self) {
+ Replaceall(tm, "$self", "self");
+ } else if (funpack) {
+ Replaceall(tm, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(tm, "$self", "obj0");
+ }
+ Replaceall(tm, "$result", "resultobj");
+ if (builtin_ctor) {
+ Replaceall(tm, "$owner", "SWIG_BUILTIN_INIT");
+ } else if (handled_as_init) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_NEW");
+ } else {
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ }
+
+ // Unwrap return values that are director classes so that the original Python object is returned instead.
+ if (!constructor && Swig_director_can_unwrap(n)) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = SWIG_DIRECTOR_CAST(%s);\n", Swig_cresult_name());
+ Append(f->code, "if (director) {\n");
+ Append(f->code, " resultobj = director->swig_get_self();\n");
+ Append(f->code, " SWIG_Py_INCREF(resultobj);\n");
+ Append(f->code, "} else {\n");
+ Printf(f->code, "%s\n", tm);
+ Append(f->code, "}\n");
+ } else {
+ Printf(f->code, "%s\n", tm);
+ }
+
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), name);
+ }
+ emit_return_variable(n, returntype, f);
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ int need_cleanup = Len(cleanup) != 0;
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "resultobj");
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+ }
+
+ if (builtin_ctor)
+ Append(f->code, " return resultobj == Py_None ? -1 : 0;\n");
+ else
+ Append(f->code, " return resultobj;\n");
+
+ /* Error handling code */
+
+ Append(f->code, "fail:\n");
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ if (builtin_ctor) {
+ Printv(f->code, " return -1;\n", NIL);
+ } else {
+ if (GetFlag(n, "feature:python:maybecall")) {
+ Append(f->code, " if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) {\n");
+ Append(f->code, " return NULL;\n");
+ Append(f->code, " }\n");
+ Append(f->code, " PyErr_Clear();\n");
+ Append(f->code, " SWIG_Py_INCREF(Py_NotImplemented);\n");
+ Append(f->code, " return Py_NotImplemented;\n");
+ } else {
+ Printv(f->code, " return NULL;\n", NIL);
+ }
+ }
+
+ Append(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", iname);
+ Replaceall(f->code, "$result", "resultobj");
+
+ if (builtin_self) {
+ Replaceall(f->code, "$self", "self");
+ } else if (funpack) {
+ Replaceall(f->code, "$self", "swig_obj[0]");
+ } else {
+ Replaceall(f->code, "$self", "obj0");
+ }
+
+ /* Dump the function out */
+ Wrapper_print(f, f_wrappers);
+
+ /* If varargs. Need to emit a varargs stub */
+ if (varargs) {
+ DelWrapper(f);
+ f = NewWrapper();
+ if (funpack) {
+ // Note: funpack is currently always false for varargs
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
+ }
+ Wrapper_add_local(f, "resultobj", builtin_ctor ? "int resultobj" : "PyObject *resultobj");
+ Wrapper_add_local(f, "varargs", "PyObject *varargs");
+ Wrapper_add_local(f, "newargs", "PyObject *newargs");
+ if (funpack) {
+ Wrapper_add_local(f, "i", "int i");
+ Printf(f->code, "newargs = PyTuple_New(%d);\n", num_fixed_arguments);
+ Printf(f->code, "for (i = 0; i < %d; ++i) {\n", num_fixed_arguments);
+ Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i]);\n");
+ Printf(f->code, " SWIG_Py_XINCREF(swig_obj[i]);\n");
+ Printf(f->code, "}\n");
+ Printf(f->code, "varargs = PyTuple_New(nobjs > %d ? nobjs - %d : 0);\n", num_fixed_arguments, num_fixed_arguments);
+ Printf(f->code, "for (i = 0; i < nobjs - %d; ++i) {\n", num_fixed_arguments);
+ Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i + %d]);\n", num_fixed_arguments);
+ Printf(f->code, " SWIG_Py_XINCREF(swig_obj[i + %d]);\n", num_fixed_arguments);
+ Printf(f->code, "}\n");
+ } else {
+ Printf(f->code, "newargs = PyTuple_GetSlice(args, 0, %d);\n", num_fixed_arguments);
+ Printf(f->code, "varargs = PyTuple_GetSlice(args, %d, PyTuple_Size(args));\n", num_fixed_arguments);
+ }
+ Printf(f->code, "resultobj = %s__varargs__(%s, newargs, varargs%s);\n", wname, builtin ? "self" : "NULL", strlen(builtin_kwargs) == 0 ? "" : ", kwargs");
+ Append(f->code, "SWIG_Py_XDECREF(newargs);\n");
+ Append(f->code, "SWIG_Py_XDECREF(varargs);\n");
+ Append(f->code, "return resultobj;\n");
+ Append(f->code, "}\n");
+ Wrapper_print(f, f_wrappers);
+ }
+
+ bool use_static_method = flat_static_method || !Swig_storage_isstatic_custom(n, "staticmemberfunctionHandler:storage");
+ /* Now register the function with the interpreter. */
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!builtin_self && (use_static_method || !builtin))
+ add_method(iname, wname, allow_kwargs, n, funpack, num_required, num_arguments);
+
+ /* Create a shadow for this function (if enabled and not in a member function) */
+ if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER) && use_static_method) {
+ emitFunctionShadowHelper(n, in_class ? f_shadow_stubs : f_shadow, iname, allow_kwargs);
+ }
+
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n, linkage, funpack, builtin_self, builtin_ctor, director_class, use_static_method);
+ }
+ }
+
+ // Put this in tp_init of the PyTypeObject
+ if (builtin_ctor) {
+ if ((director_method || !is_private(n)) && !Getattr(class_members, iname)) {
+ Setattr(class_members, iname, n);
+ if (!builtin_tp_init)
+ builtin_tp_init = Swig_name_wrapper(iname);
+ }
+ }
+
+ /* If this is a builtin type, create a PyGetSetDef entry for this member variable. */
+ if (builtin) {
+ const char *memname = "__dict__";
+ Hash *h = Getattr(builtin_getset, memname);
+ if (!h) {
+ h = NewHash();
+ Setattr(builtin_getset, memname, h);
+ Delete(h);
+ }
+ Setattr(h, "getter", "SwigPyObject_get___dict__");
+ if (!Getattr(h, "doc")) {
+ Setattr(n, "doc:high:name", Getattr(n, "name"));
+ Setattr(h, "doc", cdocstring(n, AUTODOC_VAR));
+ }
+ }
+
+ if (builtin_getter) {
+ String *memname = Getattr(n, "membervariableHandler:sym:name");
+ if (!memname)
+ memname = iname;
+ Hash *h = Getattr(builtin_getset, memname);
+ if (!h) {
+ h = NewHash();
+ Setattr(builtin_getset, memname, h);
+ Delete(h);
+ }
+ Setattr(h, "getter", wrapper_name);
+ Delattr(n, "memberget");
+ if (!Getattr(h, "doc")) {
+ Setattr(n, "doc:high:name", Getattr(n, "name"));
+ String *ds = cdocstring(n, AUTODOC_VAR);
+ Setattr(h, "doc", ds);
+ Delete(ds);
+ }
+ }
+ if (builtin_setter) {
+ String *memname = Getattr(n, "membervariableHandler:sym:name");
+ if (!memname)
+ memname = iname;
+ Hash *h = Getattr(builtin_getset, memname);
+ if (!h) {
+ h = NewHash();
+ Setattr(builtin_getset, memname, h);
+ Delete(h);
+ }
+ Setattr(h, "setter", wrapper_name);
+ Delattr(n, "memberset");
+ if (!Getattr(h, "doc")) {
+ Setattr(n, "doc:high:name", Getattr(n, "name"));
+ String *ds = cdocstring(n, AUTODOC_VAR);
+ Setattr(h, "doc", ds);
+ Delete(ds);
+ }
+ }
+
+ if (in_class && builtin) {
+ /* Handle operator overloads for builtin types */
+ String *slot = Getattr(n, "feature:python:slot");
+ if (slot && !isfriend) {
+ String *func_type = Getattr(n, "feature:python:slot:functype");
+ String *closure_decl = getClosure(func_type, wrapper_name, overname ? 0 : funpack);
+ String *feature_name = NewStringf("feature:python:%s", slot);
+ String *closure_name = 0;
+ if (closure_decl) {
+ closure_name = NewStringf("%s_%s_closure", wrapper_name, func_type);
+ if (!GetFlag(builtin_closures, closure_name))
+ Printf(builtin_closures_code, "%s /* defines %s */\n\n", closure_decl, closure_name);
+ SetFlag(builtin_closures, closure_name);
+ Delete(closure_decl);
+ } else {
+ closure_name = Copy(wrapper_name);
+ }
+ if (func_type) {
+ String *s = NewStringf("%s", closure_name);
+ Delete(closure_name);
+ closure_name = s;
+ }
+ Setattr(parent, feature_name, closure_name);
+ Delete(feature_name);
+ Delete(closure_name);
+ }
+
+ /* Handle comparison operators for builtin types */
+ String *compare = Getattr(n, "feature:python:compare");
+ if (compare) {
+ Hash *richcompare = Getattr(parent, "python:richcompare");
+ assert(richcompare);
+ Setattr(richcompare, compare, wrapper_name);
+ }
+ }
+
+ Delete(self_parse);
+ Delete(parse_args);
+ Delete(linkage);
+ Delete(arglist);
+ Delete(get_pointers);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(kwargs);
+ Delete(wname);
+ DelWrapper(f);
+ Delete(wrapper_name);
+ return SWIG_OK;
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ static int have_globals = 0;
+ String *tm;
+ Wrapper *getf, *setf;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* If this is our first call, add the globals variable to the
+ Python dictionary. */
+
+ if (!have_globals) {
+ Printf(f_init, "\t globals = SWIG_globals();\n");
+ Printf(f_init, "\t if (!globals) {\n");
+ Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Failure to create SWIG globals.\");\n");
+ Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n");
+ Printf(f_init, "\t return NULL;\n");
+ Printf(f_init, "#else\n");
+ Printf(f_init, "\t return;\n");
+ Printf(f_init, "#endif\n");
+ Printf(f_init, "\t }\n");
+ Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", globals);\n", global_name);
+ if (builtin)
+ Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name);
+ have_globals = 1;
+ if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER)) {
+ Printf(f_shadow_stubs, "%s = %s.%s\n", global_name, module, global_name);
+ }
+ }
+ int assignable = !is_immutable(n);
+
+ if (!builtin && shadow && !assignable && !in_class)
+ Printf(f_shadow_stubs, "%s = %s.%s\n", iname, global_name, iname);
+
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+ String *vargetname = NewStringf("Swig_var_%s", getname);
+ String *varsetname = NewStringf("Swig_var_%s", setname);
+
+ /* Create a function for setting the value of the variable */
+ if (assignable) {
+ Setattr(n, "wrap:name", varsetname);
+ if (builtin && in_class) {
+ String *set_wrapper = Swig_name_wrapper(setname);
+ Setattr(n, "pybuiltin:setter", set_wrapper);
+ Delete(set_wrapper);
+ }
+ Printf(setf->def, "SWIGINTERN int %s(PyObject *_val) {", varsetname);
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$input", "_val");
+ if (Getattr(n, "tmap:varin:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ emit_action_code(n, setf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ }
+ Printv(setf->code, " return 0;\n", NULL);
+ Append(setf->code, "fail:\n");
+ Printv(setf->code, " return 1;\n", NULL);
+ } else {
+ /* Is a readonly variable. Issue an error */
+ if (CPlusPlus) {
+ Printf(setf->def, "SWIGINTERN int %s(PyObject *) {", varsetname);
+ } else {
+ Printf(setf->def, "SWIGINTERN int %s(PyObject *_val SWIGUNUSED) {", varsetname);
+ }
+ Printv(setf->code, " SWIG_Error(SWIG_AttributeError,\"Variable ", iname, " is read-only.\");\n", " return 1;\n", NIL);
+ }
+
+ Append(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+
+ /* Create a function for getting the value of a variable */
+ Setattr(n, "wrap:name", vargetname);
+ if (builtin && in_class) {
+ String *get_wrapper = Swig_name_wrapper(getname);
+ Setattr(n, "pybuiltin:getter", get_wrapper);
+ Delete(get_wrapper);
+ }
+ int addfail = 0;
+ Printf(getf->def, "SWIGINTERN PyObject *%s(void) {", vargetname);
+ Wrapper_add_local(getf, "pyobj", "PyObject *pyobj = 0");
+ if (builtin) {
+ Wrapper_add_local(getf, "self", "PyObject *self = 0");
+ Append(getf->code, " (void)self;\n");
+ }
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "pyobj");
+ addfail = emit_action_code(n, getf->code, tm);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ }
+ Append(getf->code, " return pyobj;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, " return NULL;\n");
+ }
+ Append(getf->code, "}\n");
+
+ Wrapper_print(getf, f_wrappers);
+
+ /* Now add this to the variable linking mechanism */
+ Printf(f_varlinks, "\t SWIG_addvarlink(globals, \"%s\", %s, %s);\n", iname, vargetname, varsetname);
+ if (builtin && shadow && !assignable && !in_class) {
+ Printf(f_varlinks, "\t PyDict_SetItemString(md, \"%s\", PyObject_GetAttrString(globals, \"%s\"));\n", iname, iname);
+ Printf(f_varlinks, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", iname);
+ }
+ Delete(vargetname);
+ Delete(varsetname);
+ Delete(getname);
+ Delete(setname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ /* Determine if the node requires the _swigconstant code to be generated */
+ bool needs_swigconstant(Node *n) {
+ SwigType *type = Getattr(n, "type");
+ SwigType *qtype = SwigType_typedef_resolve_all(type);
+ SwigType *uqtype = SwigType_strip_qualifiers(qtype);
+ bool result = false;
+
+ /* Note, that we need special handling for function pointers, as
+ * SwigType_base(fptr) does not return the underlying pointer-to-function
+ * type but the return-type of function. */
+ if (!SwigType_isfunction(uqtype) && !SwigType_isfunctionpointer(uqtype)) {
+ SwigType *basetype = SwigType_base(uqtype);
+ result = SwigType_isclass(basetype) != 0;
+ Delete(basetype);
+ }
+
+ Delete(qtype);
+ Delete(uqtype);
+
+ return result;
+ }
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *tm;
+ int have_tm = 0;
+ int have_builtin_symname = 0;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ String *str = SwigType_str(type, wname);
+ Printf(f_header, "static %s = %s;\n", str, value);
+ Delete(str);
+ value = wname;
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Printf(const_code, "%s,\n", tm);
+ Delete(tm);
+ have_tm = 1;
+ }
+
+
+ if (builtin && in_class && Getattr(n, "pybuiltin:symname")) {
+ have_builtin_symname = 1;
+ Swig_require("builtin_constantWrapper", n, "*sym:name", "pybuiltin:symname", NIL);
+ Setattr(n, "sym:name", Getattr(n, "pybuiltin:symname"));
+ }
+
+ if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ if (needs_swigconstant(n) && !builtin && shadow && !(shadow & PYSHADOW_MEMBER) && (!in_class || !Getattr(n, "feature:python:callback"))) {
+ // Generate `*_swigconstant()` method which registers the new constant.
+ //
+ // *_swigconstant methods are required for constants of class type.
+ // Class types are registered in shadow file (see *_swigregister). The
+ // instances of class must be created (registered) after the type is
+ // registered, so we can't let SWIG_init() to register constants of
+ // class type (the SWIG_init() is called before shadow classes are
+ // defined and registered).
+ Printf(f_wrappers, "SWIGINTERN PyObject *%s_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", iname);
+ Printf(f_wrappers, tab2 "PyObject *module = NULL;\n");
+ Printf(f_wrappers, tab2 "PyObject *d;\n");
+ Printf(f_wrappers, tab2 "if (!SWIG_Python_UnpackTuple(args, \"swigconstant\", 1, 1, &module)) return NULL;\n");
+ Printf(f_wrappers, tab2 "d = PyModule_GetDict(module);\n");
+ Printf(f_wrappers, tab2 "if (!d) return NULL;\n");
+ Printf(f_wrappers, tab2 "%s\n", tm);
+ Printf(f_wrappers, tab2 "return SWIG_Py_Void();\n");
+ Printf(f_wrappers, "}\n\n\n");
+
+ // Register the method in SwigMethods array
+ String *cname = NewStringf("%s_swigconstant", iname);
+ add_method(cname, cname, 0, 0, 1, 1, 1);
+ Delete(cname);
+ } else {
+ Printf(f_init, "%s\n", tm);
+ }
+ Delete(tm);
+ have_tm = 1;
+ }
+
+ if (have_builtin_symname)
+ Swig_restore(n);
+
+ if (!have_tm) {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+
+ if (!builtin && shadow && !(shadow & PYSHADOW_MEMBER)) {
+ String *f_s;
+ if (!in_class) {
+ f_s = f_shadow;
+ } else {
+ f_s = Getattr(n, "feature:python:callback") ? NIL : f_shadow_stubs;
+ }
+
+ if (f_s) {
+ if (needs_swigconstant(n)) {
+ Printv(f_s, "\n",NIL);
+ Printv(f_s, module, ".", iname, "_swigconstant(",module,")\n", NIL);
+ }
+ Printv(f_s, iname, " = ", module, ".", iname, "\n", NIL);
+ if (have_docstring(n))
+ Printv(f_s, docstring(n, AUTODOC_CONST, tab4), "\n", NIL);
+ }
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ add_method(name, wrapname, 0);
+ if (!builtin && shadow) {
+ Printv(f_shadow_stubs, name, " = ", module, ".", name, "\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+
+
+ /* ----------------------------------------------------------------------------
+ * BEGIN C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+ /* C++/Python polymorphism demo code
+ *
+ * TODO
+ *
+ * Move some boilerplate code generation to Swig_...() functions.
+ *
+ */
+
+ /* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Python object.
+ * ** Moved down due to gcc-2.96 internal error **
+ * --------------------------------------------------------------- */
+
+ int classDirectorMethods(Node *n);
+
+ int classDirectorMethod(Node *n, Node *parent, String *super);
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("PyObject");
+ SwigType_add_pointer(type);
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { \n", classname, target, call);
+ Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
+ Append(w->def, "}\n");
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ {
+ Node *parent = Swig_methodclass(n);
+ String *basetype = Getattr(parent, "classtype");
+ Wrapper *w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(PyObject *self) : Swig::Director(self) { \n", classname, classname);
+ Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype);
+ Append(w->def, "}\n");
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ }
+ Printf(f_directors_h, " SwigDirector_%s(PyObject *self);\n", classname);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorInit()
+ * ------------------------------------------------------------ */
+
+ int classDirectorInit(Node *n) {
+ String *declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorEnd()
+ * ------------------------------------------------------------ */
+
+ int classDirectorEnd(Node *n) {
+ String *classname = Swig_class_name(n);
+
+ if (dirprot_mode()) {
+ /*
+ This implementation uses a std::map<std::string,int>.
+
+ It should be possible to rewrite it using a more elegant way,
+ like copying the Java approach for the 'override' array.
+
+ But for now, this seems to be the least intrusive way.
+ */
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "/* Internal director utilities */\n");
+ Printf(f_directors_h, "public:\n");
+ Printf(f_directors_h, " bool swig_get_inner(const char *swig_protected_method_name) const {\n");
+ Printf(f_directors_h, " std::map<std::string, bool>::const_iterator iv = swig_inner.find(swig_protected_method_name);\n");
+ Printf(f_directors_h, " return (iv != swig_inner.end() ? iv->second : false);\n");
+ Printf(f_directors_h, " }\n");
+
+ Printf(f_directors_h, " void swig_set_inner(const char *swig_protected_method_name, bool swig_val) const {\n");
+ Printf(f_directors_h, " swig_inner[swig_protected_method_name] = swig_val;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable std::map<std::string, bool> swig_inner;\n");
+
+ }
+ if (director_method_index) {
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)\n");
+ Printf(f_directors_h, "/* VTable implementation */\n");
+ Printf(f_directors_h, " PyObject *swig_get_method(size_t method_index, const char *method_name) const {\n");
+ Printf(f_directors_h, " PyObject *method = vtable[method_index];\n");
+ Printf(f_directors_h, " if (!method) {\n");
+ Printf(f_directors_h, " swig::SwigVar_PyObject name = SWIG_Python_str_FromChar(method_name);\n");
+ Printf(f_directors_h, " method = PyObject_GetAttr(swig_get_self(), name);\n");
+ Printf(f_directors_h, " if (!method) {\n");
+ Printf(f_directors_h, " std::string msg = \"Method in class %s doesn't exist, undefined \";\n", classname);
+ Printf(f_directors_h, " msg += method_name;\n");
+ Printf(f_directors_h, " Swig::DirectorMethodException::raise(msg.c_str());\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, " vtable[method_index] = method;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, " return method;\n");
+ Printf(f_directors_h, " }\n");
+ Printf(f_directors_h, "private:\n");
+ Printf(f_directors_h, " mutable swig::SwigVar_PyObject vtable[%d];\n", director_method_index);
+ Printf(f_directors_h, "#endif\n\n");
+ }
+
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+
+ /* ------------------------------------------------------------
+ * classDirectorDisown()
+ * ------------------------------------------------------------ */
+
+ int classDirectorDisown(Node *n) {
+ int result;
+ int oldshadow = shadow;
+ /* disable shadowing */
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ result = Language::classDirectorDisown(n);
+ shadow = oldshadow;
+ if (shadow) {
+ if (builtin) {
+ String *rname = SwigType_namestr(real_classname);
+ Printf(builtin_methods, " { \"__disown__\", Swig::Director::swig_pyobj_disown< %s >, METH_NOARGS, \"\" },\n", rname);
+ Delete(rname);
+ } else {
+ String *symname = Getattr(n, "sym:name");
+ String *mrename = Swig_name_disown(NSPACE_TODO, symname); //Getattr(n, "name"));
+ Printv(f_shadow, tab4, "def __disown__(self):\n", NIL);
+ Printv(f_shadow, tab8, "self.this.disown()\n", NIL);
+ Printv(f_shadow, tab8, module, ".", mrename, "(self)\n", NIL);
+ Printv(f_shadow, tab8, "return weakref.proxy(self)\n", NIL);
+ Delete(mrename);
+ }
+ }
+ return result;
+ }
+
+ /* ----------------------------------------------------------------------------
+ * END of C++ Director Class modifications
+ * ------------------------------------------------------------------------- */
+
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ if (shadow && !Getattr(n, "feature:onlychildren")) {
+ Node *mod = Getattr(n, "module");
+ if (mod) {
+ String *modname = Getattr(mod, "name");
+ Node *options = Getattr(mod, "options");
+ String *pkg = options ? Getattr(options, "package") : 0;
+ String *sym = Getattr(n, "sym:name");
+ String *importname = import_name_string(package, mainmodule, pkg, modname, sym);
+ Setattr(n, "python:proxy", importname);
+ Delete(importname);
+ }
+ }
+ int result = Language::classDeclaration(n);
+ return result;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ SwigType *add_explicit_scope(SwigType *s) {
+ if (!Strstr(s, "::")) {
+ return NewStringf("::%s", s);
+ }
+ return Copy(s);
+ }
+
+ void builtin_pre_decl(Node *n) {
+ SwigType *name = Getattr(n, "name");
+ SwigType *sname = add_explicit_scope(name);
+ String *rname = SwigType_namestr(sname);
+ String *mname = SwigType_manglestr(sname);
+
+ Printf(f_init, "\n/* type '%s' */\n", rname);
+ Printf(f_init, " d = PyDict_New();\n");
+
+ Delete(sname);
+ Delete(rname);
+ Delete(mname);
+ }
+
+ void builtin_post_decl(File *f, Node *n) {
+ SwigType *name = Getattr(n, "name");
+ SwigType *pname = Copy(name);
+ SwigType_add_pointer(pname);
+ String *symname = Getattr(n, "sym:name");
+ SwigType *sname = add_explicit_scope(name);
+ String *rname = SwigType_namestr(sname);
+ String *mname = SwigType_manglestr(sname);
+ String *pmname = SwigType_manglestr(pname);
+ String *templ = NewStringf("SwigPyBuiltin_%s", mname);
+ int funpack = fastunpack;
+
+ if (have_builtin_static_member_method_callback) {
+ Printf(f_init, " SWIG_Python_FixMethods(SwigPyBuiltin_%s_methods, swig_const_table, swig_types, swig_type_initial);\n", mname);
+ }
+
+ Printv(f_init, " builtin_base_count = 0;\n", NIL);
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ int base_count = 0;
+ for (Iterator b = First(baselist); b.item; b = Next(b)) {
+ String *bname = Getattr(b.item, "name");
+ if (!bname || GetFlag(b.item, "feature:ignore"))
+ continue;
+ base_count++;
+ String *base_name = Copy(bname);
+ SwigType_add_pointer(base_name);
+ String *base_mname = SwigType_manglestr(base_name);
+ Printf(f_init, " builtin_basetype = SWIG_MangledTypeQuery(\"%s\");\n", base_mname);
+ Printv(f_init, " if (builtin_basetype && builtin_basetype->clientdata && ((SwigPyClientData *) builtin_basetype->clientdata)->pytype) {\n", NIL);
+ Printv(f_init, " builtin_bases[builtin_base_count++] = ((SwigPyClientData *) builtin_basetype->clientdata)->pytype;\n", NIL);
+ Printv(f_init, " } else {\n", NIL);
+ Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Could not create type '%s' as base '%s' has not been initialized.\\n\");\n", symname, bname);
+ Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ Printv(f_init, " return NULL;\n", NIL);
+ Printv(f_init, "#else\n", NIL);
+ Printv(f_init, " return;\n", NIL);
+ Printv(f_init, "#endif\n", NIL);
+ Printv(f_init, " }\n", NIL);
+ Delete(base_name);
+ Delete(base_mname);
+ }
+ if (base_count > max_bases)
+ max_bases = base_count;
+ }
+ Printv(f_init, " builtin_bases[builtin_base_count] = NULL;\n", NIL);
+ builtin_bases_needed = 1;
+
+ // Check for non-public destructor, in which case tp_dealloc will issue
+ // a warning and allow the memory to leak. Any class that doesn't explicitly
+ // have a private/protected destructor has an implicit public destructor.
+ static String *tp_dealloc_bad = NewString("SwigPyBuiltin_BadDealloc");
+
+ String *getset_name = NewStringf("%s_getset", templ);
+ String *methods_name = NewStringf("%s_methods", templ);
+ String *getset_def = NewString("");
+ Printf(getset_def, "SWIGINTERN PyGetSetDef %s[] = {\n", getset_name);
+
+ // All objects have 'this' and 'thisown' attributes
+ Printv(f_init, "PyDict_SetItemString(d, \"this\", this_descr);\n", NIL);
+ Printv(f_init, "PyDict_SetItemString(d, \"thisown\", thisown_descr);\n", NIL);
+
+ // Now, the rest of the attributes
+ for (Iterator member_iter = First(builtin_getset); member_iter.item; member_iter = Next(member_iter)) {
+ String *memname = member_iter.key;
+ Hash *mgetset = member_iter.item;
+ String *getter = Getattr(mgetset, "getter");
+ String *setter = Getattr(mgetset, "setter");
+ const char *getter_closure = getter ? funpack ? "SwigPyBuiltin_FunpackGetterClosure" : "SwigPyBuiltin_GetterClosure" : "0";
+ const char *setter_closure = setter ? funpack ? "SwigPyBuiltin_FunpackSetterClosure" : "SwigPyBuiltin_SetterClosure" : "0";
+ String *gspair = NewStringf("%s_%s_getset", symname, memname);
+ Printf(f, "static SwigPyGetSet %s = { %s, %s };\n", gspair, getter ? getter : "0", setter ? setter : "0");
+ String *doc = Getattr(mgetset, "doc");
+ if (!doc)
+ doc = NewStringf("%s.%s", name, memname);
+ String *entry = NewStringf("{ (char *)\"%s\", %s, %s, (char *)\"%s\", &%s }", memname, getter_closure, setter_closure, doc, gspair);
+ if (GetFlag(mgetset, "static")) {
+ Printf(f, "static PyGetSetDef %s_def = %s;\n", gspair, entry);
+ Printf(f_init, "static_getset = SwigPyStaticVar_new_getset(metatype, &%s_def);\n", gspair);
+ Printf(f_init, "PyDict_SetItemString(d, static_getset->d_getset->name, (PyObject *)static_getset);\n");
+ Printf(f_init, "SWIG_Py_DECREF((PyObject *)static_getset);\n");
+ } else {
+ Printf(getset_def, " %s,\n", entry);
+ }
+ Delete(gspair);
+ Delete(entry);
+ }
+ Printv(f, getset_def, " { NULL, NULL, NULL, NULL, NULL } /* Sentinel */\n", "};\n\n", NIL);
+
+ // Rich compare function
+ Hash *richcompare = Getattr(n, "python:richcompare");
+ String *richcompare_func = NewStringf("%s_richcompare", templ);
+ assert(richcompare);
+ Printf(f, "SWIGINTERN PyObject *\n");
+ Printf(f, "%s(PyObject *self, PyObject *other, int op) {\n", richcompare_func);
+ Printf(f, " PyObject *result = NULL;\n");
+ if (!funpack) {
+ Printf(f, " PyObject *tuple = PyTuple_New(1);\n");
+ Printf(f, " assert(tuple);\n");
+ Printf(f, " PyTuple_SET_ITEM(tuple, 0, other);\n");
+ Printf(f, " SWIG_Py_XINCREF(other);\n");
+ }
+ List *richcompare_list = SortedKeys(richcompare, 0);
+ Iterator rich_iter = First(richcompare_list);
+ if (rich_iter.item) {
+ Printf(f, " switch (op) {\n");
+ for (; rich_iter.item; rich_iter = Next(rich_iter))
+ Printf(f, " case %s : result = %s(self, %s); break;\n", rich_iter.item, Getattr(richcompare, rich_iter.item), funpack ? "other" : "tuple");
+ Printv(f, " default : break;\n", NIL);
+ Printf(f, " }\n");
+ }
+ Delete(richcompare_list);
+ Printv(f, " if (!result && !PyErr_Occurred()) {\n", NIL);
+ Printv(f, " if (SwigPyObject_Check(self) && SwigPyObject_Check(other)) {\n", NIL);
+ Printv(f, " result = SwigPyObject_richcompare((SwigPyObject *)self, (SwigPyObject *)other, op);\n", NIL);
+ Printv(f, " } else {\n", NIL);
+ Printv(f, " result = Py_NotImplemented;\n", NIL);
+ Printv(f, " SWIG_Py_INCREF(result);\n", NIL);
+ Printv(f, " }\n", NIL);
+ Printv(f, " }\n", NIL);
+ if (!funpack)
+ Printf(f, " SWIG_Py_DECREF(tuple);\n");
+ Printf(f, " return result;\n");
+ Printf(f, "}\n\n");
+
+ // Methods
+ Printf(f, "SWIGINTERN PyMethodDef %s_methods[] = {\n", templ);
+ Dump(builtin_methods, f);
+ Printf(f, " { NULL, NULL, 0, NULL } /* Sentinel */\n};\n\n");
+
+ // No instance dict for nondynamic objects
+ if (GetFlag(n, "feature:python:nondynamic"))
+ Setattr(n, "feature:python:tp_setattro", "SWIG_Python_NonDynamicSetAttr");
+
+ Node *mod = Getattr(n, "module");
+ String *modname = mod ? Getattr(mod, "name") : 0;
+ String *quoted_symname;
+ if (package) {
+ if (modname)
+ quoted_symname = NewStringf("\"%s.%s.%s\"", package, modname, symname);
+ else
+ quoted_symname = NewStringf("\"%s.%s\"", package, symname);
+ } else {
+ if (modname)
+ quoted_symname = NewStringf("\"%s.%s\"", modname, symname);
+ else
+ quoted_symname = NewStringf("\"%s\"", symname);
+ }
+ String *quoted_tp_doc_str = NewStringf("\"%s\"", getSlot(n, "feature:python:tp_doc"));
+ String *tp_init = NewString(builtin_tp_init ? Char(builtin_tp_init) : Swig_directorclass(n) ? "0" : "SwigPyBuiltin_BadInit");
+ String *tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES");
+ String *tp_flags_py3 = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE");
+
+ static String *tp_basicsize = NewStringf("sizeof(SwigPyObject)");
+ static String *tp_dictoffset_default = NewString("offsetof(SwigPyObject, dict)");
+ static String *tp_hash = NewString("SwigPyObject_hash");
+ static String *tp_new = NewString("PyType_GenericNew");
+ String *tp_as_number = NewStringf("&%s_type.as_number", templ);
+ String *tp_as_sequence = NewStringf("&%s_type.as_sequence", templ);
+ String *tp_as_mapping = NewStringf("&%s_type.as_mapping", templ);
+ String *tp_as_buffer = NewStringf("&%s_type.as_buffer", templ);
+
+ Printv(f, "#ifndef SWIG_HEAPTYPES\n", NIL);
+ Printf(f, "static PyHeapTypeObject %s_type = {\n", templ);
+
+ // PyTypeObject ht_type
+ Printf(f, " {\n");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ Printv(f, " PyVarObject_HEAD_INIT(NULL, 0)\n", NIL);
+ Printv(f, "#else\n", NIL);
+ Printf(f, " PyObject_HEAD_INIT(NULL)\n");
+ printSlot(f, getSlot(), "ob_size");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, quoted_symname, "tp_name");
+ printSlot(f, getSlot(n, "feature:python:tp_basicsize", tp_basicsize), "tp_basicsize");
+ printSlot(f, getSlot(n, "feature:python:tp_itemsize"), "tp_itemsize");
+ printSlot(f, getSlot(n, "feature:python:tp_dealloc", tp_dealloc_bad), "tp_dealloc", "destructor");
+ Printv(f, "#if PY_VERSION_HEX < 0x030800b4\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_print"), "tp_print", "printfunc");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_vectorcall_offset"), "tp_vectorcall_offset", "Py_ssize_t");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_getattr"), "tp_getattr", "getattrfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_setattr"), "tp_setattr", "setattrfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare", "cmpfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_repr"), "tp_repr", "reprfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_as_number", tp_as_number), "tp_as_number");
+ printSlot(f, getSlot(n, "feature:python:tp_as_sequence", tp_as_sequence), "tp_as_sequence");
+ printSlot(f, getSlot(n, "feature:python:tp_as_mapping", tp_as_mapping), "tp_as_mapping");
+ printSlot(f, getSlot(n, "feature:python:tp_hash", tp_hash), "tp_hash", "hashfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc");
+ printSlot(f, getSlot(n, "feature:python:tp_setattro"), "tp_setattro", "setattrofunc");
+ printSlot(f, getSlot(n, "feature:python:tp_as_buffer", tp_as_buffer), "tp_as_buffer");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags_py3), "tp_flags");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags), "tp_flags");
+ Printv(f, "#endif\n", NIL);
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_CLASS);
+ String *tp_doc = NewString("");
+ Printf(tp_doc, "\"%s\"", ds);
+ Delete(ds);
+ printSlot(f, tp_doc, "tp_doc");
+ Delete(tp_doc);
+ } else {
+ printSlot(f, quoted_tp_doc_str, "tp_doc");
+ }
+ printSlot(f, getSlot(n, "feature:python:tp_traverse"), "tp_traverse", "traverseproc");
+ printSlot(f, getSlot(n, "feature:python:tp_clear"), "tp_clear", "inquiry");
+ printSlot(f, getSlot(n, "feature:python:tp_richcompare", richcompare_func), "tp_richcompare", "richcmpfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_weaklistoffset"), "tp_weaklistoffset");
+ printSlot(f, getSlot(n, "feature:python:tp_iter"), "tp_iter", "getiterfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_iternext"), "tp_iternext", "iternextfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_methods", methods_name), "tp_methods");
+ printSlot(f, getSlot(n, "feature:python:tp_members"), "tp_members");
+ printSlot(f, getSlot(n, "feature:python:tp_getset", getset_name), "tp_getset");
+ printSlot(f, getSlot(n, "feature:python:tp_base"), "tp_base");
+ printSlot(f, getSlot(n, "feature:python:tp_dict"), "tp_dict");
+ printSlot(f, getSlot(n, "feature:python:tp_descr_get"), "tp_descr_get", "descrgetfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_descr_set"), "tp_descr_set", "descrsetfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_dictoffset", tp_dictoffset_default), "tp_dictoffset", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_init", tp_init), "tp_init", "initproc");
+ printSlot(f, getSlot(n, "feature:python:tp_alloc"), "tp_alloc", "allocfunc");
+ printSlot(f, getSlot(), "tp_new", "newfunc");
+ printSlot(f, getSlot(n, "feature:python:tp_free"), "tp_free", "freefunc");
+ printSlot(f, getSlot(n, "feature:python:tp_is_gc"), "tp_is_gc", "inquiry");
+ printSlot(f, getSlot(n, "feature:python:tp_bases"), "tp_bases", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_mro"), "tp_mro", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_cache"), "tp_cache", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_subclasses"), "tp_subclasses", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_weaklist"), "tp_weaklist", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:tp_del"), "tp_del", "destructor");
+ printSlot(f, getSlot(n, "feature:python:tp_version_tag"), "tp_version_tag", "int");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03040000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_finalize"), "tp_finalize", "destructor");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if PY_VERSION_HEX >= 0x03080000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_vectorcall"), "tp_vectorcall", "vectorcallfunc");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if (PY_VERSION_HEX >= 0x03080000) && (PY_VERSION_HEX < 0x03090000)\n", NIL);
+ printSlot(f, getSlot(), "tp_print");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if PY_VERSION_HEX >= 0x030c0000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_watched"), "tp_watched", "unsigned char");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if PY_VERSION_HEX >= 0x030d00a4\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_versions_used"), "tp_versions_used", "uint16_t");
+ Printv(f, "#endif\n", NIL);
+
+ Printv(f, "#ifdef COUNT_ALLOCS\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:tp_allocs"), "tp_allocs", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_frees"), "tp_frees", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_maxalloc"), "tp_maxalloc", "Py_ssize_t");
+ printSlot(f, getSlot(n, "feature:python:tp_prev"), "tp_prev");
+ printSlot(f, getSlot(n, "feature:python:tp_next"), "tp_next");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, " },\n");
+
+ // PyAsyncMethods as_async
+ Printv(f, "#if PY_VERSION_HEX >= 0x03050000\n", NIL);
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:am_await"), "am_await", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:am_aiter"), "am_aiter", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:am_anext"), "am_anext", "unaryfunc");
+ Printv(f, "# if PY_VERSION_HEX >= 0x030a0000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:am_send"), "am_send", "sendfunc");
+ Printv(f, "# endif\n", NIL);
+ Printf(f, " },\n");
+ Printv(f, "#endif\n", NIL);
+
+ // PyNumberMethods as_number
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:nb_add"), "nb_add", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_subtract"), "nb_subtract", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_multiply"), "nb_multiply", "binaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_divide", "binaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_remainder"), "nb_remainder", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_divmod"), "nb_divmod", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_power"), "nb_power", "ternaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_negative"), "nb_negative", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_positive"), "nb_positive", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_absolute"), "nb_absolute", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_nonzero"), "nb_nonzero", "inquiry");
+ printSlot(f, getSlot(n, "feature:python:nb_invert"), "nb_invert", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_lshift"), "nb_lshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_rshift"), "nb_rshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_and"), "nb_and", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_xor"), "nb_xor", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_or"), "nb_or", "binaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_coerce"), "nb_coerce", "coercion");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_int"), "nb_int", "unaryfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_reserved"), "nb_reserved", "void *");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_long"), "nb_long", "unaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_float"), "nb_float", "unaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_oct"), "nb_oct", "unaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_hex"), "nb_hex", "unaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_add"), "nb_inplace_add", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_subtract"), "nb_inplace_subtract", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_multiply"), "nb_inplace_multiply", "binaryfunc");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_divide", "binaryfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_remainder"), "nb_inplace_remainder", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_power"), "nb_inplace_power", "ternaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_lshift"), "nb_inplace_lshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_rshift"), "nb_inplace_rshift", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_and"), "nb_inplace_and", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_xor"), "nb_inplace_xor", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_or"), "nb_inplace_or", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_floor_divide"), "nb_floor_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_true_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_floor_divide"), "nb_inplace_floor_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_true_divide", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_index"), "nb_index", "unaryfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03050000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:nb_matrix_multiply"), "nb_matrix_multiply", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:nb_inplace_matrix_multiply"), "nb_inplace_matrix_multiply", "binaryfunc");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, " },\n");
+
+ // PyMappingMethods as_mapping;
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:mp_length"), "mp_length", "lenfunc");
+ printSlot(f, getSlot(n, "feature:python:mp_subscript"), "mp_subscript", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:mp_ass_subscript"), "mp_ass_subscript", "objobjargproc");
+ Printf(f, " },\n");
+
+ // PySequenceMethods as_sequence;
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:sq_length"), "sq_length", "lenfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_concat"), "sq_concat", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_repeat"), "sq_repeat", "ssizeargfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_item"), "sq_item", "ssizeargfunc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:was_sq_slice"), "was_sq_slice", "void *");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_slice"), "sq_slice", "ssizessizeargfunc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_ass_item"), "sq_ass_item", "ssizeobjargproc");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:was_sq_ass_slice"), "was_sq_ass_slice", "void *");
+ Printv(f, "#else\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_ass_slice"), "sq_ass_slice", "ssizessizeobjargproc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:sq_contains"), "sq_contains", "objobjproc");
+ printSlot(f, getSlot(n, "feature:python:sq_inplace_concat"), "sq_inplace_concat", "binaryfunc");
+ printSlot(f, getSlot(n, "feature:python:sq_inplace_repeat"), "sq_inplace_repeat", "ssizeargfunc");
+ Printf(f, " },\n");
+
+ // PyBufferProcs as_buffer;
+ Printf(f, " {\n");
+ Printv(f, "#if PY_VERSION_HEX < 0x03000000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:bf_getreadbuffer"), "bf_getreadbuffer", "readbufferproc");
+ printSlot(f, getSlot(n, "feature:python:bf_getwritebuffer"), "bf_getwritebuffer", "writebufferproc");
+ printSlot(f, getSlot(n, "feature:python:bf_getsegcount"), "bf_getsegcount", "segcountproc");
+ printSlot(f, getSlot(n, "feature:python:bf_getcharbuffer"), "bf_getcharbuffer", "charbufferproc");
+ Printv(f, "#endif\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:bf_getbuffer"), "bf_getbuffer", "getbufferproc");
+ printSlot(f, getSlot(n, "feature:python:bf_releasebuffer"), "bf_releasebuffer", "releasebufferproc");
+ Printf(f, " },\n");
+
+ // PyObject *ht_name, *ht_slots, *ht_qualname;
+ printSlot(f, getSlot(n, "feature:python:ht_name"), "ht_name", "PyObject *");
+ printSlot(f, getSlot(n, "feature:python:ht_slots"), "ht_slots", "PyObject *");
+ Printv(f, "#if PY_VERSION_HEX >= 0x03030000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:ht_qualname"), "ht_qualname", "PyObject *");
+
+ // struct _dictkeysobject *ht_cached_keys;
+ printSlot(f, getSlot(n, "feature:python:ht_cached_keys"), "ht_cached_keys");
+ Printv(f, "#endif\n", NIL);
+
+ // PyObject *ht_module;
+ Printv(f, "#if PY_VERSION_HEX >= 0x03090000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:ht_module"), "ht_module", "PyObject *");
+ Printv(f, "#endif\n", NIL);
+
+ // char *_ht_tpname;
+ Printv(f, "#if PY_VERSION_HEX >= 0x030b0000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:_ht_tpname"), "_ht_tpname", "char *");
+
+ // struct _specialization_cache _spec_cache;
+ Printf(f, " {\n");
+ printSlot(f, getSlot(n, "feature:python:getitem"), "getitem", "PyObject *");
+ Printv(f, "#if PY_VERSION_HEX >= 0x030c0000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:getitem_version"), "getitem_version", "uint32_t");
+ Printv(f, "#endif\n", NIL);
+ Printv(f, "#if PY_VERSION_HEX >= 0x030d0000\n", NIL);
+ printSlot(f, getSlot(n, "feature:python:init"), "init", "PyObject *");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, " }\n");
+ Printv(f, "#endif\n", NIL);
+ Printf(f, "};\n\n");
+ Printf(f, "static PyTypeObject *%s_type_create(PyTypeObject *type, PyTypeObject **bases, PyObject *dict) {\n", templ);
+ Printv(f, " PyObject *tuple_bases;\n", NIL);
+ Printf(f, " PyTypeObject *pytype = (PyTypeObject *)&%s_type;\n", templ);
+ Printf(f, " pytype->tp_dict = dict;\n");
+ Printv(f, " SwigPyBuiltin_SetMetaType(pytype, type);\n", NIL);
+ Printf(f, " pytype->tp_new = %s;\n", getSlot(n, "feature:python:tp_new", tp_new));
+ Printv(f, " tuple_bases = SwigPyBuiltin_InitBases(bases);\n", NIL);
+ Printv(f, " pytype->tp_base = bases[0];\n", NIL);
+ Printv(f, " SWIG_Py_INCREF(pytype->tp_base);\n", NIL);
+ Printv(f, " pytype->tp_bases = tuple_bases;\n", NIL);
+ Printv(f, " if (PyType_Ready(pytype) < 0) {\n", NIL);
+ Printf(f, " PyErr_SetString(PyExc_TypeError, \"Could not create type '%s'.\");\n", symname);
+ Printv(f, " return NULL;\n", NIL);
+ Printv(f, " }\n", NIL);
+ Printf(f, " return pytype;\n");
+ Printf(f, "}\n\n");
+
+ Printv(f, "#else\n", NIL);
+
+ Printf(f, "static PyTypeObject *%s_type_create(PyTypeObject *type, PyTypeObject **bases, PyObject *dict) {\n", templ);
+ Printf(f, " PyMemberDef members[] = {\n");
+ Printf(f, " { (char *)\"__dictoffset__\", Py_T_PYSSIZET, %s, Py_READONLY, NULL },\n", getSlot(n, "feature:python:tp_dictoffset", tp_dictoffset_default));
+ Printf(f, " { NULL, 0, 0, 0, NULL }\n");
+ Printf(f, " };\n");
+ Printf(f, " PyType_Slot slots[] = {\n");
+ printSlot2(f, getSlot(n, "feature:python:tp_init", tp_init), "tp_init", "initproc");
+ printSlot2(f, getSlot(n, "feature:python:tp_dealloc", tp_dealloc_bad), "tp_dealloc", "destructor");
+ printSlot2(f, getSlot(n, "feature:python:tp_alloc"), "tp_alloc", "allocfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_free"), "tp_free", "freefunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_is_gc"), "tp_is_gc", "inquiry");
+ printSlot2(f, getSlot(n, "feature:python:tp_del"), "tp_del", "destructor");
+
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_CLASS);
+ String *tp_doc = NewString("");
+ Printf(tp_doc, "\"%s\"", ds);
+ Delete(ds);
+ printSlot2(f, tp_doc, "tp_doc");
+ Delete(tp_doc);
+ } else {
+ printSlot2(f, quoted_tp_doc_str, "tp_doc");
+ }
+ printSlot2(f, getSlot(n, "feature:python:tp_repr"), "tp_repr", "reprfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_traverse"), "tp_traverse", "traverseproc");
+ printSlot2(f, getSlot(n, "feature:python:tp_clear"), "tp_clear", "inquiry");
+ printSlot2(f, getSlot(n, "feature:python:tp_richcompare", richcompare_func), "tp_richcompare", "richcmpfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_methods", methods_name), "tp_methods");
+ printSlot2(f, getSlot(n, "feature:python:tp_getset", getset_name), "tp_getset");
+ printSlot2(f, getSlot(n, "feature:python:tp_hash", tp_hash), "tp_hash", "hashfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_setattro"), "tp_setattro", "setattrofunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_descr_get"), "tp_descr_get", "descrgetfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_descr_set"), "tp_descr_set", "descrsetfunc");
+ printSlot2(f, getSlot(n, "feature:python:mp_length"), "mp_length", "lenfunc");
+ printSlot2(f, getSlot(n, "feature:python:mp_subscript"), "mp_subscript", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:mp_ass_subscript"), "mp_ass_subscript", "objobjargproc");
+ printSlot2(f, getSlot(n, "feature:python:tp_iter"), "tp_iter", "getiterfunc");
+ printSlot2(f, getSlot(n, "feature:python:tp_iternext"), "tp_iternext", "iternextfunc");
+ //
+ // nb_* slots
+ printSlot2(f, getSlot(n, "feature:python:nb_add"), "nb_add", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_subtract"), "nb_subtract", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_multiply"), "nb_multiply", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_remainder"), "nb_remainder", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_divmod"), "nb_divmod", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_power"), "nb_power", "ternaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_negative"), "nb_negative", "unaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_positive"), "nb_positive", "unaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_absolute"), "nb_absolute", "unaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_nonzero"), "nb_bool", "inquiry");
+ printSlot2(f, getSlot(n, "feature:python:nb_invert"), "nb_invert", "unaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_lshift"), "nb_lshift", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_rshift"), "nb_rshift", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_and"), "nb_and", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_xor"), "nb_xor", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_or"), "nb_or", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_int"), "nb_int", "unaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_float"), "nb_float", "unaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_add"), "nb_inplace_add", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_subtract"), "nb_inplace_subtract", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_multiply"), "nb_inplace_multiply", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_remainder"), "nb_inplace_remainder", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_power"), "nb_inplace_power", "ternaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_lshift"), "nb_inplace_lshift", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_rshift"), "nb_inplace_rshift", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_and"), "nb_inplace_and", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_xor"), "nb_inplace_xor", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_or"), "nb_inplace_or", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_floor_divide"), "nb_floor_divide", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_divide"), "nb_true_divide", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_floor_divide"), "nb_inplace_floor_divide", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_true_divide", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:nb_index"), "nb_index", "unaryfunc");
+
+ // sequence
+ printSlot2(f, getSlot(n, "feature:python:sq_length"), "sq_length", "lenfunc");
+ printSlot2(f, getSlot(n, "feature:python:sq_concat"), "sq_concat", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:sq_repeat"), "sq_repeat", "ssizeargfunc");
+ printSlot2(f, getSlot(n, "feature:python:sq_item"), "sq_item", "ssizeargfunc");
+ printSlot2(f, getSlot(n, "feature:python:sq_ass_item"), "sq_ass_item", "ssizeobjargproc");
+ printSlot2(f, getSlot(n, "feature:python:sq_contains"), "sq_contains", "objobjproc");
+ printSlot2(f, getSlot(n, "feature:python:sq_inplace_concat"), "sq_inplace_concat", "binaryfunc");
+ printSlot2(f, getSlot(n, "feature:python:sq_inplace_repeat"), "sq_inplace_repeat", "ssizeargfunc");
+
+ Printf(f, " { Py_tp_members, members },\n");
+ Printf(f, " { 0, NULL }\n");
+ Printf(f, " };\n");
+ Printf(f, " PyType_Spec spec = {\n");
+ Printf(f, " %s,\n", quoted_symname);
+ Printf(f, " sizeof(SwigPyObject),\n");
+ Printf(f, " 0,\n");
+ Printf(f, " %s,\n", getSlot(n, "feature:python:tp_flags", tp_flags_py3), "tp_flags");
+ Printf(f, " slots\n");
+ Printf(f, " };\n");
+ Printv(f, " PyObject *tuple_bases = SwigPyBuiltin_InitBases(bases);\n", NIL);
+ Printf(f, " PyTypeObject *pytype = (PyTypeObject*)PyType_FromSpecWithBases(&spec, tuple_bases);\n");
+ Printf(f, " PyDict_Merge(pytype->tp_dict, dict, 1);\n");
+ Printv(f, " SwigPyBuiltin_SetMetaType(pytype, type);\n", NIL);
+ Printf(f, " PyType_Modified(pytype);\n");
+ Printf(f, " Py_DECREF(dict);\n");
+ Printf(f, " return pytype;\n");
+
+ Printv(f, "}\n", NULL);
+
+ Printv(f, "#endif\n", NIL);
+
+ String *clientdata = NewString("");
+ Printf(clientdata, "&%s_clientdata", templ);
+ SwigType_remember_mangleddata(pmname, clientdata);
+
+ SwigType *smart = Getattr(n, "smart");
+ if (smart) {
+ SwigType *psmart = Copy(smart);
+ SwigType_add_pointer(psmart);
+ String *smart_pmname = SwigType_manglestr(psmart);
+ SwigType_remember_mangleddata(smart_pmname, clientdata);
+ Delete(smart_pmname);
+ Delete(psmart);
+ }
+
+ Printf(f, "SWIGINTERN SwigPyClientData %s_clientdata = {0, 0, 0, 0, 0, 0, 0};\n\n", templ);
+
+ Printf(f_init, " builtin_pytype = %s_type_create(metatype, builtin_bases, d);\n", templ);
+ Printf(f_init, " if(!builtin_pytype) {\n", templ);
+ Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL);
+ Printv(f_init, " return NULL;\n", NIL);
+ Printv(f_init, "#else\n", NIL);
+ Printv(f_init, " return;\n", NIL);
+ Printv(f_init, "#endif\n", NIL);
+ Printv(f_init, " }\n", NIL);
+ Printf(f_init, " SwigPyBuiltin_%s_clientdata.pytype = builtin_pytype;\n", mname);
+ if (GetFlag(n, "feature:implicitconv")) {
+ Printf(f_init, " SwigPyBuiltin_%s_clientdata.klass = (PyObject *)builtin_pytype;\n", mname);
+ }
+ Printv(f_init, " SWIG_Py_INCREF((PyObject *)builtin_pytype);\n", NIL);
+ Printf(f_init, " PyModule_AddObject(m, \"%s\", (PyObject *)builtin_pytype);\n", symname);
+ Printf(f_init, " SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", symname);
+ Printv(f_init, " d = md;\n", NIL);
+
+ Delete(clientdata);
+ Delete(sname);
+ Delete(rname);
+ Delete(mname);
+ Delete(pname);
+ Delete(pmname);
+ Delete(templ);
+ Delete(tp_flags);
+ Delete(tp_flags_py3);
+ Delete(tp_as_buffer);
+ Delete(tp_as_mapping);
+ Delete(tp_as_sequence);
+ Delete(tp_as_number);
+ Delete(quoted_symname);
+ Delete(quoted_tp_doc_str);
+ Delete(tp_init);
+ Delete(richcompare_func);
+ Delete(getset_name);
+ Delete(methods_name);
+ }
+
+ virtual int classHandler(Node *n) {
+ File *f_shadow_file = f_shadow;
+ Node *base_node = NULL;
+
+ if (shadow) {
+
+ /* Create new strings for building up a wrapper function */
+ have_constructor = 0;
+ have_repr = 0;
+ have_builtin_static_member_method_callback = false;
+
+ class_name = Getattr(n, "sym:name");
+ real_classname = Getattr(n, "name");
+
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ if (builtin) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist) > 0) {
+ Iterator b = First(baselist);
+ base_node = b.item;
+ }
+ }
+
+ shadow_indent = (String *) tab4;
+
+ /* Handle inheritance */
+ String *base_class = NewString("");
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ b = First(baselist);
+ while (b.item) {
+ String *bname = Getattr(b.item, "python:proxy");
+ bool ignore = GetFlag(b.item, "feature:ignore") ? true : false;
+ if (!bname || ignore) {
+ if (!bname && !ignore) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(n), Getline(n),
+ "Base class '%s' ignored - unknown module name for base. Either import the appropriate module interface file or specify the name of the module in the %%import directive.\n",
+ SwigType_namestr(Getattr(b.item, "name")));
+ }
+ b = Next(b);
+ continue;
+ }
+ Printv(base_class, bname, NIL);
+ b = Next(b);
+ if (b.item) {
+ Printv(base_class, ", ", NIL);
+ }
+ }
+ }
+
+ if (builtin) {
+ Hash *base_richcompare = NULL;
+ Hash *richcompare = NULL;
+ if (base_node)
+ base_richcompare = Getattr(base_node, "python:richcompare");
+ if (base_richcompare)
+ richcompare = Copy(base_richcompare);
+ else
+ richcompare = NewHash();
+ Setattr(n, "python:richcompare", richcompare);
+ }
+
+ /* dealing with abstract base class */
+ String *abcs = Getattr(n, "feature:python:abc");
+ if (abcs) {
+ if (Len(base_class) > 0)
+ Printv(base_class, ", ", NIL);
+ Printv(base_class, abcs, NIL);
+ }
+
+ if (builtin) {
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_CLASS);
+ Setattr(n, "feature:python:tp_doc", ds);
+ Delete(ds);
+ } else {
+ SwigType *name = Getattr(n, "name");
+ SwigType *sname = add_explicit_scope(name);
+ String *rname = SwigType_namestr(sname);
+ Setattr(n, "feature:python:tp_doc", rname);
+ Delete(sname);
+ Delete(rname);
+ }
+ } else {
+ if (GetFlag(n, "feature:python:nondynamic"))
+ Printv(f_shadow, "@_swig_add_metaclass(_SwigNonDynamicMeta)\n", NIL);
+ Printv(f_shadow, "class ", class_name, NIL);
+
+ if (Len(base_class)) {
+ Printf(f_shadow, "(%s)", base_class);
+ } else {
+ if (GetFlag(n, "feature:exceptionclass")) {
+ Printf(f_shadow, "(Exception)");
+ } else {
+ Printf(f_shadow, "(object");
+ /* Replace @_swig_add_metaclass above with below when support for python 2.7 is dropped
+ if (GetFlag(n, "feature:python:nondynamic")) {
+ Printf(f_shadow, ", metaclass=_SwigNonDynamicMeta");
+ }
+ */
+ Printf(f_shadow, ")");
+ }
+ }
+
+ Printf(f_shadow, ":\n");
+
+ // write docstrings if requested
+ if (have_docstring(n)) {
+ String *str = docstring(n, AUTODOC_CLASS, tab4);
+ if (str && Len(str))
+ Printv(f_shadow, tab4, str, "\n\n", NIL);
+ }
+
+ Printv(f_shadow, tab4, "thisown = property(lambda x: x.this.own(), ", "lambda x, v: x.this.own(v), doc=\"The membership flag\")\n", NIL);
+ /* Add static attribute */
+ if (GetFlag(n, "feature:python:nondynamic")) {
+ Printv(f_shadow_file, tab4, "__setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)\n", NIL);
+ }
+ }
+ }
+
+ /* Emit all of the members */
+
+ in_class = 1;
+ if (builtin)
+ builtin_pre_decl(n);
+
+ /* Override the shadow file so we can capture its methods */
+ f_shadow = NewString("");
+
+ // Set up type check for director class constructor
+ Clear(none_comparison);
+ if (builtin && Swig_directorclass(n)) {
+ String *p_real_classname = Copy(real_classname);
+ SwigType_add_pointer(p_real_classname);
+ String *mangle = SwigType_manglestr(p_real_classname);
+ String *descriptor = NewStringf("SWIGTYPE%s", mangle);
+ Printv(none_comparison, "self->ob_type != ((SwigPyClientData *)(", descriptor, ")->clientdata)->pytype", NIL);
+ Delete(descriptor);
+ Delete(mangle);
+ Delete(p_real_classname);
+ } else {
+ Printv(none_comparison, "$arg != Py_None", NIL);
+ }
+
+ Language::classHandler(n);
+
+ in_class = 0;
+
+ /* Complete the class */
+ if (shadow) {
+ /* Generate a class registration function */
+ // Replace storing a pointer to underlying class with a smart pointer (intended for use with non-intrusive smart pointers)
+ SwigType *smart = Getattr(n, "smart");
+ SwigType *ct = Copy(smart ? smart : real_classname);
+ SwigType_add_pointer(ct);
+ SwigType *realct = Copy(real_classname);
+ SwigType_add_pointer(realct);
+ SwigType_remember(realct);
+ if (builtin) {
+ Printv(f_wrappers, builtin_closures_code, NIL);
+ Delete(builtin_closures_code);
+ builtin_closures_code = NewString("");
+ Clear(builtin_closures);
+ } else {
+ Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
+ Printv(f_wrappers, " PyObject *obj = NULL;\n", NIL);
+ Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args, \"swigregister\", 1, 1, &obj)) return NULL;\n", NIL);
+
+ Printv(f_wrappers,
+ " SWIG_TypeNewClientData(SWIGTYPE", SwigType_manglestr(ct), ", SWIG_NewClientData(obj));\n", " return SWIG_Py_Void();\n", "}\n\n", NIL);
+ String *cname = NewStringf("%s_swigregister", class_name);
+ add_method(cname, cname, 0, 0, 1, 1, 1);
+ Delete(cname);
+ }
+ Delete(ct);
+ Delete(realct);
+ if (!have_constructor) {
+ if (!builtin)
+ Printv(f_shadow_file, "\n", tab4, "def __init__(self, *args, **kwargs):\n", tab8, "raise AttributeError(\"", "No constructor defined",
+ (Getattr(n, "abstracts") ? " - class is abstract" : ""), "\")\n", NIL);
+ } else if (!builtin) {
+
+ Printv(f_wrappers, "SWIGINTERN PyObject *", class_name, "_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {\n", NIL);
+ Printv(f_wrappers, " return SWIG_Python_InitShadowInstance(args);\n", "}\n\n", NIL);
+ String *cname = NewStringf("%s_swiginit", class_name);
+ add_method(cname, cname, 0);
+ Delete(cname);
+ }
+ if (!have_repr && !builtin) {
+ /* Supply a repr method for this class */
+ String *rname = SwigType_namestr(real_classname);
+ Printv(f_shadow_file, tab4, "__repr__ = _swig_repr\n", NIL);
+ Delete(rname);
+ }
+
+ if (builtin)
+ builtin_post_decl(f_builtins, n);
+
+ if (builtin_tp_init) {
+ Delete(builtin_tp_init);
+ builtin_tp_init = 0;
+ }
+
+ if (!builtin) {
+ /* Now emit methods */
+ Printv(f_shadow_file, f_shadow, NIL);
+ Printf(f_shadow_file, "\n");
+ Printf(f_shadow_file, "# Register %s in %s:\n", class_name, module);
+ Printf(f_shadow_file, "%s.%s_swigregister(%s)\n", module, class_name, class_name);
+ }
+
+ shadow_indent = 0;
+ if (Len(f_shadow_stubs) > 0)
+ Printf(f_shadow_file, "%s\n", f_shadow_stubs);
+ Clear(f_shadow_stubs);
+ }
+
+ if (builtin) {
+ Clear(class_members);
+ Clear(builtin_getset);
+ Clear(builtin_methods);
+ }
+
+ /* Restore shadow file back to original version */
+ Delete(f_shadow);
+ f_shadow = f_shadow_file;
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionHandler() - Mainly overloaded for callback handling
+ * ------------------------------------------------------------ */
+
+ virtual int functionHandler(Node *n) {
+ String *pcb = GetFlagAttr(n, "feature:python:callback");
+ if (pcb) {
+ if (Strcmp(pcb, "1") == 0) {
+ SetFlagAttr(n, "feature:callback", "%s_cb_ptr");
+ } else {
+ SetFlagAttr(n, "feature:callback", pcb);
+ }
+ autodoc_l dlevel = autodoc_level(Getattr(n, "feature:autodoc"));
+ if (dlevel != NO_AUTODOC && dlevel > TYPES_AUTODOC) {
+ Setattr(n, "feature:autodoc", "1");
+ }
+ }
+ return Language::functionHandler(n);
+ }
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow;
+
+ if (builtin)
+ Swig_save("builtin_memberfunc", n, "python:argcount", NIL);
+
+ /* Create the default member function */
+ oldshadow = shadow; /* Disable shadowing when wrapping member functions */
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::memberfunctionHandler(n);
+ shadow = oldshadow;
+
+ if (builtin && in_class) {
+ // Can't use checkAttribute(n, "access", "public") because
+ // "access" attr isn't set on %extend methods
+ if (!checkAttribute(n, "access", "private") && strncmp(Char(symname), "operator ", 9) && !Getattr(class_members, symname)) {
+ String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *wname = Swig_name_wrapper(fullname);
+ Setattr(class_members, symname, n);
+ int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2;
+ String *ds = have_docstring(n) ? cdocstring(n, AUTODOC_METHOD) : NewString("");
+ if (check_kwargs(n)) {
+ // Cast via void(*)(void) to suppress GCC -Wcast-function-type
+ // warning. Python should always call the function correctly, but
+ // the Python C API requires us to store it in function pointer of a
+ // different type.
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, METH_VARARGS|METH_KEYWORDS, \"%s\" },\n", symname, wname, ds);
+ } else if (argcount == 0) {
+ Printf(builtin_methods, " { \"%s\", %s, METH_NOARGS, \"%s\" },\n", symname, wname, ds);
+ } else if (argcount == 1) {
+ Printf(builtin_methods, " { \"%s\", %s, METH_O, \"%s\" },\n", symname, wname, ds);
+ } else {
+ Printf(builtin_methods, " { \"%s\", %s, METH_VARARGS, \"%s\" },\n", symname, wname, ds);
+ }
+ Delete(fullname);
+ Delete(wname);
+ Delete(ds);
+ }
+ }
+
+ if (builtin)
+ Swig_restore(n);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ if (shadow && !builtin) {
+ int fproxy = fastproxy;
+ String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ if (Strcmp(symname, "__repr__") == 0) {
+ have_repr = 1;
+ }
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, fullname);
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ fproxy = 0;
+ } else {
+ int allow_kwargs = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, true, true, allow_kwargs);
+ if (!have_addtofunc(n)) {
+ if (!fastproxy || olddefs) {
+ Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (Node *node_with_doc = find_overload_with_docstring(n))
+ Printv(f_shadow, tab8, docstring(node_with_doc, AUTODOC_METHOD, tab8), "\n", NIL);
+ Printv(f_shadow, tab8, "return ", funcCall(fullname, callParms), "\n", NIL);
+ }
+ } else {
+ Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (Node *node_with_doc = find_overload_with_docstring(n))
+ Printv(f_shadow, tab8, docstring(node_with_doc, AUTODOC_METHOD, tab8), "\n", NIL);
+ if (have_pythonprepend(n)) {
+ fproxy = 0;
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ }
+ if (have_pythonappend(n)) {
+ fproxy = 0;
+ Printv(f_shadow, tab8, "val = ", funcCall(fullname, callParms), "\n", NIL);
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow, tab8, "return val\n\n", NIL);
+ } else {
+ Printv(f_shadow, tab8, "return ", funcCall(fullname, callParms), "\n\n", NIL);
+ }
+ }
+ }
+ if (fproxy) {
+ Printf(f_shadow, tab4);
+ Printf(f_shadow, "%s = _swig_new_instance_method(%s.%s)\n", symname, module, Swig_name_member(NSPACE_TODO, class_name, symname));
+ }
+ Delete(fullname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (builtin && in_class) {
+ Swig_save("builtin_memberconstantHandler", n, "pybuiltin:symname", NIL);
+ Setattr(n, "pybuiltin:symname", symname);
+ }
+ Language::staticmemberfunctionHandler(n);
+ if (builtin && in_class) {
+ Swig_restore(n);
+ }
+
+ int kw = (check_kwargs(n) && !Getattr(n, "sym:overloaded")) ? 1 : 0;
+ if (builtin && in_class) {
+ if ((GetFlagAttr(n, "feature:extend") || checkAttribute(n, "access", "public"))
+ && !Getattr(class_members, symname)) {
+ String *fullname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *wname = Swig_name_wrapper(fullname);
+ Setattr(class_members, symname, n);
+ int funpack = fastunpack && !Getattr(n, "sym:overloaded");
+ String *pyflags = NewString("METH_STATIC|");
+ int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2;
+ if (funpack && argcount == 0)
+ Append(pyflags, "METH_NOARGS");
+ else if (funpack && argcount == 1)
+ Append(pyflags, "METH_O");
+ else
+ Append(pyflags, kw ? "METH_VARARGS|METH_KEYWORDS" : "METH_VARARGS");
+ // Cast via void(*)(void) to suppress GCC -Wcast-function-type warning.
+ // Python should always call the function correctly, but the Python C
+ // API requires us to store it in function pointer of a different type.
+ if (have_docstring(n)) {
+ String *ds = cdocstring(n, AUTODOC_STATICFUNC);
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds);
+ Delete(ds);
+ } else if (Getattr(n, "feature:callback")) {
+ String *ds = NewStringf("swig_ptr: %s", Getattr(n, "feature:callback:name"));
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"%s\" },\n", symname, wname, pyflags, ds);
+ Delete(ds);
+ have_builtin_static_member_method_callback = true;
+ } else {
+ Printf(builtin_methods, " { \"%s\", (PyCFunction)(void(*)(void))%s, %s, \"\" },\n", symname, wname, pyflags);
+ }
+ Delete(fullname);
+ Delete(wname);
+ Delete(pyflags);
+ }
+ return SWIG_OK;
+ }
+
+ if (Getattr(n, "sym:nextSibling")) {
+ return SWIG_OK;
+ }
+
+ if (shadow) {
+ String *staticfunc_name = NewString(fastproxy ? "_swig_new_static_method" : "staticmethod");
+ bool fast = (fastproxy && !have_addtofunc(n)) || Getattr(n, "feature:callback");
+ if (!fast || olddefs) {
+ String *parms = make_pyParmList(n, false, false, kw);
+ String *callParms = make_pyParmList(n, false, true, kw);
+ Printv(f_shadow, "\n", tab4, "@staticmethod", NIL);
+ Printv(f_shadow, "\n", tab4, "def ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (Node *node_with_doc = find_overload_with_docstring(n))
+ Printv(f_shadow, tab8, docstring(node_with_doc, AUTODOC_STATICFUNC, tab8), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ if (have_pythonappend(n)) {
+ Printv(f_shadow, tab8, "val = ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL);
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow, tab8, "return val\n", NIL);
+ } else {
+ Printv(f_shadow, tab8, "return ", funcCall(Swig_name_member(NSPACE_TODO, class_name, symname), callParms), "\n", NIL);
+ }
+ }
+
+ // Below may result in a 2nd definition of the method when -olddefs is used. The Python interpreter will use the second definition as it overwrites the first.
+ if (fast) {
+ Printv(f_shadow, tab4, symname, " = ", staticfunc_name, "(", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname),
+ ")\n", NIL);
+ }
+ Delete(staticfunc_name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow = shadow;
+ int use_director = Swig_directorclass(n);
+
+ /*
+ * If we're wrapping the constructor of a C++ director class, prepend a new parameter
+ * to receive the scripting language object (e.g. 'self')
+ *
+ */
+ Swig_save("python:constructorHandler", n, "parms", NIL);
+ if (use_director) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("PyObject");
+ SwigType_add_pointer(type);
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "O");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Setattr(n, "hidden", "1");
+ Delete(self);
+ }
+
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::constructorHandler(n);
+ shadow = oldshadow;
+
+ Delattr(n, "wrap:self");
+ Swig_restore(n);
+
+ if (!Getattr(n, "sym:nextSibling")) {
+ if (shadow) {
+ int allow_kwargs = (check_kwargs(n) && (!Getattr(n, "sym:overloaded"))) ? 1 : 0;
+ int handled_as_init = 0;
+ if (!have_constructor) {
+ String *nname = Getattr(n, "sym:name");
+ String *sname = Getattr(getCurrentClass(), "sym:name");
+ String *cname = Swig_name_construct(NSPACE_TODO, sname);
+ handled_as_init = (Strcmp(nname, sname) == 0) || (Strcmp(nname, cname) == 0);
+ Delete(cname);
+ }
+
+ String *subfunc = Swig_name_construct(NSPACE_TODO, symname);
+ if (!have_constructor && handled_as_init) {
+ if (!builtin) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, subfunc);
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ String *pass_self = NewString("");
+ Node *parent = Swig_methodclass(n);
+ String *classname = Swig_class_name(parent);
+ String *rclassname = Swig_class_name(getCurrentClass());
+ assert(rclassname);
+ (void)rclassname;
+
+ String *parms = make_pyParmList(n, true, false, allow_kwargs);
+ /* Pass 'self' only if using director */
+ String *callParms = make_pyParmList(n, false, true, allow_kwargs, true);
+
+ if (use_director) {
+ Insert(callParms, 0, "_self, ");
+ Printv(pass_self, tab8, NIL);
+ Printf(pass_self, "if self.__class__ == %s:\n", classname);
+ //Printv(pass_self, tab8, tab4, "args = (None,) + args\n", tab8, "else:\n", tab8, tab4, "args = (self,) + args\n", NIL);
+ Printv(pass_self, tab8, tab4, "_self = None\n", tab8, "else:\n", tab8, tab4, "_self = self\n", NIL);
+ }
+
+ Printv(f_shadow, "\n", tab4, "def __init__(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (Node *node_with_doc = find_overload_with_docstring(n))
+ Printv(f_shadow, tab8, docstring(node_with_doc, AUTODOC_CTOR, tab8), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ Printv(f_shadow, pass_self, NIL);
+ Printv(f_shadow, tab8, module, ".", class_name, "_swiginit(self, ", funcCall(subfunc, callParms), ")\n", NIL);
+ if (have_pythonappend(n))
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n\n", NIL);
+ Delete(pass_self);
+ }
+ have_constructor = 1;
+ }
+ } else {
+ /* Hmmm. We seem to be creating a different constructor. We're just going to create a
+ function for it. */
+ if (!builtin) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), "", Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, subfunc);
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow_stubs, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ String *parms = make_pyParmList(n, false, false, allow_kwargs);
+ String *callParms = make_pyParmList(n, false, true, allow_kwargs);
+
+ Printv(f_shadow_stubs, "\ndef ", symname, "(", parms, ")", returnTypeAnnotation(n), ":\n", NIL);
+ if (Node *node_with_doc = find_overload_with_docstring(n))
+ Printv(f_shadow_stubs, tab4, docstring(node_with_doc, AUTODOC_CTOR, tab4), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow_stubs, indent_pythoncode(pythonprepend(n), tab4, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "val = ", funcCall(subfunc, callParms), "\n", NIL);
+ if (have_pythonappend(n))
+ Printv(f_shadow_stubs, indent_pythoncode(pythonappend(n), tab4, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow_stubs, tab4, "return val\n", NIL);
+ }
+ } else {
+ Printf(f_shadow_stubs, "%s = %s\n", symname, subfunc);
+ }
+ }
+ Delete(subfunc);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ int oldshadow = shadow;
+
+ if (builtin && in_class) {
+ Node *cls = Swig_methodclass(n);
+ // Use the destructor for the tp_dealloc slot unless a user overrides it with another method
+ if (!Getattr(cls, "feature:python:tp_dealloc")) {
+ Setattr(n, "feature:python:slot", "tp_dealloc");
+ Setattr(n, "feature:python:slot:functype", "destructor");
+ }
+ }
+
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ //Setattr(n,"emit:dealloc","1");
+ Language::destructorHandler(n);
+ shadow = oldshadow;
+
+ if (shadow) {
+ if (Getattr(n, "feature:shadow")) {
+ String *pycode = indent_pythoncode(Getattr(n, "feature:shadow"), tab4, Getfile(n), Getline(n), "%feature(\"shadow\")");
+ String *pyaction = NewStringf("%s.%s", module, Swig_name_destroy(NSPACE_TODO, symname));
+ Replaceall(pycode, "$action", pyaction);
+ Delete(pyaction);
+ Printv(f_shadow, pycode, "\n", NIL);
+ Delete(pycode);
+ } else {
+ Printv(f_shadow, tab4, "__swig_destroy__ = ", module, ".", Swig_name_destroy(NSPACE_TODO, symname), "\n", NIL);
+ if (!have_pythonprepend(n) && !have_pythonappend(n)) {
+ return SWIG_OK;
+ }
+ Printv(f_shadow, tab4, "def __del__(self):\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab8, docstring(n, AUTODOC_DTOR, tab8), "\n", NIL);
+ if (have_pythonprepend(n))
+ Printv(f_shadow, indent_pythoncode(pythonprepend(n), tab8, Getfile(n), Getline(n), "%pythonprepend or %feature(\"pythonprepend\")"), "\n", NIL);
+ if (have_pythonappend(n))
+ Printv(f_shadow, indent_pythoncode(pythonappend(n), tab8, Getfile(n), Getline(n), "%pythonappend or %feature(\"pythonappend\")"), "\n", NIL);
+ Printv(f_shadow, tab8, "pass\n", NIL);
+ Printv(f_shadow, "\n", NIL);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+
+ int oldshadow = shadow;
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::membervariableHandler(n);
+ shadow = oldshadow;
+
+ if (shadow && !builtin) {
+ String *mname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *setname = Swig_name_set(NSPACE_TODO, mname);
+ String *getname = Swig_name_get(NSPACE_TODO, mname);
+ int assignable = !is_immutable(n);
+ String *variable_annotation = variableAnnotation(n);
+ Printv(f_shadow, tab4, symname, variable_annotation, " = property(", module, ".", getname, NIL);
+ if (assignable)
+ Printv(f_shadow, ", ", module, ".", setname, NIL);
+ if (have_docstring(n)) {
+ String *s = docstring(n, AUTODOC_VAR, tab4);
+ if (Len(s))
+ Printv(f_shadow, ", doc=", s, NIL);
+ }
+ Printv(f_shadow, ")\n", NIL);
+ Delete(variable_annotation);
+ Delete(mname);
+ Delete(setname);
+ Delete(getname);
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * staticmembervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ Swig_save("builtin_staticmembervariableHandler", n, "builtin_symname", NIL);
+ Language::staticmembervariableHandler(n);
+ Swig_restore(n);
+
+ if (GetFlag(n, "wrappedasconstant"))
+ return SWIG_OK;
+
+ String *symname = Getattr(n, "sym:name");
+
+ if (shadow) {
+ if (!builtin && GetFlag(n, "hasconsttype")) {
+ String *mname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ Printf(f_shadow_stubs, "%s.%s = %s.%s.%s\n", class_name, symname, module, global_name, mname);
+ Delete(mname);
+ } else {
+ String *mname = Swig_name_member(NSPACE_TODO, class_name, symname);
+ String *getname = Swig_name_get(NSPACE_TODO, mname);
+ String *wrapgetname = Swig_name_wrapper(getname);
+ String *vargetname = NewStringf("Swig_var_%s", getname);
+ String *setname = Swig_name_set(NSPACE_TODO, mname);
+ String *wrapsetname = Swig_name_wrapper(setname);
+ String *varsetname = NewStringf("Swig_var_%s", setname);
+
+ Wrapper *f = NewWrapper();
+ Printv(f->def, "SWIGINTERN PyObject *", wrapgetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(args)) {", NIL);
+ Printv(f->code, " return ", vargetname, "();\n", NIL);
+ Append(f->code, "}\n");
+ add_method(getname, wrapgetname, 0);
+ Wrapper_print(f, f_wrappers);
+ DelWrapper(f);
+ int assignable = !is_immutable(n);
+ if (assignable) {
+ int funpack = fastunpack;
+ Wrapper *f = NewWrapper();
+ Printv(f->def, "SWIGINTERN PyObject *", wrapsetname, "(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {", NIL);
+ Wrapper_add_local(f, "res", "int res");
+ if (!funpack) {
+ Wrapper_add_local(f, "value", "PyObject *value");
+ Append(f->code, "if (!PyArg_ParseTuple(args, \"O:set\", &value)) return NULL;\n");
+ }
+ Printf(f->code, "res = %s(%s);\n", varsetname, funpack ? "args" : "value");
+ Append(f->code, "return !res ? SWIG_Py_Void() : NULL;\n");
+ Append(f->code, "}\n");
+ Wrapper_print(f, f_wrappers);
+ add_method(setname, wrapsetname, 0, 0, funpack, 1, 1);
+ DelWrapper(f);
+ }
+ if (!builtin) {
+ Printv(f_shadow, tab4, symname, " = property(", module, ".", getname, NIL);
+ if (assignable)
+ Printv(f_shadow, ", ", module, ".", setname, NIL);
+ if (have_docstring(n)) {
+ String *s = docstring(n, AUTODOC_VAR, tab4);
+ if (Len(s))
+ Printv(f_shadow, ", doc=", s, NIL);
+ }
+ Printv(f_shadow, ")\n", NIL);
+ }
+ String *getter = Getattr(n, "pybuiltin:getter");
+ String *setter = Getattr(n, "pybuiltin:setter");
+ Hash *h = NULL;
+ if (getter || setter) {
+ h = Getattr(builtin_getset, symname);
+ if (!h) {
+ h = NewHash();
+ Setattr(h, "static", "1");
+ Setattr(builtin_getset, symname, h);
+ }
+ }
+ if (getter)
+ Setattr(h, "getter", getter);
+ if (setter)
+ Setattr(h, "setter", setter);
+ if (h)
+ Delete(h);
+ Delete(mname);
+ Delete(getname);
+ Delete(wrapgetname);
+ Delete(vargetname);
+ Delete(setname);
+ Delete(wrapsetname);
+ Delete(varsetname);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * memberconstantHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberconstantHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (builtin && in_class) {
+ Swig_save("builtin_memberconstantHandler", n, "pybuiltin:symname", NIL);
+ Setattr(n, "pybuiltin:symname", symname);
+ }
+ int oldshadow = shadow;
+ if (shadow)
+ shadow = shadow | PYSHADOW_MEMBER;
+ Language::memberconstantHandler(n);
+ shadow = oldshadow;
+
+ if (builtin && in_class) {
+ Swig_restore(n);
+ } else if (shadow) {
+ Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(NSPACE_TODO, class_name, symname), "\n", NIL);
+ if (have_docstring(n))
+ Printv(f_shadow, tab4, docstring(n, AUTODOC_CONST, tab4), "\n", NIL);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * insertDirective()
+ *
+ * Hook for %insert directive. We're going to look for special %shadow inserts
+ * as a special case so we can do indenting correctly
+ * ------------------------------------------------------------ */
+
+ virtual int insertDirective(Node *n) {
+ String *code = Getattr(n, "code");
+ String *section = Getattr(n, "section");
+
+ if (!ImportMode && (Cmp(section, "python") == 0 || Cmp(section, "shadow") == 0)) {
+ if (shadow) {
+ String *pycode = indent_pythoncode(code, shadow_indent, Getfile(n), Getline(n), "%pythoncode or %insert(\"python\") block");
+ Printv(f_shadow, pycode, NIL);
+ Delete(pycode);
+ }
+ } else if (!ImportMode && (Cmp(section, "pythonbegin") == 0)) {
+ if (shadow) {
+ String *pycode = indent_pythoncode(code, "", Getfile(n), Getline(n), "%pythonbegin or %insert(\"pythonbegin\") block");
+ Printv(f_shadow_begin, pycode, NIL);
+ Delete(pycode);
+ }
+ } else {
+ Language::insertDirective(n);
+ }
+ return SWIG_OK;
+ }
+
+ virtual String *runtimeCode() {
+ String *s = NewString("");
+ String *shead = Swig_include_sys("pyhead.swg");
+ if (!shead) {
+ Printf(stderr, "*** Unable to open 'pyhead.swg'\n");
+ } else {
+ Append(s, shead);
+ Delete(shead);
+ }
+ String *serrors = Swig_include_sys("pyerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'pyerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *sthread = Swig_include_sys("pythreads.swg");
+ if (!sthread) {
+ Printf(stderr, "*** Unable to open 'pythreads.swg'\n");
+ } else {
+ Append(s, sthread);
+ Delete(sthread);
+ }
+ String *sapi = Swig_include_sys("pyapi.swg");
+ if (!sapi) {
+ Printf(stderr, "*** Unable to open 'pyapi.swg'\n");
+ } else {
+ Append(s, sapi);
+ Delete(sapi);
+ }
+ String *srun = Swig_include_sys("pyrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'pyrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ virtual String *defaultExternalRuntimeFilename() {
+ return NewString("swigpyrun.h");
+ }
+
+ /*----------------------------------------------------------------------
+ * kwargsSupport()
+ *--------------------------------------------------------------------*/
+
+ bool kwargsSupport() const {
+ return true;
+ }
+};
+
+/* ---------------------------------------------------------------
+ * classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Python object.
+ *
+ * ** Moved it here due to internal error on gcc-2.96 **
+ * --------------------------------------------------------------- */
+int PYTHON::classDirectorMethods(Node *n) {
+ director_method_index = 0;
+ return Language::classDirectorMethods(n);
+}
+
+
+int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ SwigType *returntype = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ if (builtin) {
+ // Rename any wrapped parameters called 'self' as the generated code contains a variable with same name
+ Parm *p;
+ for (p = l; p; p = nextSibling(p)) {
+ String *arg = Getattr(p, "name");
+ if (arg && Cmp(arg, "self") == 0)
+ Delattr(p, "name");
+ }
+ }
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ String *str = SwigType_str(Getattr(p, "type"), 0);
+ Append(w->def, str);
+ Append(declaration, str);
+ Delete(str);
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (builtin) {
+ Printv(w->code, "PyObject *self = NULL;\n", NIL);
+ Printv(w->code, "(void)self;\n", NIL);
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> Python) */
+ String *arglist = NewString("");
+ String *parse_args = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ /* remove the wrapper 'w' since it was producing spurious temps */
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ Parm *p;
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0;
+ p = l;
+ int use_parse = 0;
+ while (p) {
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ String *pname = Getattr(p, "name");
+ String *ptype = Getattr(p, "type");
+
+ Putc(',', arglist);
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ String *parse = Getattr(p, "tmap:directorin:parse");
+ if (!parse) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewString(source);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Delete(input);
+ Replaceall(tm, "$owner", "0");
+ /* Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL); */
+ Printv(wrap_args, "swig::SwigVar_PyObject ", source, ";\n", NIL);
+
+ Printv(wrap_args, tm, "\n", NIL);
+ Printv(arglist, "(PyObject *)", source, NIL);
+ Putc('O', parse_args);
+ } else {
+ use_parse = 1;
+ Append(parse_args, parse);
+ Setattr(p, "emit:directorinput", pname);
+ Replaceall(tm, "$input", pname);
+ Replaceall(tm, "$owner", "0");
+ if (Len(tm) == 0)
+ Append(tm, pname);
+ Append(arglist, tm);
+ }
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(ptype, "void")) {
+ /* special handling for pointers to other C++ director classes.
+ * ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. in other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. we avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
+ Node *module = Getattr(parent, "module");
+ Node *target = Swig_directormap(module, ptype);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(ptype) + 2);
+ /* name as pointer */
+ String *ppname = Copy(pname);
+ if (SwigType_isreference(ptype)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Python doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", pname);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(ptype, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n",
+ SwigType_str(ptype, pname), SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(ptype);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_DIRECTOR_CAST(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_InternalNewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Append(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "SWIG_Py_INCREF((PyObject *)%s);\n", source);
+ Append(wrap_args, "}\n");
+ Delete(director);
+ Printv(arglist, source, NIL);
+ } else {
+ Wrapper_add_localv(w, source, "swig::SwigVar_PyObject", source, "= 0", NIL);
+ Printf(wrap_args, "%s = SWIG_InternalNewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
+ // source, nonconst, base);
+ Printv(arglist, source, NIL);
+ }
+ Putc('O', parse_args);
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* add the method name as a PyString */
+ String *pyname = Getattr(n, "sym:name");
+
+ int allow_thread = threads_enable(n);
+
+ if (allow_thread) {
+ thread_begin_block(n, w->code);
+ Append(w->code, "{\n");
+ }
+
+ /* wrap complex arguments to PyObjects */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the Python object */
+ if (dirprot_mode() && !is_public(n)) {
+ Printf(w->code, "swig_set_inner(\"%s\", true);\n", name);
+ }
+
+
+ Append(w->code, "if (!swig_get_self()) {\n");
+ Printf(w->code, " Swig::DirectorException::raise(\"'self' uninitialized, maybe you forgot to call %s.__init__.\");\n", classname);
+ Append(w->code, "}\n");
+ Append(w->code, "#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)\n");
+ Printf(w->code, "const size_t swig_method_index = %d;\n", director_method_index++);
+ Printf(w->code, "const char *const swig_method_name = \"%s\";\n", pyname);
+
+ Append(w->code, "PyObject *method = swig_get_method(swig_method_index, swig_method_name);\n");
+ if (Len(parse_args) > 0) {
+ if (use_parse) {
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunction(method, (char *)\"(%s)\" %s);\n", Swig_cresult_name(), parse_args, arglist);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunctionObjArgs(method %s, NULL);\n", Swig_cresult_name(), arglist);
+ }
+ } else {
+ Append(w->code, "swig::SwigVar_PyObject args = PyTuple_New(0);\n");
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_Call(method, (PyObject *) args, NULL);\n", Swig_cresult_name());
+ }
+ Append(w->code, "#else\n");
+ if (Len(parse_args) > 0) {
+ if (use_parse) {
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethod(swig_get_self(), (char *)\"%s\", (char *)\"(%s)\" %s);\n", Swig_cresult_name(), pyname, parse_args, arglist);
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar(\"%s\");\n", pyname);
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name %s, NULL);\n", Swig_cresult_name(), arglist);
+ }
+ } else {
+ Printf(w->code, "swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar(\"%s\");\n", pyname);
+ Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, NULL);\n", Swig_cresult_name());
+ }
+ Append(w->code, "#endif\n");
+
+ if (dirprot_mode() && !is_public(n))
+ Printf(w->code, "swig_set_inner(\"%s\", false);\n", name);
+
+ /* exception handling */
+ tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ if (tm)
+ tm = Copy(tm);
+ }
+ Printf(w->code, "if (!%s) {\n", Swig_cresult_name());
+ Append(w->code, " PyObject *error = PyErr_Occurred();\n");
+ if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
+ Replaceall(tm, "$error", "error");
+ Printv(w->code, Str(tm), "\n", NIL);
+ } else {
+ Append(w->code, " if (error) {\n");
+ Printf(w->code, " Swig::DirectorMethodException::raise(\"Error detected when calling '%s.%s'\");\n", classname, pyname);
+ Append(w->code, " }\n");
+ }
+ Append(w->code, "}\n");
+ Delete(tm);
+
+ /*
+ * Python method may return a simple object, or a tuple.
+ * for in/out arguments, we have to extract the appropriate PyObjects from the tuple,
+ * then marshal everything back to C/C++ (return value and output arguments).
+ *
+ */
+
+ /* marshal return value and other outputs (if any) from PyObject to C/C++ type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ if (outputs > 1) {
+ Wrapper_add_local(w, "output", "PyObject *output");
+ Printf(w->code, "if (!PyTuple_Check(%s)) {\n", Swig_cresult_name());
+ Printf(w->code, " Swig::DirectorTypeMismatchException::raise(\"Python method %s.%sfailed to return a tuple.\");\n", classname, pyname);
+ Append(w->code, "}\n");
+ }
+
+ idx = 0;
+
+ /* marshal return value */
+ if (!is_void) {
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = PyTuple_GetItem(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ }
+ char temp[24];
+ sprintf(temp, "%d", idx);
+ Replaceall(tm, "$argnum", temp);
+
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ if (Getattr(n, "tmap:directorout:implicitconv")) {
+ Replaceall(tm, "$implicitconv", get_implicitconv_flag(n));
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = PyTuple_GetItem(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$result", "output");
+ } else {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ }
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* any existing helper functions to handle this? */
+ if (allow_thread) {
+ Append(w->code, "}\n");
+ thread_end_block(n, w->code);
+ }
+
+ Delete(parse_args);
+ Delete(arglist);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Append(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_python() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_python() {
+ return new PYTHON();
+}
+extern "C" Language *swig_python(void) {
+ return new_swig_python();
+}
diff --git a/contrib/tools/swig/Source/Modules/r.cxx b/contrib/tools/swig/Source/Modules/r.cxx
new file mode 100644
index 00000000000..1f9da693028
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/r.cxx
@@ -0,0 +1,2850 @@
+
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * r.cxx
+ *
+ * R language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static String* replaceInitialDash(const String *name)
+{
+ String *retval;
+ if (!Strncmp(name, "_", 1)) {
+ retval = Copy(name);
+ Insert(retval, 0, "s");
+ } else {
+ retval = Copy(name);
+ }
+ return retval;
+}
+
+static String * getRTypeName(SwigType *t, int *outCount = NULL) {
+ String *b = SwigType_base(t);
+ List *els = SwigType_split(t);
+ int count = 0;
+ int i;
+
+ if(Strncmp(b, "struct ", 7) == 0)
+ Replace(b, "struct ", "", DOH_REPLACE_FIRST);
+
+ for(i = 0; i < Len(els); i++) {
+ String *el = Getitem(els, i);
+ if(Strcmp(el, "p.") == 0 || Strncmp(el, "a(", 2) == 0) {
+ count++;
+ Append(b, "Ref");
+ }
+ }
+ if(outCount)
+ *outCount = count;
+
+ String *tmp = NewString("");
+ char *retName = Char(SwigType_manglestr(t));
+ Insert(tmp, 0, retName);
+ return tmp;
+
+}
+
+/* --------------------------------------------------------------
+ * Tries to get the resolved name, with options of adding
+ * or removing a layer of references. Take care not
+ * to request both
+ * --------------------------------------------------------------*/
+
+static String *getRClassName(String *retType, int deRef=0, int upRef=0) {
+ SwigType *resolved = SwigType_typedef_resolve_all(retType);
+ int ispointer = SwigType_ispointer(resolved);
+ int isreference = SwigType_isreference(resolved);
+ if (upRef) {
+ SwigType_add_pointer(resolved);
+ }
+ if (deRef) {
+ if (ispointer) {
+ SwigType_del_pointer(resolved);
+ }
+ if (isreference) {
+ SwigType_del_reference(resolved);
+ }
+ }
+ String *tmp = NewString("");
+ Insert(tmp, 0, Char(SwigType_manglestr(resolved)));
+ return(tmp);
+}
+
+/* --------------------------------------------------------------
+ * Tries to get the name of the R class corresponding to the given type
+ * e.g. struct A * is ARef, struct A** is ARefRef.
+ * Now handles arrays, i.e. struct A[2]
+ * --------------------------------------------------------------*/
+
+
+static String * getRClassNameCopyStruct(String *retType, int addRef) {
+ String *tmp = NewString("");
+
+ List *l = SwigType_split(retType);
+ int n = Len(l);
+ if(!l || n == 0) {
+#ifdef R_SWIG_VERBOSE
+ Printf(stdout, "SwigType_split return an empty list for %s\n", retType);
+#endif
+ return(tmp);
+ }
+
+
+ String *el = Getitem(l, n-1);
+ char *ptr = Char(el);
+ if(strncmp(ptr, "struct ", 7) == 0)
+ ptr += 7;
+
+ Printf(tmp, "%s", ptr);
+
+ if(addRef) {
+ for(int i = 0; i < n; i++) {
+ if(Strcmp(Getitem(l, i), "p.") == 0 ||
+ Strncmp(Getitem(l, i), "a(", 2) == 0)
+ Printf(tmp, "Ref");
+ }
+ }
+
+ return tmp;
+}
+
+
+/* -------------------------------------------------------------
+ * Write the elements of a list to the File*, one element per line.
+ * If quote is true, surround the element with "element".
+ * This takes care of inserting a tab in front of each line and also
+ * a comma after each element, except the last one.
+ * --------------------------------------------------------------*/
+
+
+static void writeListByLine(List *l, File *out, bool quote = 0) {
+ int i, n = Len(l);
+ for(i = 0; i < n; i++)
+ Printf(out, "%s%s%s%s%s\n", tab8,
+ quote ? "\"" :"",
+ Getitem(l, i),
+ quote ? "\"" :"", i < n-1 ? "," : "");
+}
+
+
+static const char *usage = "\
+R Options (available with -r)\n\
+ -copystruct - Emit R code to copy C structs (on by default)\n\
+ -debug - Output debug\n\
+ -dll <name> - Name of the DLL (without the .dll or .so suffix).\n\
+ Default is the module name.\n\
+ -gc - Aggressive garbage collection\n\
+ -memoryprof - Add memory profile\n\
+ -namespace - Output NAMESPACE file\n\
+ -no-init-code - Turn off the generation of the R_init_<pkgname> code\n\
+ (registration information still generated)\n\
+ -package <name> - Package name for the PACKAGE argument of the R .Call()\n\
+ invocations. Default is the module name.\n\
+";
+
+
+
+/* -------------------------------------------------------------
+ * Display the help for this module on the screen/console.
+ * --------------------------------------------------------------*/
+
+static void showUsage() {
+ fputs(usage, stdout);
+}
+
+static bool expandTypedef(SwigType *t) {
+ if (SwigType_isenum(t)) return false;
+ String *prefix = SwigType_prefix(t);
+ if (Strncmp(prefix, "f", 1)) return false;
+ if (Strncmp(prefix, "p.f", 3)) return false;
+ return true;
+}
+
+
+/* -------------------------------------------------------------
+ * Determine whether we should add a .copy argument to the S function
+ * that wraps/interfaces to the routine that returns the given type.
+ * --------------------------------------------------------------*/
+
+static int addCopyParameter(SwigType *type) {
+ int ok = 0;
+ ok = Strncmp(type, "struct ", 7) == 0 || Strncmp(type, "p.struct ", 9) == 0;
+ if(!ok) {
+ ok = Strncmp(type, "p.", 2);
+ }
+
+ return(ok);
+}
+
+static void replaceRClass(String *tm, SwigType *type) {
+ String *tmp = getRClassName(type, 0, 0);
+ String *tmp_base = getRClassName(type, 1, 0);
+ String *tmp_ref = getRClassName(type, 0, 1);
+ Replaceall(tm, "$R_class", tmp);
+ Replaceall(tm, "$*R_class", tmp_base);
+ Replaceall(tm, "$&R_class", tmp_ref);
+ Delete(tmp); Delete(tmp_base); Delete(tmp_ref);
+}
+
+class R : public Language {
+public:
+ R();
+ void registerClass(Node *n);
+ void main(int argc, char *argv[]);
+ int top(Node *n);
+
+ void dispatchFunction(Node *n);
+ int functionWrapper(Node *n);
+ int constantWrapper(Node *n);
+ int variableWrapper(Node *n);
+
+ int classDeclaration(Node *n);
+ int enumDeclaration(Node *n);
+ String *enumValue(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ int membervariableHandler(Node *n);
+
+ int typedefHandler(Node *n);
+
+ static List *Swig_overload_rank(Node *n, bool script_lang_wrapping);
+
+ int memberfunctionHandler(Node *n) {
+ if (debugMode)
+ Printf(stdout, "<memberfunctionHandler> %s %s\n",
+ Getattr(n, "name"),
+ Getattr(n, "type"));
+ member_name = Getattr(n, "sym:name");
+ processing_class_member_function = 1;
+ int status = Language::memberfunctionHandler(n);
+ processing_class_member_function = 0;
+ return status;
+ }
+
+ /* Grab the name of the current class being processed so that we can
+ deal with members of that class. */
+ int classHandler(Node *n){
+ if(!ClassMemberTable)
+ ClassMemberTable = NewHash();
+
+ class_name = Getattr(n, "name");
+ int status = Language::classHandler(n);
+
+ class_name = NULL;
+ return status;
+ }
+
+ String *runtimeCode();
+ void replaceSpecialVariables(String *method, String *tm, Parm *parm);
+
+protected:
+ int addRegistrationRoutine(String *rname, int nargs);
+ int outputRegistrationRoutines(File *out);
+
+ int outputCommandLineArguments(File *out);
+ int generateCopyRoutines(Node *n);
+ int DumpCode(Node *n);
+
+ int OutputMemberReferenceMethod(String *className, int isSet, List *memberList, List *nameList, List *typeList, File *out);
+ int defineArrayAccessors(SwigType *type);
+
+ void addNamespaceFunction(String *name) {
+ if(!namespaceFunctions)
+ namespaceFunctions = NewList();
+ Append(namespaceFunctions, name);
+ }
+
+ void addNamespaceMethod(String *name) {
+ if(!namespaceMethods)
+ namespaceMethods = NewList();
+ Append(namespaceMethods, name);
+ }
+
+ String* processType(SwigType *t, Node *n, int *nargs = NULL);
+ String *createFunctionPointerHandler(SwigType *t, Node *n, int *nargs);
+ int addFunctionPointerProxy(String *name, Node *n, SwigType *t, String *s_paramTypes) {
+ /*XXX Do we need to put the t in there to get the return type later. */
+ if(!functionPointerProxyTable)
+ functionPointerProxyTable = NewHash();
+
+ Setattr(functionPointerProxyTable, name, n);
+
+ Setattr(SClassDefs, name, name);
+ Printv(s_classes, "setClass('",
+ name,
+ "',\n", tab8,
+ "prototype = list(parameterTypes = c(", s_paramTypes, "),\n",
+ tab8, tab8, tab8,
+ "returnType = '", SwigType_manglestr(t), "'),\n", tab8,
+ "contains = 'CRoutinePointer')\n\n##\n", NIL);
+
+ return SWIG_OK;
+ }
+
+
+ void addSMethodInfo(String *name,
+ String *argType, int nargs);
+ // Simple initialization such as constant strings that can be reused.
+ void init();
+
+
+ void addAccessor(String *memberName, Wrapper *f,
+ String *name, String *methodSetGet);
+
+ static int getFunctionPointerNumArgs(Node *n, SwigType *tt);
+
+ // filtering of class member lists by function type. Used in constructing accessors
+ // are we allowed to use stl style functors to customise this?
+ List* filterMemberList(List *class_member_function_types, List *class_member_other, String *R_MEMBER, bool equal);
+
+protected:
+ bool copyStruct;
+ bool memoryProfile;
+ bool aggressiveGc;
+
+ // Strings into which we cumulate the generated code that is to be written
+ //vto the files.
+ String *enum_values;
+ String *enum_def_calls;
+ String *sfile;
+ String *f_init;
+ String *s_classes;
+ String *f_begin;
+ String *f_runtime;
+ String *f_wrapper;
+ String *s_header;
+ String *f_wrappers;
+ String *s_init;
+ String *s_init_routine;
+ String *s_namespace;
+
+ // State variables that carry information across calls to functionWrapper()
+ // from member accessors and class declarations.
+ String *opaqueClassDeclaration;
+ int processing_variable;
+ int processing_member_access_function;
+ String *member_name;
+ String *class_name;
+
+ String *R_MEMBER_NORMAL;
+ String *R_MEMBER_SET;
+ String *R_MEMBER_GET;
+
+ int processing_class_member_function;
+ // Spread out the lists so that they are simpler to process
+ // by storing the type of the method (i.e. set, get or nothing)
+ // and having separate lists for name, membername and wrapper
+ List *class_member_function_types;
+ List *class_member_function_names;
+ List *class_member_function_membernames;
+ List *class_member_function_wrappernames;
+ /* */
+ Hash *ClassMemberTable;
+ Hash *ClassMethodsTable;
+ Hash *SClassDefs;
+ Hash *SMethodInfo;
+
+ // Information about routines that are generated and to be registered with
+ // R for dynamic lookup.
+ Hash *registrationTable;
+ Hash *functionPointerProxyTable;
+
+ List *namespaceFunctions;
+ List *namespaceMethods;
+ List *namespaceClasses; // Probably can do this from ClassMemberTable.
+
+
+ // Store a copy of the command line.
+ // Need only keep a string that has it formatted.
+ char **Argv;
+ int Argc;
+ bool inCPlusMode;
+
+ // State variables that we remember from the command line settings
+ // potentially that govern the code we generate.
+ String *DllName;
+ String *Rpackage;
+ bool noInitializationCode;
+ bool outputNamespaceInfo;
+
+ String *UnProtectWrapupCode;
+
+ // Static members
+ static bool debugMode;
+};
+
+R::R() :
+ copyStruct(false),
+ memoryProfile(false),
+ aggressiveGc(false),
+ enum_values(0),
+ enum_def_calls(0),
+ sfile(0),
+ f_init(0),
+ s_classes(0),
+ f_begin(0),
+ f_runtime(0),
+ f_wrapper(0),
+ s_header(0),
+ f_wrappers(0),
+ s_init(0),
+ s_init_routine(0),
+ s_namespace(0),
+ opaqueClassDeclaration(0),
+ processing_variable(0),
+ processing_member_access_function(0),
+ member_name(0),
+ class_name(0),
+ R_MEMBER_NORMAL(NewString("normal")),
+ R_MEMBER_SET(NewString("set")),
+ R_MEMBER_GET(NewString("get")),
+ processing_class_member_function(0),
+ class_member_function_types(0),
+ class_member_function_names(0),
+ class_member_function_membernames(0),
+ class_member_function_wrappernames(0),
+ ClassMemberTable(0),
+ ClassMethodsTable(0),
+ SClassDefs(0),
+ SMethodInfo(0),
+ registrationTable(0),
+ functionPointerProxyTable(0),
+ namespaceFunctions(0),
+ namespaceMethods(0),
+ namespaceClasses(0),
+ Argv(0),
+ Argc(0),
+ inCPlusMode(false),
+ DllName(0),
+ Rpackage(0),
+ noInitializationCode(false),
+ outputNamespaceInfo(false),
+ UnProtectWrapupCode(0) {
+}
+
+bool R::debugMode = false;
+
+int R::getFunctionPointerNumArgs(Node *n, SwigType *tt) {
+ (void) tt;
+ n = Getattr(n, "type");
+ if (debugMode)
+ Printf(stdout, "type: %s\n", n);
+
+ ParmList *parms = Getattr(n, "parms");
+ if (debugMode)
+ Printf(stdout, "parms = %p\n", parms);
+ return ParmList_len(parms);
+}
+
+
+void R::addSMethodInfo(String *name, String *argType, int nargs) {
+ (void) argType;
+
+ if(!SMethodInfo)
+ SMethodInfo = NewHash();
+ if (debugMode)
+ Printf(stdout, "[addMethodInfo] %s\n", name);
+
+ Hash *tb = Getattr(SMethodInfo, name);
+
+ if(!tb) {
+ tb = NewHash();
+ Setattr(SMethodInfo, name, tb);
+ }
+
+ String *str = Getattr(tb, "max");
+ int max = -1;
+ if(str)
+ max = atoi(Char(str));
+ if(max < nargs) {
+ if(str) Delete(str);
+ str = NewStringf("%d", max);
+ Setattr(tb, "max", str);
+ }
+}
+
+/* ----------------------------------------
+ * Returns the name of the new routine.
+ * ------------------------------------------ */
+
+String * R::createFunctionPointerHandler(SwigType *t, Node *n, int *numArgs) {
+ String *funName = SwigType_manglestr(t);
+
+ /* See if we have already processed this one. */
+ if(functionPointerProxyTable && Getattr(functionPointerProxyTable, funName))
+ return funName;
+
+ if (debugMode)
+ Printf(stdout, "<createFunctionPointerHandler> Defining %s\n", t);
+
+ SwigType *rettype = Copy(Getattr(n, "type"));
+ SwigType *funcparams = SwigType_functionpointer_decompose(rettype);
+ String *rtype = SwigType_str(rettype, 0);
+
+ // ParmList *parms = Getattr(n, "parms");
+ // memory leak
+ ParmList *parms = SwigType_function_parms(SwigType_del_pointer(Copy(t)), n);
+
+
+ if (debugMode) {
+ Printf(stdout, "Type: %s\n", t);
+ Printf(stdout, "Return type: %s\n", SwigType_base(t));
+ }
+
+ bool isVoidType = Strcmp(rettype, "void") == 0;
+ if (debugMode)
+ Printf(stdout, "%s is void ? %s (%s)\n", funName, isVoidType ? "yes" : "no", rettype);
+
+ Wrapper *f = NewWrapper();
+
+ /* Go through argument list, attach lnames for arguments */
+ int i = 0;
+ Parm *p = parms;
+ for (i = 0; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname;
+ if (!arg && Cmp(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i+1);
+ Setattr(p, "name", lname);
+ } else
+ lname = arg;
+
+ Setattr(p, "lname", lname);
+ }
+
+ Swig_typemap_attach_parms("out", parms, f);
+ Swig_typemap_attach_parms("scoerceout", parms, f);
+ Swig_typemap_attach_parms("scheck", parms, f);
+
+ Printf(f->def, "%s %s(", rtype, funName);
+
+ emit_parameter_variables(parms, f);
+ emit_return_variable(n, rettype, f);
+ // emit_attach_parmmaps(parms,f);
+
+ /* Using weird name and struct to avoid potential conflicts. */
+ Wrapper_add_local(f, "r_swig_cb_data", "RCallbackFunctionData *r_swig_cb_data = R_SWIG_getCallbackFunctionData()");
+ String *lvar = NewString("r_swig_cb_data");
+
+ Wrapper_add_local(f, "r_tmp", "SEXP r_tmp"); // for use in converting arguments to R objects for call.
+ Wrapper_add_local(f, "r_nprotect", "int r_nprotect = 0"); // for use in converting arguments to R objects for call.
+ Wrapper_add_local(f, "r_vmax", "char * r_vmax= 0"); // for use in converting arguments to R objects for call.
+
+ // Add local for error code in return value. This is not in emit_return_variable because that assumes an out typemap
+ // whereas the type makes are reverse
+ Wrapper_add_local(f, "ecode", "int ecode = 0");
+
+ p = parms;
+ int nargs = ParmList_len(parms);
+ if(numArgs) {
+ *numArgs = nargs;
+ if (debugMode)
+ Printf(stdout, "Setting number of parameters to %d\n", *numArgs);
+ }
+ String *setExprElements = NewString("");
+
+ String *s_paramTypes = NewString("");
+ for(i = 0; p; i++) {
+ SwigType *tt = Getattr(p, "type");
+ SwigType *name = Getattr(p, "name");
+ SwigType *swig_parm_name = NewStringf("swigarg_%s", name);
+ String *tm = Getattr(p, "tmap:out");
+ bool isVoidParm = Strcmp(tt, "void") == 0;
+ if (isVoidParm)
+ Printf(f->def, "%s", SwigType_str(tt, 0));
+ else
+ Printf(f->def, "%s %s", SwigType_str(tt, 0), swig_parm_name);
+ if (tm) {
+ String *lstr = SwigType_lstr(tt, 0);
+ if (SwigType_isreference(tt) || SwigType_isrvalue_reference(tt)) {
+ Printf(f->code, "%s = (%s) &%s;\n", Getattr(p, "lname"), lstr, swig_parm_name);
+ } else if (!isVoidParm) {
+ Printf(f->code, "%s = (%s) %s;\n", Getattr(p, "lname"), lstr, swig_parm_name);
+ }
+ Replaceall(tm, "$1", name);
+ Replaceall(tm, "$result", "r_tmp");
+ if (debugMode) {
+ Printf(stdout, "Calling Replace A: %s\n", Getattr(p,"type"));
+ }
+ replaceRClass(tm, Getattr(p,"type"));
+ Replaceall(tm,"$owner", "0");
+ Delete(lstr);
+ }
+
+ Printf(setExprElements, "%s\n", tm);
+ Printf(setExprElements, "SETCAR(r_swig_cb_data->el, %s);\n", "r_tmp");
+ Printf(setExprElements, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
+
+ Printf(s_paramTypes, "'%s'", SwigType_manglestr(tt));
+
+
+ p = nextSibling(p);
+ if(p) {
+ Printf(f->def, ", ");
+ Printf(s_paramTypes, ", ");
+ }
+ }
+
+ Printf(f->def, ") {\n");
+
+ Printf(f->code, "Rf_protect(%s->expr = Rf_allocVector(LANGSXP, %d));\n", lvar, nargs + 1);
+ Printf(f->code, "r_nprotect++;\n");
+ Printf(f->code, "r_swig_cb_data->el = r_swig_cb_data->expr;\n\n");
+
+ Printf(f->code, "SETCAR(r_swig_cb_data->el, r_swig_cb_data->fun);\n");
+ Printf(f->code, "r_swig_cb_data->el = CDR(r_swig_cb_data->el);\n\n");
+
+ Printf(f->code, "%s\n\n", setExprElements);
+
+ Printv(f->code, "r_swig_cb_data->retValue = R_tryEval(",
+ "r_swig_cb_data->expr,",
+ " R_GlobalEnv,",
+ " &r_swig_cb_data->errorOccurred",
+ ");\n",
+ NIL);
+
+ Printv(f->code, "\n",
+ "if(r_swig_cb_data->errorOccurred) {\n",
+ "R_SWIG_popCallbackFunctionData(1);\n",
+ "Rf_error(\"error in calling R function as a function pointer (",
+ funName,
+ ")\");\n",
+ "}\n",
+ NIL);
+
+
+
+ if(!isVoidType) {
+ /* Need to deal with the return type of the function pointer, not the function pointer itself.
+ So build a new node that has the relevant pieces.
+ XXX Have to be a little more clever so that we can deal with struct A * - the * is getting lost.
+ Is this still true? If so, will a SwigType_push() solve things?
+ */
+ Parm *bbase = NewParmNode(rettype, n);
+ String *returnTM = Swig_typemap_lookup("in", bbase, Swig_cresult_name(), f);
+ if(returnTM) {
+ String *tm = returnTM;
+ Replaceall(tm,"$input", "r_swig_cb_data->retValue");
+ replaceRClass(tm, rettype);
+ Replaceall(tm,"$owner", "0");
+ Replaceall(tm,"$disown","0");
+ Printf(f->code, "%s\n", tm);
+ }
+ Delete(bbase);
+ }
+
+ Printv(f->code, "R_SWIG_popCallbackFunctionData(1);\n", NIL);
+ Printv(f->code, "\n", UnProtectWrapupCode, NIL);
+
+ if (SwigType_isreference(rettype)) {
+ Printv(f->code, "return *", Swig_cresult_name(), ";\n", NIL);
+ } else if (SwigType_isrvalue_reference(rettype)) {
+ Printv(f->code, "return std::move(*", Swig_cresult_name(), ");\n", NIL);
+ } else if (!isVoidType) {
+ Printv(f->code, "return ", Swig_cresult_name(), ";\n", NIL);
+ }
+
+ Printv(f->code, "\n}\n", NIL);
+ Replaceall(f->code, "SWIG_exception_fail", "SWIG_exception_noreturn");
+
+ /* To coerce correctly in S, we really want to have an extra/intermediate
+ function that handles the scoerceout.
+ We need to check if any of the argument types have an entry in
+ that map. If none do, the ignore and call the function straight.
+ Otherwise, generate a marshalling function.
+ Need to be able to find it in S. Or use an entirely generic one
+ that evaluates the expressions.
+ Handle errors in the evaluation of the function by restoring
+ the stack, if there is one in use for this function (i.e. no
+ userData).
+ */
+
+ Wrapper_print(f, f_wrapper);
+
+ addFunctionPointerProxy(funName, n, t, s_paramTypes);
+ Delete(s_paramTypes);
+ Delete(rtype);
+ Delete(rettype);
+ Delete(funcparams);
+ DelWrapper(f);
+
+ return funName;
+}
+
+void R::init() {
+ UnProtectWrapupCode =
+ NewStringf("%s", "vmaxset(r_vmax);\nif(r_nprotect) Rf_unprotect(r_nprotect);\n\n");
+
+ SClassDefs = NewHash();
+
+ sfile = NewString("");
+ f_init = NewString("");
+ s_header = NewString("");
+ f_begin = NewString("");
+ f_runtime = NewString("");
+ f_wrapper = NewString("");
+ s_classes = NewString("");
+ s_init = NewString("");
+ s_init_routine = NewString("");
+ enum_def_calls = NewString("");
+}
+
+
+/* -------------------------------------------------------------
+ * Method from Language that is called to start the entire
+ * processing off, i.e. the generation of the code.
+ * It is called after the input has been read and parsed.
+ * Here we open the output streams and generate the code.
+ * ------------------------------------------------------------- */
+int R::top(Node *n) {
+ String *module = Getattr(n, "name");
+
+ if (debugMode) {
+ Printf(stdout, "<Top> %s\n", module);
+ }
+
+ if(!Rpackage)
+ Rpackage = Copy(module);
+ if(!DllName)
+ DllName = Copy(module);
+
+ if(outputNamespaceInfo) {
+ s_namespace = NewString("");
+ Swig_register_filebyname("snamespace", s_namespace);
+ Printf(s_namespace, "useDynLib(%s)\n", DllName);
+ }
+ // Register the naming functions
+ Swig_name_register("wrapper", "R_swig_%f");
+
+ /* Associate the different streams with names so that they can be used in %insert directives by the
+ typemap code. */
+ Swig_register_filebyname("sinit", s_init);
+ Swig_register_filebyname("sinitroutine", s_init_routine);
+
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("header", s_header);
+ Swig_register_filebyname("wrapper", f_wrapper);
+ Swig_register_filebyname("s", sfile);
+ Swig_register_filebyname("sclasses", s_classes);
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "R");
+
+ Swig_banner_target_lang(s_init, "#");
+ outputCommandLineArguments(s_init);
+
+ Printf(f_wrapper, "#ifdef __cplusplus\n");
+ Printf(f_wrapper, "extern \"C\" {\n");
+ Printf(f_wrapper, "#endif\n\n");
+
+ Language::top(n);
+
+ Printf(f_wrapper, "#ifdef __cplusplus\n");
+ Printf(f_wrapper, "}\n");
+ Printf(f_wrapper, "#endif\n");
+
+ String *type_table = NewString("");
+ SwigType_emit_type_table(f_runtime,f_wrapper);
+ Delete(type_table);
+
+ if(ClassMemberTable) {
+ //XXX OutputClassAccessInfo(ClassMemberTable, sfile);
+ Delete(ClassMemberTable);
+ ClassMemberTable = NULL;
+ }
+
+ Printf(f_init,"}\n");
+ if(registrationTable)
+ outputRegistrationRoutines(f_init);
+
+ /* Now arrange to write the 2 files - .S and .c. */
+
+ DumpCode(n);
+
+ Delete(sfile);
+ Delete(s_classes);
+ Delete(s_init);
+ Delete(f_wrapper);
+ Delete(f_init);
+
+ Delete(s_header);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+}
+
+
+/* -------------------------------------------------------------
+ * Write the generated code to the .S and the .c files.
+ * ------------------------------------------------------------- */
+int R::DumpCode(Node *n) {
+ String *output_filename = NewString("");
+
+
+ /* The name of the file in which we will generate the S code. */
+ Printf(output_filename, "%s%s.R", SWIG_output_directory(), Rpackage);
+
+#ifdef R_SWIG_VERBOSE
+ Printf(stdout, "Writing S code to %s\n", output_filename);
+#endif
+
+ File *scode = NewFile(output_filename, "w", SWIG_output_files());
+ if (!scode) {
+ FileErrorDisplay(output_filename);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(output_filename);
+
+
+ Printf(scode, "%s\n\n", s_init);
+ Printf(scode, "%s\n\n", s_classes);
+ Printf(scode, "%s\n", sfile);
+ Printf(scode, "%s\n", enum_def_calls);
+
+ Delete(scode);
+ String *outfile = Getattr(n,"outfile");
+ File *runtime = NewFile(outfile,"w", SWIG_output_files());
+ if (!runtime) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ Printf(runtime, "%s", f_begin);
+ Printf(runtime, "%s\n", f_runtime);
+ Printf(runtime, "%s\n", s_header);
+ Printf(runtime, "%s\n", f_wrapper);
+ Printf(runtime, "%s\n", f_init);
+
+ Delete(runtime);
+
+ if(outputNamespaceInfo) {
+ output_filename = NewString("");
+ Printf(output_filename, "%sNAMESPACE", SWIG_output_directory());
+ File *ns = NewFile(output_filename, "w", SWIG_output_files());
+ if (!ns) {
+ FileErrorDisplay(output_filename);
+ Exit(EXIT_FAILURE);
+ }
+ Delete(output_filename);
+
+ Printf(ns, "%s\n", s_namespace);
+
+ Printf(ns, "\nexport(\n");
+ writeListByLine(namespaceFunctions, ns);
+ Printf(ns, ")\n");
+ Printf(ns, "\nexportMethods(\n");
+ writeListByLine(namespaceMethods, ns, 1);
+ Printf(ns, ")\n");
+ Delete(ns);
+ Delete(s_namespace);
+ }
+
+ return SWIG_OK;
+}
+
+
+List *R::filterMemberList(List *class_member_types,
+ List *class_member_other,
+ String *R_MEMBER, bool equal) {
+ // filters class_member_other based on whether corresponding elements of
+ // class_member_function_types are equal or notequal to R_MEMBER
+ List *CM = NewList();
+ Iterator ftype, other;
+
+ for (ftype = First(class_member_types), other = First(class_member_other);
+ ftype.item;
+ ftype=Next(ftype), other=Next(other)) {
+ // verbose, clean up later if the overall structure works
+ if (equal) {
+ if (ftype.item == R_MEMBER) {
+ Append(CM, other.item);
+ }
+ } else {
+ if (ftype.item != R_MEMBER) {
+ Append(CM, other.item);
+ }
+ }
+ }
+ return(CM);
+}
+
+# if 0
+// not called
+/* -------------------------------------------------------------
+ * We may need to do more.... so this is left as a
+ * stub for the moment.
+ * -------------------------------------------------------------*/
+int R::OutputClassAccessInfo(Hash *tb, File *out) {
+ int n = OutputClassMemberTable(tb, out);
+ OutputClassMethodsTable(out);
+ return n;
+}
+
+/* -------------------------------------------------------------
+ * Currently this just writes the information collected about the
+ * different methods of the C++ classes that have been processed
+ * to the console.
+ * This will be used later to define S4 generics and methods.
+ * --------------------------------------------------------------*/
+
+int R::OutputClassMethodsTable(File *) {
+ Hash *tb = ClassMethodsTable;
+
+ if(!tb)
+ return SWIG_OK;
+
+ List *keys = Keys(tb);
+ String *key;
+ int i, n = Len(keys);
+ if (debugMode) {
+ for(i = 0; i < n ; i++ ) {
+ key = Getitem(keys, i);
+ Printf(stdout, "%d) %s\n", i, key);
+ List *els = Getattr(tb, key);
+ int nels = Len(els);
+ Printf(stdout, "\t");
+ for(int j = 0; j < nels; j+=2) {
+ Printf(stdout, "%s%s", Getitem(els, j), j < nels - 1 ? ", " : "");
+ Printf(stdout, "%s\n", Getitem(els, j+1));
+ }
+ Printf(stdout, "\n");
+ }
+ }
+
+ return SWIG_OK;
+}
+
+
+/* --------------------------------------------------------------
+ * Iterate over the <class name>_set and <>_get
+ * elements and generate the $ and $<- functions
+ * that provide constrained access to the member
+ * fields in these elements.
+
+ * tb - a hash table that is built up in functionWrapper
+ * as we process each membervalueHandler.
+ * The entries are indexed by <class name>_set and
+ * <class_name>_get. Each entry is a List *.
+
+ * out - the stream where the code is to be written. This is the S
+ * code stream as we generate only S code here.
+ * --------------------------------------------------------------*/
+
+int R::OutputClassMemberTable(Hash *tb, File *out) {
+ List *keys = Keys(tb), *el;
+
+ String *key;
+ int i, n = Len(keys);
+ /* Loop over all the <Class>_set and <Class>_get entries in the table. */
+ /* This function checks for names ending in _set - perhaps it should */
+ /* use attributes of some other form, as it potentially clashes with */
+ /* methods ending in _set */
+
+ if(n && outputNamespaceInfo) {
+ Printf(s_namespace, "exportClasses(");
+ }
+ for(i = 0; i < n; i++) {
+ key = Getitem(keys, i);
+ el = Getattr(tb, key);
+
+ String *className = Getitem(el, 0);
+ char *ptr = Char(key);
+ int klen = Len(key);
+ int isSet = 0;
+ if (klen > 4) {
+ ptr = &ptr[klen - 4];
+ isSet = strcmp(ptr, "_set") == 0;
+ }
+
+ if(outputNamespaceInfo)
+ Printf(s_namespace, "\"%s\"%s", className, i < n-1 ? "," : "");
+ }
+ if(n && outputNamespaceInfo) {
+ Printf(s_namespace, ")\n");
+ }
+
+ return n;
+}
+
+// end not used
+#endif
+/* --------------------------------------------------------------
+ * Write the methods for $ or $<- for accessing a member field in an
+ * struct or union (or class).
+ * className - the name of the struct or union (e.g. Bar for struct Bar)
+ * isSet - a logical value indicating whether the method is for
+ * modifying ($<-) or accessing ($) the member field.
+ * el - a list of length 2 * # accessible member elements + 1.
+ * The first element is the name of the class.
+ * The other pairs are member name and the name of the R function to access it.
+ * out - the stream where we write the code.
+ * --------------------------------------------------------------*/
+
+int R::OutputMemberReferenceMethod(String *className, int isSet,
+ List *memberList, List *nameList,
+ List *typeList, File *out) {
+ int numMems = Len(memberList), j;
+ int varaccessor = 0;
+ if (numMems == 0)
+ return SWIG_OK;
+
+ Wrapper *f = NewWrapper(), *attr = NewWrapper();
+
+ Printf(f->def, "function(x, name%s)", isSet ? ", value" : "");
+ Printf(attr->def, "function(x, i, j, ...%s)", isSet ? ", value" : "");
+
+ Printf(f->code, "{\n");
+ Printf(f->code, "%saccessorFuns = list(", tab8);
+
+ Node *itemList = NewHash();
+ bool has_prev = false;
+ for(j = 0; j < numMems; j++) {
+ String *item = Getitem(memberList, j);
+ String *dup = Getitem(nameList, j);
+ String *setgetmethod = Getitem(typeList, j);
+
+ if (setgetmethod == R_MEMBER_GET)
+ varaccessor++;
+
+ if (Getattr(itemList, item))
+ continue;
+ Setattr(itemList, item, "1");
+
+ String *pitem;
+ if (!Strcmp(item, "operator ()")) {
+ pitem = NewString("call");
+ } else if (!Strcmp(item, "operator ->")) {
+ pitem = NewString("deref");
+ } else if (!Strcmp(item, "operator +")) {
+ pitem = NewString("add");
+ } else if (!Strcmp(item, "operator -")) {
+ pitem = NewString("sub");
+ } else {
+ pitem = Copy(item);
+ }
+ if (has_prev)
+ Printf(f->code, ", ");
+ Printf(f->code, "'%s' = %s", pitem, dup);
+ has_prev = true;
+ Delete(pitem);
+ }
+ Delete(itemList);
+ Printf(f->code, ");\n");
+
+ if (!isSet && varaccessor > 0) {
+ Printf(f->code, "%svaccessors = c(", tab8);
+ bool first = true;
+ for(j = 0; j < numMems; j++) {
+ String *item = Getitem(memberList, j);
+ String *setgetmethod = Getitem(typeList, j);
+
+ // Check the type here instead of the name
+ if (setgetmethod == R_MEMBER_GET) {
+ Printf(f->code, "%s'%s'", first ? "" : ", ", item);
+ first = false;
+ }
+ }
+ Printf(f->code, ");\n");
+ }
+
+ Printv(f->code, ";", tab8,
+ "idx = pmatch(name, names(accessorFuns));\n",
+ tab8,
+ "if(is.na(idx)) \n",
+ tab8, tab4, NIL);
+ Printf(f->code, "return(callNextMethod(x, name%s));\n",
+ isSet ? ", value" : "");
+ Printv(f->code, tab8, "f = accessorFuns[[idx]];\n", NIL);
+ if(isSet) {
+ Printv(f->code, tab8, "f(x, value);\n", NIL);
+ Printv(f->code, tab8, "x;\n", NIL); // make certain to return the S value.
+ } else {
+ if (varaccessor) {
+ Printv(f->code, tab8,
+ "if (is.na(match(name, vaccessors))) function(...){f(x, ...)} else f(x);\n", NIL);
+ } else {
+ Printv(f->code, tab8, "function(...){f(x, ...)};\n", NIL);
+ }
+ }
+ Printf(f->code, "}\n");
+
+ String *classname_str = SwigType_namestr(className);
+ Printf(out, "# Start of accessor method for %s\n", classname_str);
+ Printf(out, "setMethod('$%s', '_p%s', ",
+ isSet ? "<-" : "",
+ getRClassName(className));
+ Wrapper_print(f, out);
+ Printf(out, ");\n");
+
+ if(isSet) {
+ Printf(out, "setMethod('[[<-', c('_p%s', 'character'),",
+ getRClassName(className));
+ Insert(f->code, 2, "name = i;\n");
+ Printf(attr->code, "%s", f->code);
+ Wrapper_print(attr, out);
+ Printf(out, ");\n");
+ }
+
+ Printf(out, "# end of accessor method for %s\n", classname_str);
+
+ Delete(classname_str);
+ DelWrapper(attr);
+ DelWrapper(f);
+
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+ * Called when a enumeration is to be processed.
+ * We want to call the R function defineEnumeration().
+ * tdname is the typedef of the enumeration, i.e. giving its name.
+ * --------------------------------------------------------------*/
+
+int R::enumDeclaration(Node *n) {
+ if (!ImportMode) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ String *symname = Getattr(n, "sym:name");
+
+ // TODO - deal with anonymous enumerations
+ // Previous enum code for R didn't wrap them
+ if (!symname || Getattr(n, "unnamedinstance"))
+ return SWIG_NOWRAP;
+
+ // create mangled name for the enum
+ // This will have content if the %nspace feature is set on
+ // the input file
+ String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
+ String *ename;
+
+ String *name = Getattr(n, "name");
+ ename = getRClassName(name);
+ if (debugMode) {
+ Node *current_class = getCurrentClass();
+ String *cl = NewString("");
+ if (current_class) {
+ cl = getEnumClassPrefix();
+ }
+ Printf(stdout, "enumDeclaration: %s, %s, %s, %s, %s\n", name, symname, nspace, ename, cl);
+ }
+ Delete(name);
+ // set up a call to create the R enum structure. The list of
+ // individual elements will be built in enum_code
+ enum_values = 0;
+ // Emit each enum item
+ Language::enumDeclaration(n);
+
+ Printf(enum_def_calls, "defineEnumeration(\"%s\",\n .values=c(%s))\n\n", ename, enum_values);
+ Delete(enum_values);
+ Delete(ename);
+ }
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+* --------------------------------------------------------------*/
+
+int R::enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC)) {
+ Printf(stdout, "evd: Not public\n");
+ return SWIG_NOWRAP;
+ }
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ String *parent_name = Getattr(parent, "name");
+ String *newsymname = 0;
+ String *tmpValue;
+
+ // Strange hack from parent method
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ // Deal with enum values that are not int
+ int swigtype = SwigType_type(Getattr(n, "type"));
+ if (swigtype == T_CHAR) {
+ if (Getattr(n, "enumstringval")) {
+ String *val = NewStringf("'%(escape)s'", Getattr(n, "enumstringval"));
+ Setattr(n, "enumvalue", val);
+ Delete(val);
+ }
+ } else {
+ String *numval = Getattr(n, "enumnumval");
+ if (numval) Setattr(n, "enumvalue", numval);
+ }
+
+ if (GetFlag(parent, "scopedenum")) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ symname = newsymname;
+ }
+
+ {
+ // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
+ SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
+ if (debugMode) {
+ Printf(stdout, "Setting type: %s\n", Copy(typemap_lookup_type));
+ }
+ Setattr(n, "type", typemap_lookup_type);
+
+ // Simple integer constants
+ // Note these are always generated for anonymous enums, no matter what enum_feature is specified
+ // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
+
+ String *value = enumValue(n);
+ if (enum_values) {
+ Printf(enum_values, ",\n\"%s\" = %s", name, value);
+ } else {
+ enum_values = NewString("");
+ Printf(enum_values, "\"%s\" = %s", name, value);
+ }
+
+ Delete(value);
+ }
+
+ return SWIG_OK;
+}
+
+
+/* -------------------------------------------------------------
+ * Create accessor functions for variables.
+ * Does not create equivalent wrappers for enumerations,
+ * which are handled differently
+ * --------------------------------------------------------------*/
+
+int R::variableWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ if (debugMode) {
+ Printf(stdout, "variableWrapper %s\n", n);
+ }
+ processing_variable = 1;
+ Language::variableWrapper(n); // Force the emission of the _set and _get function wrappers.
+ processing_variable = 0;
+
+
+ SwigType *ty = Getattr(n, "type");
+ String *nodeType = nodeType(n);
+ int addCopyParam = addCopyParameter(ty);
+
+ //XXX
+ processType(ty, n);
+
+ if (nodeType && !Strcmp(nodeType, "enumitem")) {
+ /* special wrapper for enums - don't want the R _set, _get functions*/
+ if (debugMode) {
+ Printf(stdout, "variableWrapper enum branch\n");
+ }
+ } else if(!SwigType_isconst(ty)) {
+ Wrapper *f = NewWrapper();
+ Printf(f->def, "%s = \nfunction(value%s)\n{\n",
+ name, addCopyParam ? ", .copy = FALSE" : "");
+ Printv(f->code, "if(missing(value)) {\n",
+ name, "_get(", addCopyParam ? ".copy" : "", ")\n}", NIL);
+ Printv(f->code, " else {\n",
+ name, "_set(value)\n}\n}", NIL);
+
+ Wrapper_print(f, sfile);
+ DelWrapper(f);
+ } else {
+ Printf(sfile, "%s = %s_get\n", name, name);
+ }
+
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+ * Creates accessor functions for class members.
+
+ * ToDo - this version depends on naming conventions and needs
+ * to be replaced.
+ * --------------------------------------------------------------*/
+
+void R::addAccessor(String *memberName, Wrapper *wrapper, String *name,
+ String *methodSetGet) {
+
+ if (!class_member_function_names) {
+ class_member_function_names = NewList();
+ class_member_function_membernames = NewList();
+ class_member_function_wrappernames = NewList();
+ class_member_function_types = NewList();
+ }
+ Append(class_member_function_types, methodSetGet);
+ Append(class_member_function_names, name);
+ Append(class_member_function_membernames, memberName);
+
+ String *tmp = NewString("");
+ Wrapper_print(wrapper, tmp);
+ Append(class_member_function_wrappernames, tmp);
+ // if we could put the wrapper in directly: Append(l, Copy(sfun));
+ if (debugMode)
+ Printf(stdout, "Adding accessor: %s (%s) => %s\n", memberName, name, tmp);
+}
+
+#define MAX_OVERLOAD 256
+
+namespace {
+struct Overloaded {
+ Node *n; /* Node */
+ int argc; /* Argument count */
+ ParmList *parms; /* Parameters used for overload check */
+ int error; /* Ambiguity error */
+};
+}
+
+List * R::Swig_overload_rank(Node *n,
+ bool script_lang_wrapping) {
+ Overloaded nodes[MAX_OVERLOAD];
+ int nnodes = 0;
+ Node *o = Getattr(n,"sym:overloaded");
+
+
+ if (!o) return 0;
+
+ Node *c = o;
+ while (c) {
+ if (Getattr(c,"error")) {
+ c = Getattr(c,"sym:nextSibling");
+ continue;
+ }
+ /* Make a list of all the declarations (methods) that are overloaded with
+ * this one particular method name */
+
+ if (Getattr(c,"wrap:name")) {
+ nodes[nnodes].n = c;
+ nodes[nnodes].parms = Getattr(c,"wrap:parms");
+ nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
+ nodes[nnodes].error = 0;
+ nnodes++;
+ }
+ c = Getattr(c,"sym:nextSibling");
+ }
+
+ /* Sort the declarations by required argument count */
+ {
+ int i,j;
+ for (i = 0; i < nnodes; i++) {
+ for (j = i+1; j < nnodes; j++) {
+ if (nodes[i].argc > nodes[j].argc) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ }
+ }
+ }
+
+ /* Sort the declarations by argument types */
+ {
+ int i,j;
+ for (i = 0; i < nnodes-1; i++) {
+ if (nodes[i].argc == nodes[i+1].argc) {
+ for (j = i+1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
+ Parm *p1 = nodes[i].parms;
+ Parm *p2 = nodes[j].parms;
+ int differ = 0;
+ int num_checked = 0;
+ while (p1 && p2 && (num_checked < nodes[i].argc)) {
+ if (debugMode) {
+ Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
+ }
+ if (checkAttribute(p1,"tmap:in:numinputs","0")) {
+ p1 = Getattr(p1,"tmap:in:next");
+ continue;
+ }
+ if (checkAttribute(p2,"tmap:in:numinputs","0")) {
+ p2 = Getattr(p2,"tmap:in:next");
+ continue;
+ }
+ String *t1 = Getattr(p1,"tmap:typecheck:precedence");
+ String *t2 = Getattr(p2,"tmap:typecheck:precedence");
+ if (debugMode) {
+ Printf(stdout,"t1 = '%s', t2 = '%s'\n", t1, t2);
+ }
+ if ((!t1) && (!nodes[i].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
+ nodes[i].error = 1;
+ } else if ((!t2) && (!nodes[j].error)) {
+ Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s not supported (incomplete type checking rule - no precedence level in typecheck typemap for '%s').\n",
+ Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
+ nodes[j].error = 1;
+ }
+ if (t1 && t2) {
+ int t1v, t2v;
+ t1v = atoi(Char(t1));
+ t2v = atoi(Char(t2));
+ differ = t1v-t2v;
+ }
+ else if (!t1 && t2) differ = 1;
+ else if (t1 && !t2) differ = -1;
+ else if (!t1 && !t2) differ = -1;
+ num_checked++;
+ if (differ > 0) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ break;
+ } else if ((differ == 0) && (Strcmp(t1,"0") == 0)) {
+ t1 = Getattr(p1,"ltype");
+ if (!t1) {
+ t1 = SwigType_ltype(Getattr(p1,"type"));
+ if (Getattr(p1,"tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t1);
+ }
+ Setattr(p1,"ltype",t1);
+ }
+ t2 = Getattr(p2,"ltype");
+ if (!t2) {
+ t2 = SwigType_ltype(Getattr(p2,"type"));
+ if (Getattr(p2,"tmap:typecheck:SWIGTYPE")) {
+ SwigType_add_pointer(t2);
+ }
+ Setattr(p2,"ltype",t2);
+ }
+
+ /* Need subtype check here. If t2 is a subtype of t1, then we need to change the
+ order */
+
+ if (SwigType_issubtype(t2,t1)) {
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+
+ if (Strcmp(t1,t2) != 0) {
+ differ = 1;
+ break;
+ }
+ } else if (differ) {
+ break;
+ }
+ if (Getattr(p1,"tmap:in:next")) {
+ p1 = Getattr(p1,"tmap:in:next");
+ } else {
+ p1 = nextSibling(p1);
+ }
+ if (Getattr(p2,"tmap:in:next")) {
+ p2 = Getattr(p2,"tmap:in:next");
+ } else {
+ p2 = nextSibling(p2);
+ }
+ }
+ if (!differ) {
+ /* See if declarations differ by const only */
+ String *d1 = Getattr(nodes[i].n, "decl");
+ String *d2 = Getattr(nodes[j].n, "decl");
+ if (d1 && d2) {
+ String *dq1 = Copy(d1);
+ String *dq2 = Copy(d2);
+ if (SwigType_isconst(d1)) {
+ Delete(SwigType_pop(dq1));
+ }
+ if (SwigType_isconst(d2)) {
+ Delete(SwigType_pop(dq2));
+ }
+ if (Strcmp(dq1, dq2) == 0) {
+
+ if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
+ if (script_lang_wrapping) {
+ // Swap nodes so that the const method gets ignored (shadowed by the non-const method)
+ Overloaded t = nodes[i];
+ nodes[i] = nodes[j];
+ nodes[j] = t;
+ }
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
+ differ = 1;
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using non-const method %s instead.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ Delete(dq1);
+ Delete(dq2);
+ }
+ }
+ if (!differ) {
+ if (!nodes[j].error) {
+ if (script_lang_wrapping) {
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s effectively ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "as it is shadowed by %s.\n", Swig_name_decl(nodes[i].n));
+ } else {
+ if (!Getattr(nodes[j].n, "overload:ignore")) {
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
+ "Overloaded method %s ignored,\n", Swig_name_decl(nodes[j].n));
+ Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[i].n), Getline(nodes[i].n),
+ "using %s instead.\n", Swig_name_decl(nodes[i].n));
+ }
+ }
+ nodes[j].error = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ List *result = NewList();
+ {
+ int i;
+ for (i = 0; i < nnodes; i++) {
+ if (nodes[i].error)
+ Setattr(nodes[i].n, "overload:ignore", "1");
+ Append(result,nodes[i].n);
+ }
+ }
+ return result;
+}
+
+void R::dispatchFunction(Node *n) {
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *nodeType = Getattr(n, "nodeType");
+ bool constructor = (!Cmp(nodeType, "constructor"));
+
+ String *sfname = NewString(symname);
+
+ if (constructor)
+ Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
+
+ Printf(f->def,
+ "`%s` <- function(...) {", sfname);
+ if (debugMode) {
+ Swig_print_node(n);
+ }
+ List *dispatch = Swig_overload_rank(n, true);
+ int nfunc = Len(dispatch);
+ Printv(f->code,
+ "argtypes <- mapply(class, list(...));\n",
+ "argv <- list(...);\n",
+ "argc <- length(argtypes);\n",
+ "f <- NULL;\n", NIL);
+
+ Printf(f->code, "# dispatch functions %d\n", nfunc);
+ int cur_args = -1;
+ bool first_compare = true;
+ for (int i=0; i < nfunc; i++) {
+ Node *ni = Getitem(dispatch,i);
+ Parm *pi = Getattr(ni,"wrap:parms");
+ int num_arguments = emit_num_arguments(pi);
+
+ String *overname = Getattr(ni,"sym:overname");
+ if (cur_args != num_arguments) {
+ if (cur_args != -1) {
+ Printv(f->code, "} else ", NIL);
+ }
+ Printf(f->code, "if (argc == %d) {", num_arguments);
+ cur_args = num_arguments;
+ first_compare = true;
+ }
+ Parm *p;
+ int j;
+ if (num_arguments > 0) {
+ if (!first_compare) {
+ Printv(f->code, " else ", NIL);
+ } else {
+ first_compare = false;
+ }
+ Printv(f->code, "if (", NIL);
+ for (p = pi, j = 0 ; j < num_arguments ; j++) {
+ SwigType *pt = Getattr(p, "type");
+ if (debugMode) {
+ Swig_print_node(p);
+ }
+ String *tm = Swig_typemap_lookup("rtype", p, "", 0);
+ if (tm) {
+ replaceRClass(tm, pt);
+ }
+
+ /* Check if type have a %typemap(rtypecheck) */
+ String *tmcheck = Getattr(p,"tmap:rtypecheck");
+ if (tmcheck) {
+ tmcheck = Copy(tmcheck);
+ String *tmp_argtype = NewStringf("argtypes[%d]", j+1);
+ Replaceall(tmcheck, "$argtype", tmp_argtype);
+ String *tmp_arg = NewStringf("argv[[%d]]", j+1);
+ Replaceall(tmcheck, "$arg", tmp_arg);
+ replaceRClass(tmcheck, pt);
+ if (debugMode) {
+ Printf(stdout, "<rtypecheck>%s\n", tmcheck);
+ }
+ if (num_arguments == 1) {
+ Printf(f->code, "%s", tmcheck);
+ } else {
+ Printf(f->code, "%s(%s)", j == 0 ? "" : " && ", tmcheck);
+ }
+ Delete(tmcheck);
+ Delete(tmp_arg);
+ Delete(tmp_argtype);
+ } else {
+ Swig_warning(WARN_R_TYPEMAP_RTYPECHECK_UNDEF, input_file, line_number, "No rtypecheck typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+ Printf(f->code, ") { f <- %s%s; }\n", sfname, overname);
+ } else {
+ Printf(f->code, "f <- %s%s; ", sfname, overname);
+ }
+ }
+ if (cur_args != -1) {
+ Printf(f->code, "};\n");
+ }
+ Printf(f->code, "if (is.null(f)) {\n"
+ "stop(\"cannot find overloaded function for %s with argtypes (\","
+ "toString(argtypes),\")\");\n"
+ "}", sfname);
+ Printv(f->code, ";\nf(...)", NIL);
+ Printv(f->code, ";\n}", NIL);
+ Wrapper_print(f, sfile);
+ Printv(sfile, "# Dispatch function\n", NIL);
+ DelWrapper(f);
+}
+
+/*--------------------------------------------------------------
+
+* --------------------------------------------------------------*/
+
+int R::functionWrapper(Node *n) {
+ String *fname = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *returntype = Getattr(n, "type");
+
+ if (debugMode) {
+ Printf(stdout,
+ "<functionWrapper> %s %s %s\n", fname, iname, returntype);
+ }
+ String *overname = 0;
+ String *nodeType = Getattr(n, "nodeType");
+ bool constructor = (!Cmp(nodeType, "constructor"));
+ bool destructor = (!Cmp(nodeType, "destructor"));
+
+ String *sfname = NewString(iname);
+
+ if (constructor)
+ Replace(sfname, "new_", "", DOH_REPLACE_FIRST);
+
+ if (Getattr(n,"sym:overloaded")) {
+ overname = Getattr(n,"sym:overname");
+ Append(sfname, overname);
+ }
+
+ if (debugMode)
+ Printf(stdout,
+ "<functionWrapper> processing parameters\n");
+
+
+ ParmList *l = Getattr(n, "parms");
+ Parm *p;
+ String *tm;
+
+ p = l;
+ while(p) {
+ SwigType *resultType = Getattr(p, "type");
+ if (expandTypedef(resultType) &&
+ SwigType_istypedef(resultType)) {
+ SwigType *resolved =
+ SwigType_typedef_resolve_all(resultType);
+ if (expandTypedef(resolved)) {
+ if (debugMode) {
+ Printf(stdout, "Setting type: %s\n", resolved);
+ }
+ Setattr(p, "type", Copy(resolved));
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ String *unresolved_return_type = Copy(returntype);
+ if (expandTypedef(returntype) && SwigType_istypedef(returntype)) {
+ SwigType *resolved = SwigType_typedef_resolve_all(returntype);
+ if (debugMode)
+ Printf(stdout, "<functionWrapper> resolved %s\n", Copy(unresolved_return_type));
+ if (expandTypedef(resolved)) {
+ returntype = Copy(resolved);
+ Setattr(n, "type", returntype);
+ }
+ }
+ if (debugMode)
+ Printf(stdout, "<functionWrapper> unresolved_return_type %s\n", unresolved_return_type);
+ if(processing_member_access_function) {
+ if (debugMode)
+ Printf(stdout, "<functionWrapper memberAccess> '%s' '%s' '%s' '%s'\n", fname, iname, member_name, class_name);
+
+ if(opaqueClassDeclaration)
+ return SWIG_OK;
+
+
+ /* Add the name of this member to a list for this class_name.
+ We will dump all these at the end. */
+
+ bool isSet = GetFlag(n, "memberset") ? true : false;
+
+ String *tmp = NewString(isSet ? Swig_name_set(NSPACE_TODO, class_name) : Swig_name_get(NSPACE_TODO, class_name));
+
+ List *memList = Getattr(ClassMemberTable, tmp);
+ if(!memList) {
+ memList = NewList();
+ Append(memList, class_name);
+ Setattr(ClassMemberTable, tmp, memList);
+ }
+ Delete(tmp);
+ Append(memList, member_name);
+ Append(memList, iname);
+ }
+
+ int i;
+ int nargs;
+
+ String *wname = Swig_name_wrapper(iname);
+
+ if(overname)
+ Append(wname, overname);
+ Setattr(n,"wrap:name", wname);
+
+ Wrapper *f = NewWrapper();
+ Wrapper *sfun = NewWrapper();
+
+ int isVoidReturnType = (Strcmp(returntype, "void") == 0);
+ // Need to use the unresolved returntype since
+ // typedef resolution removes the const which causes a
+ // mismatch with the function action
+ emit_return_variable(n, unresolved_return_type, f);
+
+ SwigType *rtype = Getattr(n, "type");
+ int addCopyParam = 0;
+
+ if(!isVoidReturnType)
+ addCopyParam = addCopyParameter(rtype);
+
+ if (debugMode)
+ Printf(stdout, "Adding a .copy argument to %s for %s = %s\n", iname, returntype, addCopyParam ? "yes" : "no");
+
+ Printv(f->def, "SWIGEXPORT SEXP\n", wname, " ( ", NIL);
+
+ Printf(sfun->def, "# Start of %s\n", iname);
+ Printv(sfun->def, "\n`", sfname, "` = function(", NIL);
+
+ if(outputNamespaceInfo) {//XXX Need to be a little more discriminating
+ if (constructor) {
+ String *niname = Copy(iname);
+ Replace(niname, "new_", "", DOH_REPLACE_FIRST);
+ addNamespaceFunction(niname);
+ Delete(niname);
+ } else {
+ addNamespaceFunction(iname);
+ }
+ }
+
+ Swig_typemap_attach_parms("scoercein", l, f);
+ Swig_typemap_attach_parms("scoerceout", l, f);
+ Swig_typemap_attach_parms("scheck", l, f);
+ Swig_typemap_attach_parms("rtypecheck", l, f);
+
+ emit_parameter_variables(l, f);
+ emit_attach_parmmaps(l,f);
+ Setattr(n,"wrap:parms",l);
+
+ nargs = emit_num_arguments(l);
+
+ Wrapper_add_local(f, "r_nprotect", "unsigned int r_nprotect = 0");
+ Wrapper_add_localv(f, "r_ans", "SEXP", "r_ans = R_NilValue", NIL);
+ Wrapper_add_localv(f, "r_vmax", "VMAXTYPE", "r_vmax = vmaxget()", NIL);
+
+ String *sargs = NewString("");
+
+
+ String *s_inputTypes = NewString("");
+ String *s_inputMap = NewString("");
+ bool inFirstArg = true;
+ bool inFirstType = true;
+ Parm *curP;
+ for (p =l, i = 0 ; i < nargs ; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *tt = Getattr(p, "type");
+ int nargs = -1;
+ String *funcptr_name = processType(tt, p, &nargs);
+
+ String *name = makeParameterName(n, p, i+1, false);
+ String *lname = Getattr(p, "lname");
+
+ if (name) {
+ /* If we have a :: in the parameter name because we are accessing a static member of a class, say, then
+ we need to remove that prefix. */
+ while (Strstr(name, "::")) {
+ String *oldname = name;
+ name = NewStringf("%s", Strchr(name, ':') + 2);
+ if (debugMode)
+ Printf(stdout, "+++ parameter name with :: in it %s\n", name);
+ Delete(oldname);
+ }
+ }
+
+ name = replaceInitialDash(name);
+
+ if (!Strncmp(name, "arg", 3)) {
+ name = Copy(name);
+ Insert(name, 0, "s_");
+ }
+
+ if(processing_variable) {
+ name = Copy(name);
+ Insert(name, 0, "s_");
+ }
+
+ if(!Strcmp(name, fname)) {
+ name = Copy(name);
+ Insert(name, 0, "s_");
+ }
+
+ Printf(sargs, "%s, ", name);
+
+ String *tm;
+ if((tm = Getattr(p, "tmap:scoercein"))) {
+ Replaceall(tm, "$input", name);
+ replaceRClass(tm, Getattr(p, "type"));
+
+ if(funcptr_name) {
+ //XXX need to get this to return non-zero
+ if(nargs == -1)
+ nargs = getFunctionPointerNumArgs(p, tt);
+
+ String *snargs = NewStringf("%d", nargs);
+ Printv(sfun->code, "if(is.function(", name, ")) {", "\n",
+ "assert('...' %in% names(formals(", name,
+ ")) || length(formals(", name, ")) >= ", snargs, ");\n} ", NIL);
+ Delete(snargs);
+
+ Printv(sfun->code, "else {\n",
+ "if(is.character(", name, ")) {\n",
+ name, " = getNativeSymbolInfo(", name, ");",
+ "\n};\n",
+ "if(is(", name, ", \"NativeSymbolInfo\")) {\n",
+ name, " = ", name, "$address", ";\n};\n",
+ "if(is(", name, ", \"ExternalReference\")) {\n",
+ name, " = ", name, "@ref;\n}\n",
+ "}; \n",
+ NIL);
+ } else {
+ Printf(sfun->code, "%s\n", tm);
+ }
+ }
+
+ Printv(sfun->def, inFirstArg ? "" : ", ", name, NIL);
+
+ if ((tm = Getattr(p,"tmap:scheck"))) {
+
+ Replaceall(tm,"$input", name);
+ replaceRClass(tm, Getattr(p, "type"));
+ Printf(sfun->code,"%s\n",tm);
+ }
+
+
+
+ curP = p;
+ if ((tm = Getattr(p,"tmap:in"))) {
+
+ Replaceall(tm,"$input", name);
+
+ if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) {
+ Replaceall(tm,"$disown","SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm,"$disown","0");
+ }
+
+ if(funcptr_name) {
+ /* have us a function pointer */
+ Printf(f->code, "if(TYPEOF(%s) != CLOSXP) {\n", name);
+ Replaceall(tm,"$R_class", "");
+ } else {
+ replaceRClass(tm, Getattr(p, "type"));
+ }
+
+
+ Printf(f->code,"%s\n",tm);
+ if(funcptr_name)
+ Printf(f->code, "} else {\n%s = %s;\nR_SWIG_pushCallbackFunctionData(%s, NULL);\n}\n",
+ lname, funcptr_name, name);
+ Printv(f->def, inFirstArg ? "" : ", ", "SEXP ", name, NIL);
+ if (Len(name) != 0)
+ inFirstArg = false;
+ p = Getattr(p,"tmap:in:next");
+
+ } else {
+ p = nextSibling(p);
+ }
+
+
+ tm = Swig_typemap_lookup("rtype", curP, "", 0);
+ if(tm) {
+ replaceRClass(tm, Getattr(curP, "type"));
+ }
+ Printf(s_inputTypes, "%s'%s'", inFirstType ? "" : ", ", tm);
+ Printf(s_inputMap, "%s%s='%s'", inFirstType ? "" : ", ", name, tm);
+ inFirstType = false;
+
+ if(funcptr_name)
+ Delete(funcptr_name);
+ } /* end of looping over parameters. */
+
+ if(addCopyParam) {
+ Printf(sfun->def, "%s.copy = FALSE", nargs > 0 ? ", " : "");
+ Printf(f->def, "%sSEXP s_swig_copy", nargs > 0 ? ", " : "");
+
+ Printf(sargs, "as.logical(.copy), ");
+ }
+
+ Printv(f->def, ")\n{\n", NIL);
+ // SWIG_fail in R leads to a call to Rf_error() which calls longjmp()
+ // which means the destructors of any live function-local C++ objects won't
+ // get run. To avoid this happening, we wrap almost everything in the
+ // function in a block, and end that right before Rf_error() at which
+ // point those destructors will get called.
+ if (CPlusPlus) Append(f->def, "{\n");
+
+ Printv(sfun->def, ")\n{\n", NIL);
+
+
+ /* Insert cleanup code */
+ String *cleanup = NewString("");
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ if (tm && (Len(tm) != 0)) {
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ String *outargs = NewString("");
+ int numOutArgs = isVoidReturnType ? -1 : 0;
+ for(p = l, i = 0; p; i++) {
+ if((tm = Getattr(p, "tmap:argout"))) {
+ // String *lname = Getattr(p, "lname");
+ numOutArgs++;
+ String *pos = NewStringf("%d", numOutArgs);
+ Replaceall(tm,"$result", "r_ans");
+ Replaceall(tm,"$n", pos); // The position into which to store the answer.
+ Replaceall(tm,"$arg", Getattr(p, "emit:input"));
+ Replaceall(tm,"$input", Getattr(p, "emit:input"));
+ Replaceall(tm,"$owner", "0");
+
+
+ Printf(outargs, "%s\n", tm);
+ p = Getattr(p,"tmap:argout:next");
+ } else
+ p = nextSibling(p);
+ }
+
+ String *actioncode = emit_action(n);
+
+ /* Deal with the explicit return value. */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+ SwigType *retType = Getattr(n, "type");
+
+ Replaceall(tm,"$1", Swig_cresult_name());
+ Replaceall(tm,"$result", "r_ans");
+ if (debugMode){
+ Printf(stdout, "Calling replace D: %s, %s, %s\n", retType, n, tm);
+ }
+ replaceRClass(tm, retType);
+
+ if (GetFlag(n,"feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm,"$owner", "0");
+ }
+
+ Printf(f->code, "%s\n", tm);
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), fname);
+ }
+
+
+ if(Len(outargs)) {
+ Wrapper_add_local(f, "R_OutputValues", "SEXP R_OutputValues");
+
+ String *tmp = NewString("");
+ if(!isVoidReturnType)
+ Printf(tmp, "Rf_protect(r_ans);\n");
+
+ Printf(tmp, "Rf_protect(R_OutputValues = Rf_allocVector(VECSXP,%d));\nr_nprotect += %d;\n",
+ numOutArgs + !isVoidReturnType,
+ isVoidReturnType ? 1 : 2);
+
+ if(!isVoidReturnType)
+ Printf(tmp, "SET_VECTOR_ELT(R_OutputValues, 0, r_ans);\n");
+ Printf(tmp, "r_ans = R_OutputValues;\n");
+
+ Insert(outargs, 0, tmp);
+ Delete(tmp);
+
+
+
+ Printv(f->code, outargs, NIL);
+ Delete(outargs);
+
+ }
+
+ /* Output cleanup code */
+ int need_cleanup = Len(cleanup) != 0;
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ Printv(f->code, UnProtectWrapupCode, NIL);
+
+ /*If the user gave us something to convert the result in */
+ if ((tm = Swig_typemap_lookup("scoerceout", n, Swig_cresult_name(), sfun))) {
+ Replaceall(tm,"$result","ans");
+ if (debugMode) {
+ Printf(stdout, "Calling replace B: %s, %s, %s\n", Getattr(n, "type"), Getattr(n, "sym:name"), getNSpace());
+ }
+ replaceRClass(tm, Getattr(n, "type"));
+ Chop(tm);
+ }
+
+
+ Printv(sfun->code, ";", (Len(tm) ? "ans = " : ""), ".Call('", wname,
+ "', ", sargs, "PACKAGE='", Rpackage, "');\n", NIL);
+ if(Len(tm))
+ {
+ Printf(sfun->code, "%s\n\n", tm);
+ if (constructor)
+ {
+ String *finalizer = NewString(iname);
+ Replace(finalizer, "new_", "", DOH_REPLACE_FIRST);
+ Printf(sfun->code, "reg.finalizer(ans@ref, delete_%s);\n", finalizer);
+ }
+ Printf(sfun->code, "ans\n");
+ }
+
+ if (destructor)
+ Printv(f->code, "R_ClearExternalPtr(self);\n", NIL);
+
+ Printv(f->code, "return r_ans;\n", NIL);
+
+ /* Error handling code */
+ Printv(f->code, "fail: SWIGUNUSED;\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ if (CPlusPlus) Append(f->code, "}\n");
+ Printv(f->code, " Rf_error(\"%s %s\", SWIG_ErrorType(SWIG_lasterror_code), SWIG_lasterror_msg);\n", NIL);
+ Printv(f->code, " return R_NilValue;\n", NIL);
+ Delete(cleanup);
+
+ Printv(f->code, "}\n", NIL);
+ Printv(sfun->code, "\n}", NIL);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code,"$symname",iname);
+
+ Wrapper_print(f, f_wrapper);
+ Wrapper_print(sfun, sfile);
+
+ Printf(sfun->code, "\n# End of %s\n", iname);
+ tm = Swig_typemap_lookup("rtype", n, "", 0);
+ if(tm) {
+ SwigType *retType = Getattr(n, "type");
+ if (debugMode) {
+ Printf(stdout, "Calling replace C: %s\n", Copy(retType));
+ }
+ replaceRClass(tm, retType);
+ }
+
+ Printv(sfile, "attr(`", sfname, "`, 'returnType') = '",
+ isVoidReturnType ? "void" : (tm ? tm : ""),
+ "'\n", NIL);
+
+ if(nargs > 0)
+ Printv(sfile, "attr(`", sfname, "`, \"inputTypes\") = c(",
+ s_inputTypes, ")\n", NIL);
+ Printv(sfile, "class(`", sfname, "`) = c(\"SWIGFunction\", class('",
+ sfname, "'))\n\n", NIL);
+
+ if (memoryProfile) {
+ Printv(sfile, "memory.profile()\n", NIL);
+ }
+ if (aggressiveGc) {
+ Printv(sfile, "gc()\n", NIL);
+ }
+
+ // Printv(sfile, "setMethod('", name, "', '", name, "', ", iname, ")\n\n\n");
+
+
+
+ /* If we are dealing with a method in an C++ class, then
+ add the name of the R function and its definition.
+ XXX need to figure out how to store the Wrapper if possible in the hash/list.
+ Would like to be able to do this so that we can potentially insert
+ */
+ if(processing_member_access_function || processing_class_member_function) {
+ String *method_type = R_MEMBER_NORMAL;
+ if (GetFlag(n, "memberset")) {
+ method_type = R_MEMBER_SET;
+ } else if (GetFlag(n, "memberget")) {
+ method_type = R_MEMBER_GET;
+ }
+ addAccessor(member_name, sfun, iname, method_type);
+ }
+
+ if (Getattr(n, "sym:overloaded") &&
+ !Getattr(n, "sym:nextSibling")) {
+ dispatchFunction(n);
+ }
+
+ addRegistrationRoutine(wname, addCopyParam ? nargs +1 : nargs);
+
+ DelWrapper(f);
+ DelWrapper(sfun);
+
+ Delete(sargs);
+ Delete(sfname);
+ return SWIG_OK;
+}
+
+/* ----------------------------------------------------------------------
+ * R::constantWrapper()
+ * ---------------------------------------------------------------------- */
+
+int R::constantWrapper(Node *n) {
+ (void) n;
+ // TODO
+ return SWIG_OK;
+}
+
+/*--------------------------------------------------------------
+ * Add the specified routine name to the collection of
+ * generated routines that are called from R functions.
+ * This is used to register the routines with R for
+ * resolving symbols.
+
+ * rname - the name of the routine
+ * nargs - the number of arguments it expects.
+ * --------------------------------------------------------------*/
+
+int R::addRegistrationRoutine(String *rname, int nargs) {
+ if(!registrationTable)
+ registrationTable = NewHash();
+
+ String *el =
+ NewStringf("{\"%s\", (DL_FUNC) &%s, %d}", rname, rname, nargs);
+
+ Setattr(registrationTable, rname, el);
+
+ return SWIG_OK;
+}
+
+/* -------------------------------------------------------------
+ * Write the registration information to an array and
+ * create the initialization routine for registering
+ * these.
+ * --------------------------------------------------------------*/
+
+int R::outputRegistrationRoutines(File *out) {
+ int i, n;
+ if(!registrationTable)
+ return(0);
+ if(inCPlusMode)
+ Printf(out, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n");
+
+ Printf(out, "#include <R_ext/Rdynload.h>\n\n");
+ if(inCPlusMode)
+ Printf(out, "#ifdef __cplusplus\n}\n#endif\n\n");
+
+ Printf(out, "SWIGINTERN R_CallMethodDef CallEntries[] = {\n");
+
+ List *keys = Keys(registrationTable);
+ n = Len(keys);
+ for(i = 0; i < n; i++)
+ Printf(out, " %s,\n", Getattr(registrationTable, Getitem(keys, i)));
+
+ Printf(out, " {NULL, NULL, 0}\n};\n\n");
+
+ if(!noInitializationCode) {
+ if (inCPlusMode)
+ Printv(out, "extern \"C\" ", NIL);
+ { /* R allows pckage names to have '.' in the name, which is not allowed in C++ var names
+ we simply replace all occurrences of '.' with '_' to construct the var name */
+ String * Rpackage_sane = Copy(Rpackage);
+ Replace(Rpackage_sane, ".", "_", DOH_REPLACE_ANY);
+ Printf(out, "SWIGEXPORT void R_init_%s(DllInfo *dll) {\n", Rpackage_sane);
+ Delete(Rpackage_sane);
+ }
+ Printf(out, "%sR_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n", tab4);
+ if(Len(s_init_routine)) {
+ Printf(out, "\n%s\n", s_init_routine);
+ }
+ Printf(out, "}\n");
+ }
+
+ return n;
+}
+
+
+
+/* -------------------------------------------------------------
+ * Process a struct, union or class declaration in the source code,
+ * or an anonymous typedef struct
+ * --------------------------------------------------------------*/
+
+//XXX What do we need to do here -
+// Define an S4 class to refer to this.
+
+void R::registerClass(Node *n) {
+ String *name = Getattr(n, "name");
+
+ if (debugMode)
+ Swig_print_node(n);
+ String *sname = NewStringf("_p%s", SwigType_manglestr(name));
+ if(!Getattr(SClassDefs, sname)) {
+ Setattr(SClassDefs, sname, sname);
+ String *base;
+
+ if (CPlusPlus && (Strcmp(nodeType(n), "class") == 0)) {
+ base = NewString("");
+ List *l = Getattr(n, "bases");
+ if(Len(l)) {
+ Printf(base, "c(");
+ for(int i = 0; i < Len(l); i++) {
+ registerClass(Getitem(l, i));
+ Printf(base, "'_p%s'%s",
+ SwigType_manglestr(Getattr(Getitem(l, i), "name")),
+ i < Len(l)-1 ? ", " : "");
+ }
+ Printf(base, ")");
+ } else {
+ base = NewString("'C++Reference'");
+ }
+ } else
+ base = NewString("'ExternalReference'");
+
+ Printf(s_classes, "setClass('%s', contains = %s)\n", sname, base);
+ Delete(base);
+ }
+}
+
+int R::classDeclaration(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *kind = Getattr(n, "kind");
+
+ if (debugMode)
+ Swig_print_node(n);
+ registerClass(n);
+
+
+ /* If we have a typedef union { ... } U, then we never get to see the typedef
+ via a regular call to typedefHandler. Instead, */
+ if(Getattr(n, "unnamed") && Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "typedef") == 0
+ && Getattr(n, "tdname") && Strcmp(Getattr(n, "tdname"), name) == 0) {
+ if (debugMode)
+ Printf(stdout, "Typedef in the class declaration for %s\n", name);
+ // typedefHandler(n);
+ }
+
+ bool opaque = GetFlag(n, "feature:opaque") ? true : false;
+
+ if(opaque)
+ opaqueClassDeclaration = name;
+
+ int status = Language::classDeclaration(n);
+
+ opaqueClassDeclaration = NULL;
+
+
+ if (class_member_function_types) {
+
+ // collect the "set" methods
+ List *class_set_membernames = filterMemberList(class_member_function_types,
+ class_member_function_membernames, R_MEMBER_SET, true);
+ List *class_set_functionnames = filterMemberList(class_member_function_types,
+ class_member_function_names, R_MEMBER_SET, true);
+ // this one isn't used - collecting to keep code simpler
+ List *class_set_functiontypes = filterMemberList(class_member_function_types,
+ class_member_function_types, R_MEMBER_SET, true);
+
+ // collect the others
+ List *class_other_membernames = filterMemberList(class_member_function_types,
+ class_member_function_membernames, R_MEMBER_SET, false);
+ List *class_other_functionnames = filterMemberList(class_member_function_types,
+ class_member_function_names, R_MEMBER_SET, false);
+ List *class_other_functiontypes = filterMemberList(class_member_function_types,
+ class_member_function_types, R_MEMBER_SET, false);
+
+ if (Len(class_other_membernames) > 0) {
+ OutputMemberReferenceMethod(name, 0, class_other_membernames, class_other_functionnames, class_other_functiontypes, sfile);
+ }
+ if (Len(class_set_membernames) > 0) {
+ OutputMemberReferenceMethod(name, 1, class_set_membernames, class_set_functionnames, class_set_functiontypes, sfile);
+ }
+ Delete(class_set_membernames);
+ Delete(class_set_functionnames);
+ Delete(class_set_functiontypes);
+ Delete(class_other_membernames);
+ Delete(class_other_functionnames);
+ Delete(class_other_functiontypes);
+ }
+
+ if (class_member_function_types) {
+ Delete(class_member_function_types);
+ class_member_function_types = NULL;
+ Delete(class_member_function_names);
+ class_member_function_names = NULL;
+ Delete(class_member_function_membernames);
+ class_member_function_membernames = NULL;
+ Delete(class_member_function_wrappernames);
+ class_member_function_wrappernames = NULL;
+ }
+ if (Getattr(n, "has_destructor")) {
+ Printf(sfile, "setMethod('delete', '_p%s', function(obj) {delete%s(obj)})\n", getRClassName(name), getRClassName(name));
+
+ }
+ if(!opaque && !Strcmp(kind, "struct") && copyStruct) {
+
+ String *def =
+ NewStringf("setClass(\"%s\",\n%srepresentation(\n", name, tab4);
+ bool firstItem = true;
+
+ for(Node *c = firstChild(n); c; ) {
+ String *elName;
+ String *tp;
+
+ elName = Getattr(c, "name");
+
+ String *elKind = Getattr(c, "kind");
+ if (!Equal(elKind, "variable")) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (!Len(elName)) {
+ c = nextSibling(c);
+ continue;
+ }
+ tp = Swig_typemap_lookup("rtype", c, "", 0);
+ if(!tp) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (Strstr(tp, "R_class")) {
+ c = nextSibling(c);
+ continue;
+ }
+ if (Strcmp(tp, "character") &&
+ Strstr(Getattr(c, "decl"), "p.")) {
+ c = nextSibling(c);
+ continue;
+ }
+
+ if (!firstItem) {
+ Printf(def, ",\n");
+ }
+ // else
+ //XXX How can we tell if this is already done.
+ // SwigType_push(elType, elDecl);
+
+
+ // returns "" tp = processType(elType, c, NULL);
+ // Printf(stdout, "<classDeclaration> elType %p\n", elType);
+ // tp = getRClassNameCopyStruct(Getattr(c, "type"), 1);
+
+ String *elNameT = replaceInitialDash(elName);
+ Printf(def, "%s%s = \"%s\"", tab8, elNameT, tp);
+ firstItem = false;
+ Delete(tp);
+ Delete(elNameT);
+ c = nextSibling(c);
+ }
+ Printf(def, "),\n%scontains = \"RSWIGStruct\")\n", tab8);
+ Printf(s_classes, "%s\n\n# End class %s\n\n", def, name);
+
+ generateCopyRoutines(n);
+
+ Delete(def);
+ }
+
+ return status;
+}
+
+
+
+/* -------------------------------------------------------------
+ * Create the C routines that copy an S object of the class given
+ * by the given struct definition in Node *n to the C value
+ * and also the routine that goes from the C routine to an object
+ * of this S class.
+ * --------------------------------------------------------------*/
+
+/*XXX
+ Clean up the toCRef - make certain the names are correct for the types, etc.
+ in all cases.
+*/
+
+int R::generateCopyRoutines(Node *n) {
+ Wrapper *copyToR = NewWrapper();
+ Wrapper *copyToC = NewWrapper();
+
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *kind = Getattr(n, "kind");
+ String *type;
+
+ if(Len(tdname)) {
+ type = Copy(tdname);
+ } else {
+ type = NewStringf("%s %s", kind, name);
+ }
+
+ String *mangledName = SwigType_manglestr(name);
+
+ if (debugMode)
+ Printf(stdout, "generateCopyRoutines: name = %s, %s\n", name, type);
+
+ Printf(copyToR->def, "CopyToR%s = function(value, obj = new(\"%s\"))\n{\n",
+ mangledName, name);
+ Printf(copyToC->def, "CopyToC%s = function(value, obj)\n{\n",
+ mangledName);
+
+ Node *c = firstChild(n);
+
+ for(; c; c = nextSibling(c)) {
+ String *elName = Getattr(c, "name");
+ if (!Len(elName)) {
+ continue;
+ }
+ String *elKind = Getattr(c, "kind");
+ if (!Equal(elKind, "variable")) {
+ continue;
+ }
+
+ String *tp = Swig_typemap_lookup("rtype", c, "", 0);
+ if(!tp) {
+ continue;
+ }
+ if (Strstr(tp, "R_class")) {
+ continue;
+ }
+ if (Strcmp(tp, "character") &&
+ Strstr(Getattr(c, "decl"), "p.")) {
+ continue;
+ }
+
+
+ /* The S functions to get and set the member value. */
+ String *elNameT = replaceInitialDash(elName);
+ Printf(copyToR->code, "obj@%s = value$%s;\n", elNameT, elNameT);
+ Printf(copyToC->code, "obj$%s = value@%s;\n", elNameT, elNameT);
+ Delete(elNameT);
+ }
+ Printf(copyToR->code, "obj;\n}\n\n");
+ String *rclassName = getRClassNameCopyStruct(type, 0); // without the Ref.
+ Printf(sfile, "# Start definition of copy functions & methods for %s\n", rclassName);
+
+ Wrapper_print(copyToR, sfile);
+ Printf(copyToC->code, "obj\n}\n\n");
+ Wrapper_print(copyToC, sfile);
+
+
+ Printf(sfile, "# Start definition of copy methods for %s\n", rclassName);
+ Printf(sfile, "setMethod('copyToR', '_p%s', CopyToR%s);\n", mangledName,
+ mangledName);
+ Printf(sfile, "setMethod('copyToC', '%s', CopyToC%s);\n\n", rclassName,
+ mangledName);
+
+ Printf(sfile, "# End definition of copy methods for %s\n", rclassName);
+ Printf(sfile, "# End definition of copy functions & methods for %s\n", rclassName);
+
+ String *m = NewStringf("%sCopyToR", name);
+ addNamespaceMethod(m);
+ char *tt = Char(m); tt[Len(m)-1] = 'C';
+ addNamespaceMethod(m);
+ Delete(m);
+ Delete(rclassName);
+ Delete(mangledName);
+ DelWrapper(copyToR);
+ DelWrapper(copyToC);
+
+ return SWIG_OK;
+}
+
+
+
+/* -------------------------------------------------------------
+ * Called when there is a typedef to be invoked.
+ *
+ * XXX Needs to be enhanced or split to handle the case where we have a
+ * typedef within a classDeclaration emission because the struct/union/etc.
+ * is anonymous.
+ * --------------------------------------------------------------*/
+
+int R::typedefHandler(Node *n) {
+ SwigType *tp = Getattr(n, "type");
+ String *type = Getattr(n, "type");
+ if (debugMode)
+ Printf(stdout, "<typedefHandler> %s\n", Getattr(n, "name"));
+
+ processType(tp, n);
+
+ if(Strncmp(type, "struct ", 7) == 0) {
+ String *name = Getattr(n, "name");
+ char *trueName = Char(type);
+ trueName += 7;
+ if (debugMode)
+ Printf(stdout, "<typedefHandler> Defining S class %s\n", trueName);
+ Printf(s_classes, "setClass('_p%s', contains = 'ExternalReference')\n",
+ SwigType_manglestr(name));
+ }
+
+ return Language::typedefHandler(n);
+}
+
+
+
+/* --------------------------------------------------------------
+ * Called when processing a field in a "class", i.e. struct, union or
+ * actual class. We set a state variable so that we can correctly
+ * interpret the resulting functionWrapper() call and understand that
+ * it is for a field element.
+ * --------------------------------------------------------------*/
+
+int R::membervariableHandler(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ processType(t, n, NULL);
+ processing_member_access_function = 1;
+ member_name = Getattr(n,"sym:name");
+ if (debugMode)
+ Printf(stdout, "<membervariableHandler> name = %s, sym:name = %s\n",
+ Getattr(n, "name"), member_name);
+
+ int status(Language::membervariableHandler(n));
+
+ if(!opaqueClassDeclaration && debugMode)
+ Printf(stdout, "<membervariableHandler> %s %s\n", Getattr(n, "name"), Getattr(n, "type"));
+
+ processing_member_access_function = 0;
+ member_name = NULL;
+
+ return status;
+}
+
+
+/*
+ This doesn't seem to get used so leave it out for the moment.
+*/
+String * R::runtimeCode() {
+ String *s = Swig_include_sys("rrun.swg");
+ if (!s) {
+ Printf(stdout, "*** Unable to open 'rrun.swg'\n");
+ s = NewString("");
+ }
+ return s;
+}
+
+/*----------------------------------------------------------------------
+ * replaceSpecialVariables()
+ *--------------------------------------------------------------------*/
+
+void R::replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+ replaceRClass(tm, type);
+}
+
+
+/* -----------------------------------------------------------------------
+ * Called when SWIG wants to initialize this
+ * We initialize anythin we want here.
+ * Most importantly, tell SWIG where to find the files (e.g. r.swg) for this module.
+ * Use Swig_mark_arg() to tell SWIG that it is understood and not to
+ * throw an error.
+ * --------------------------------------------------------------*/
+
+void R::main(int argc, char *argv[]) {
+ init();
+ Preprocessor_define("SWIGR 1", 0);
+ SWIG_library_directory("r");
+ SWIG_config_file("r.swg");
+ debugMode = false;
+ copyStruct = true;
+ memoryProfile = false;
+ aggressiveGc = false;
+ inCPlusMode = false;
+ outputNamespaceInfo = false;
+ noInitializationCode = false;
+
+ this->Argc = argc;
+ this->Argv = argv;
+
+ allow_overloading();// can we support this?
+
+ for(int i = 0; i < argc; i++) {
+ if(strcmp(argv[i], "-package") == 0) {
+ Swig_mark_arg(i);
+ i++;
+ Swig_mark_arg(i);
+ Rpackage = argv[i];
+ } else if(strcmp(argv[i], "-dll") == 0) {
+ Swig_mark_arg(i);
+ i++;
+ Swig_mark_arg(i);
+ DllName = argv[i];
+ } else if(strcmp(argv[i], "-help") == 0) {
+ showUsage();
+ } else if(strcmp(argv[i], "-namespace") == 0) {
+ outputNamespaceInfo = true;
+ Swig_mark_arg(i);
+ } else if(!strcmp(argv[i], "-no-init-code")) {
+ noInitializationCode = true;
+ Swig_mark_arg(i);
+ } else if(!strcmp(argv[i], "-c++")) {
+ inCPlusMode = true;
+ Swig_mark_arg(i);
+ Printf(s_classes, "setClass('C++Reference', contains = 'ExternalReference')\n");
+ } else if(!strcmp(argv[i], "-debug")) {
+ debugMode = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i],"-copystruct")) {
+ copyStruct = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-nocopystruct")) {
+ copyStruct = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-memoryprof")) {
+ memoryProfile = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-nomemoryprof")) {
+ memoryProfile = false;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-aggressivegc")) {
+ aggressiveGc = true;
+ Swig_mark_arg(i);
+ } else if (!strcmp(argv[i], "-noaggressivegc")) {
+ aggressiveGc = false;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ Exit(EXIT_FAILURE);
+ }
+
+ if (debugMode) {
+ Swig_typemap_search_debug_set();
+ Swig_typemap_used_debug_set();
+ Swig_typemap_register_debug_set();
+ Swig_file_debug_set();
+ }
+ /// copyToR copyToC functions.
+
+ }
+}
+
+/* -----------------------------------------------------------------------
+ * Could make this work for String or File and then just store the resulting string
+ * rather than the collection of arguments and argc.
+ * ----------------------------------------------------------------------- */
+int R::outputCommandLineArguments(File *out)
+{
+ if(Argc < 1 || !Argv || !Argv[0])
+ return(-1);
+
+ Printf(out, "\n## Generated via the command line invocation:\n##\t");
+ for(int i = 0; i < Argc ; i++) {
+ Printf(out, " %s", Argv[i]);
+ }
+ Printf(out, "\n\n\n");
+
+ return Argc;
+}
+
+
+
+/* How SWIG instantiates an object from this module.
+ See swigmain.cxx */
+extern "C"
+Language *swig_r(void) {
+ return new R();
+}
+
+
+
+
+/* -----------------------------------------------------------------------
+ * Needs to be reworked.
+ *----------------------------------------------------------------------- */
+String * R::processType(SwigType *t, Node *n, int *nargs) {
+ //XXX Need to handle typedefs, e.g.
+ // a type which is a typedef to a function pointer.
+
+ SwigType *tmp = Getattr(n, "tdname");
+ if (debugMode)
+ Printf(stdout, "processType %s (tdname = %s)(SwigType = %s)\n", Getattr(n, "name"), tmp, Copy(t));
+
+ SwigType *td = t;
+ if (expandTypedef(t) &&
+ SwigType_istypedef(t)) {
+ SwigType *resolved =
+ SwigType_typedef_resolve_all(t);
+ if (expandTypedef(resolved)) {
+ td = Copy(resolved);
+ }
+ }
+
+ if(!td) {
+ int count = 0;
+ String *b = getRTypeName(t, &count);
+ if(count && b && !Getattr(SClassDefs, b)) {
+ if (debugMode)
+ Printf(stdout, "<processType> Defining class %s\n", b);
+
+ Printf(s_classes, "setClass('%s', contains = 'ExternalReference')\n", b);
+ Setattr(SClassDefs, b, b);
+ }
+
+ }
+
+
+ if(td)
+ t = td;
+
+ if(SwigType_isfunctionpointer(t)) {
+ if (debugMode)
+ Printf(stdout,
+ "<processType> Defining pointer handler %s\n", t);
+
+ String *tmp = createFunctionPointerHandler(t, n, nargs);
+ return tmp;
+ }
+
+ return NULL;
+}
+
+
+/* -----------------------------------------------------------------------
+ * enumValue()
+ * This method will return a string with an enum value to use in from R when
+ * setting up an enum variable
+ * ------------------------------------------------------------------------ */
+
+String *R::enumValue(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *value = Getattr(n, "value");
+ String *newsymname = 0;
+
+ Node *parent = parentNode(n);
+ symname = Getattr(n, "sym:name");
+
+ // parent enumtype has namespace mangled in
+ String *etype = Getattr(parent, "enumtype");
+ // we have to directly call the c wrapper function, as the
+ // R wrapper to the enum is designed to be used after the enum
+ // structures have been created on the R side. This means
+ // that we'll need to construct a .Call expression
+
+ // change the type for variableWrapper
+ if (debugMode) {
+ Printf(stdout, "<enumValue> type set: %s\n", etype);
+ }
+
+ Setattr(n, "type", etype);
+
+ if (!getCurrentClass()) {
+ newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ // Strange hack to change the name
+ Setattr(n, "name", Getattr(n, "value"));
+ Setattr(n, "sym:name", newsymname);
+ variableWrapper(n);
+ value = Swig_name_get(NSPACE_TODO, newsymname);
+ } else {
+ String *enumClassPrefix = getEnumClassPrefix();
+ newsymname = Swig_name_member(0, enumClassPrefix, symname);
+ Setattr(n, "name", Getattr(n, "value"));
+ Setattr(n, "sym:name", newsymname);
+ variableWrapper(n);
+ value = Swig_name_get(NSPACE_TODO, newsymname);
+ }
+ value = Swig_name_wrapper(value);
+ Replace(value, "_wrap", "R_swig", DOH_REPLACE_FIRST);
+
+ String *valuecall=NewString("");
+ Printv(valuecall, ".Call('", value, "',FALSE, PACKAGE='", Rpackage, "')", NIL);
+ Delete(value);
+ return valuecall;
+}
diff --git a/contrib/tools/swig/Source/Modules/ruby.cxx b/contrib/tools/swig/Source/Modules/ruby.cxx
new file mode 100644
index 00000000000..44f2596ddb7
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/ruby.cxx
@@ -0,0 +1,3468 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * ruby.cxx
+ *
+ * Ruby language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+#include <string.h>
+#include <limits.h> /* for INT_MAX */
+
+#define SWIG_PROTECTED_TARGET_METHODS 1
+
+class RClass {
+private:
+ String *temp;
+
+public:
+ String *name; /* class name (renamed) */
+ String *cname; /* original C class/struct name */
+ String *mname; /* Mangled name */
+
+ /**
+ * The C variable name used in the SWIG-generated wrapper code to refer to
+ * this class; usually it is of the form "SwigClassXXX.klass", where SwigClassXXX
+ * is a swig_class struct instance and klass is a member of that struct.
+ */
+ String *vname;
+
+ /**
+ * The C variable name used in the SWIG-generated wrapper code to refer to
+ * the module that implements this class's methods (when we're trying to
+ * support C++ multiple inheritance). Usually it is of the form
+ * "SwigClassClassName.mImpl", where SwigClassXXX is a swig_class struct instance
+ * and mImpl is a member of that struct.
+ */
+ String *mImpl;
+
+ String *type;
+ String *prefix;
+ String *init;
+
+
+ int constructor_defined;
+ int destructor_defined;
+
+ RClass() {
+ temp = NewString("");
+ name = NewString("");
+ cname = NewString("");
+ mname = NewString("");
+ vname = NewString("");
+ mImpl = NewString("");
+ type = NewString("");
+ prefix = NewString("");
+ init = NewString("");
+ constructor_defined = 0;
+ destructor_defined = 0;
+ }
+
+ ~RClass() {
+ Delete(name);
+ Delete(cname);
+ Delete(vname);
+ Delete(mImpl);
+ Delete(mname);
+ Delete(type);
+ Delete(prefix);
+ Delete(init);
+ Delete(temp);
+ }
+
+ void set_name(const_String_or_char_ptr cn, const_String_or_char_ptr rn, const_String_or_char_ptr valn) {
+ /* Original C/C++ class (or struct) name */
+ Clear(cname);
+ Append(cname, cn);
+
+ /* Mangled name */
+ Delete(mname);
+ mname = Swig_name_mangle_string(cname);
+
+ /* Renamed class name */
+ Clear(name);
+ Append(name, valn);
+
+ /* Variable name for the VALUE that refers to the Ruby Class object */
+ Clear(vname);
+ Printf(vname, "SwigClass%s.klass", name);
+
+ /* Variable name for the VALUE that refers to the Ruby Class object */
+ Clear(mImpl);
+ Printf(mImpl, "SwigClass%s.mImpl", name);
+
+ /* Prefix */
+ Clear(prefix);
+ Printv(prefix, (rn ? rn : cn), "_", NIL);
+ }
+
+ char *strip(const_String_or_char_ptr s) {
+ Clear(temp);
+ if (Strncmp(s, prefix, Len(prefix)) == 0) {
+ Append(temp, Char(s) + Len(prefix));
+ } else {
+ Append(temp, s);
+ }
+ return Char(temp);
+ }
+};
+
+
+/* flags for the make_autodoc function */
+namespace {
+enum autodoc_t {
+ AUTODOC_CLASS,
+ AUTODOC_CTOR,
+ AUTODOC_DTOR,
+ AUTODOC_STATICFUNC,
+ AUTODOC_FUNC,
+ AUTODOC_METHOD,
+ AUTODOC_GETTER,
+ AUTODOC_SETTER,
+ AUTODOC_NONE
+};
+}
+
+static const char *usage = "\
+Ruby Options (available with -ruby)\n\
+ -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\
+ -globalmodule - Wrap everything into the global module\n\
+ -initname <name>- Set entry function to Init_<name> (used by `require')\n\
+ -minherit - Attempt to support multiple inheritance\n\
+ -noautorename - Disable renaming of classes and methods (default)\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+";
+
+
+#define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0)
+#define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0))
+
+
+class RUBY:public Language {
+private:
+
+ String *module;
+ String *modvar;
+ String *feature;
+ String *prefix;
+ int current;
+ Hash *classes; /* key=cname val=RClass */
+ RClass *klass; /* Currently processing class */
+ Hash *special_methods; /* Python style special method name table */
+
+ File *f_directors;
+ File *f_directors_h;
+ File *f_directors_helpers;
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_initbeforefunc;
+
+ bool useGlobalModule;
+ bool multipleInheritance;
+
+ // Wrap modes
+ enum WrapperMode {
+ NO_CPP,
+ MEMBER_FUNC,
+ CONSTRUCTOR_ALLOCATE,
+ CONSTRUCTOR_INITIALIZE,
+ DESTRUCTOR,
+ MEMBER_VAR,
+ CLASS_CONST,
+ STATIC_FUNC,
+ STATIC_VAR
+ };
+
+ /* ------------------------------------------------------------
+ * autodoc level declarations
+ * ------------------------------------------------------------ */
+
+ enum autodoc_l {
+ NO_AUTODOC = -2, // no autodoc
+ STRING_AUTODOC = -1, // use provided string
+ NAMES_AUTODOC = 0, // only parameter names
+ TYPES_AUTODOC = 1, // parameter names and types
+ EXTEND_AUTODOC = 2, // extended documentation and parameter names
+ EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names
+ };
+
+ autodoc_t last_mode;
+ String* last_autodoc;
+
+ autodoc_l autodoc_level(String *autodoc) {
+ autodoc_l dlevel = NO_AUTODOC;
+ char *c = Char(autodoc);
+ if (c) {
+ if (isdigit(c[0])) {
+ dlevel = (autodoc_l) atoi(c);
+ } else {
+ if (strcmp(c, "extended") == 0) {
+ dlevel = EXTEND_AUTODOC;
+ } else {
+ dlevel = STRING_AUTODOC;
+ }
+ }
+ }
+ return dlevel;
+ }
+
+
+
+ /* ------------------------------------------------------------
+ * have_docstring()
+ * Check if there is a docstring directive and it has text,
+ * or there is an autodoc flag set
+ * ------------------------------------------------------------ */
+
+ bool have_docstring(Node *n) {
+ String *str = Getattr(n, "feature:docstring");
+ return (str && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ }
+
+ /* ------------------------------------------------------------
+ * docstring()
+ * Get the docstring text, stripping off {} if necessary,
+ * and enclose in triple double quotes. If autodoc is also
+ * set then it will build a combined docstring.
+ * ------------------------------------------------------------ */
+
+ String *docstring(Node *n, autodoc_t ad_type) {
+
+ String *str = Getattr(n, "feature:docstring");
+ bool have_ds = (str && Len(str) > 0);
+ bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
+ String *autodoc = NULL;
+ String *doc = NULL;
+
+ if (have_ds) {
+ char *t = Char(str);
+ if (*t == '{') {
+ Delitem(str, 0);
+ Delitem(str, DOH_END);
+ }
+ }
+
+ if (have_auto) {
+ autodoc = make_autodoc(n, ad_type);
+ have_auto = (autodoc && Len(autodoc) > 0);
+ }
+
+ if (have_auto || have_ds)
+ doc = NewString("/*");
+
+ if (have_auto && have_ds) { // Both autodoc and docstring are present
+ Printv(doc, "\n", autodoc, "\n", str, "\n", NIL);
+ } else if (!have_auto && have_ds) { // only docstring
+ Printv(doc, str, NIL);
+ } else if (have_auto && !have_ds) { // only autodoc
+ Printv(doc, "\n", autodoc, "\n", NIL);
+ } else {
+ doc = NewString("");
+ }
+
+ if (have_auto || have_ds)
+ Append(doc, "*/\n");
+
+ // Save the generated strings in the parse tree in case they are used later
+ // by post processing tools
+ Setattr(n, "ruby:docstring", doc);
+ Setattr(n, "ruby:autodoc", autodoc);
+ return doc;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * addMissingParameterNames()
+ * For functions that have not had nameless parameters set in the Language class.
+ *
+ * Inputs:
+ * plist - entire parameter list
+ * arg_offset - argument number for first parameter
+ * Side effects:
+ * The "lname" attribute in each parameter in plist will be contain a parameter name
+ * ----------------------------------------------------------------------------- */
+
+ void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
+ Parm *p = plist;
+ int i = arg_offset;
+ while (p) {
+ if (!Getattr(p, "lname")) {
+ String *name = makeParameterName(n, p, i);
+ Setattr(p, "lname", name);
+ Delete(name);
+ }
+ i++;
+ p = nextSibling(p);
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodocParmList()
+ * Generate the documentation for the function parameters
+ * ------------------------------------------------------------ */
+
+ String *make_autodocParmList(Node *n, bool showTypes) {
+ String *doc = NewString("");
+ String *pdocs = 0;
+ ParmList *plist = CopyParmList(Getattr(n, "parms"));
+ Parm *p;
+ Parm *pnext;
+ int lines = 0;
+ int arg_num = is_wrapping_class() ? 1 : 0;
+ const int maxwidth = 80;
+
+ addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
+
+ Swig_typemap_attach_parms("in", plist, 0);
+ Swig_typemap_attach_parms("doc", plist, 0);
+
+ if (Strcmp(ParmList_protostr(plist), "void") == 0) {
+ //No parameters actually
+ return doc;
+ }
+
+ for (p = plist; p; p = pnext, arg_num++) {
+
+ String *tm = Getattr(p, "tmap:in");
+ if (tm) {
+ pnext = Getattr(p, "tmap:in:next");
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ continue;
+ }
+ } else {
+ pnext = nextSibling(p);
+ }
+
+ String *name = 0;
+ String *type = 0;
+ String *value = 0;
+ String *pdoc = Getattr(p, "tmap:doc");
+ if (pdoc) {
+ name = Getattr(p, "tmap:doc:name");
+ type = Getattr(p, "tmap:doc:type");
+ value = Getattr(p, "tmap:doc:value");
+ }
+
+ // Note: the generated name should be consistent with that in kwnames[]
+ String *made_name = 0;
+ if (!name) {
+ name = made_name = makeParameterName(n, p, arg_num);
+ }
+
+ type = type ? type : Getattr(p, "type");
+ value = value ? value : Getattr(p, "value");
+
+ if (SwigType_isvarargs(type))
+ break;
+
+ // Skip the 'self' parameter which in ruby is implicit
+ if ( Cmp(name, "self") == 0 )
+ continue;
+
+ // Make __p parameters just p (as used in STL)
+ Replace( name, "__", "", DOH_REPLACE_FIRST );
+
+ if (Len(doc)) {
+ // add a comma to the previous one if any
+ Append(doc, ", ");
+
+ // Do we need to wrap a long line?
+ if ((Len(doc) - lines * maxwidth) > maxwidth) {
+ Printf(doc, "\n%s", tab4);
+ lines += 1;
+ }
+ }
+
+ // Do the param type too?
+ Node *nn = classLookup(Getattr(p, "type"));
+ String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ if (showTypes)
+ Printf(doc, "%s ", type_str);
+
+ Append(doc, name);
+ if (pdoc) {
+ if (!pdocs)
+ pdocs = NewString("Parameters:\n");
+ Printf(pdocs, " %s.\n", pdoc);
+ }
+
+ if (value) {
+ String *new_value = convertValue(value, Getattr(p, "numval"), Getattr(p, "stringval"), Getattr(p, "type"));
+ if (new_value) {
+ value = new_value;
+ } else {
+ Node *lookup = Swig_symbol_clookup(value, 0);
+ if (lookup)
+ value = Getattr(lookup, "sym:name");
+ }
+ Printf(doc, "=%s", value);
+
+ if (new_value)
+ Delete(new_value);
+ }
+ Delete(type_str);
+ Delete(made_name);
+ }
+ if (pdocs)
+ Setattr(n, "feature:pdocs", pdocs);
+ Delete(plist);
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * make_autodoc()
+ * Build a docstring for the node, using parameter and other
+ * info in the parse tree. If the value of the autodoc
+ * attribute is "0" then do not include parameter types, if
+ * it is "1" (the default) then do. If it has some other
+ * value then assume it is supplied by the extension writer
+ * and use it directly.
+ * ------------------------------------------------------------ */
+
+ String *make_autodoc(Node *n, autodoc_t ad_type) {
+ int extended = 0;
+ // If the function is overloaded then this function is called
+ // for the last one. Rewind to the first so the docstrings are
+ // in order.
+ while (Getattr(n, "sym:previousSibling"))
+ n = Getattr(n, "sym:previousSibling");
+
+ Node *pn = Swig_methodclass(n);
+ String* super_names = NewString("");
+ String* class_name = Getattr(pn, "sym:name") ;
+
+ if ( !class_name ) {
+ class_name = NewString("");
+ } else {
+ class_name = Copy(class_name);
+ List *baselist = Getattr(pn, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+
+ int count = 0;
+ for ( ;base.item; ++count) {
+ if ( count ) Append(super_names, ", ");
+ String *basename = Getattr(base.item, "sym:name");
+
+ String* basenamestr = NewString(basename);
+ Node* parent = parentNode(base.item);
+ while (parent)
+ {
+ String *parent_name = Copy( Getattr(parent, "sym:name") );
+ if ( !parent_name ) {
+ Node* mod = Getattr(parent, "module");
+ if ( mod )
+ parent_name = Copy( Getattr(mod, "name") );
+ if ( parent_name )
+ (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]);
+ }
+ if ( parent_name ) {
+ Insert(basenamestr, 0, "::");
+ Insert(basenamestr, 0, parent_name);
+ Delete(parent_name);
+ }
+ parent = parentNode(parent);
+ }
+
+ Append(super_names, basenamestr );
+ Delete(basenamestr);
+ base = Next(base);
+ }
+ }
+ }
+ String* full_name;
+ if ( module ) {
+ full_name = NewString(module);
+ if (Len(class_name) > 0)
+ Append(full_name, "::");
+ }
+ else
+ full_name = NewString("");
+ Append(full_name, class_name);
+
+ String* symname = Getattr(n, "sym:name");
+ if ( Getattr( special_methods, symname ) )
+ symname = Getattr( special_methods, symname );
+
+ String* methodName = NewString(full_name);
+ Append(methodName, symname);
+
+
+ // Each overloaded function will try to get documented,
+ // so we keep the name of the last overloaded function and its type.
+ // Documenting just from functionWrapper() is not possible as
+ // sym:name has already been changed to include the class name
+ if ( last_mode == ad_type && Cmp(methodName, last_autodoc) == 0 ) {
+ Delete(full_name);
+ Delete(class_name);
+ Delete(super_names);
+ Delete(methodName);
+ return NewString("");
+ }
+
+
+ last_mode = ad_type;
+ last_autodoc = Copy(methodName);
+
+ String *doc = NewString("");
+ int counter = 0;
+ bool skipAuto = false;
+ Node* on = n;
+ for ( ; n; ++counter ) {
+ String *type_str = NULL;
+ skipAuto = false;
+ bool showTypes = false;
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+ switch (dlevel) {
+ case NO_AUTODOC:
+ break;
+ case NAMES_AUTODOC:
+ showTypes = false;
+ break;
+ case TYPES_AUTODOC:
+ showTypes = true;
+ break;
+ case EXTEND_AUTODOC:
+ extended = 1;
+ showTypes = false;
+ break;
+ case EXTEND_TYPES_AUTODOC:
+ extended = 1;
+ showTypes = true;
+ break;
+ case STRING_AUTODOC:
+ skipAuto = true;
+ break;
+ }
+
+ SwigType *type = Getattr(n, "type");
+
+ if (type) {
+ if (Strcmp(type, "void") == 0) {
+ type_str = NULL;
+ } else {
+ SwigType *qt = SwigType_typedef_resolve_all(type);
+ if (SwigType_isenum(qt)) {
+ type_str = NewString("int");
+ } else {
+ Node *nn = classLookup(type);
+ type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
+ }
+ }
+ }
+
+ if (counter == 0) {
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ Printf(doc, " Document-class: %s", full_name);
+ if ( Len(super_names) > 0 )
+ Printf( doc, " < %s", super_names);
+ Append(doc, "\n\n");
+ break;
+ case AUTODOC_CTOR:
+ Printf(doc, " Document-method: %s.new\n\n", full_name);
+ break;
+
+ case AUTODOC_DTOR:
+ break;
+
+ case AUTODOC_STATICFUNC:
+ Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
+ break;
+
+ case AUTODOC_FUNC:
+ case AUTODOC_METHOD:
+ case AUTODOC_GETTER:
+ Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
+ break;
+ case AUTODOC_SETTER:
+ Printf(doc, " Document-method: %s.%s=\n\n", full_name, symname);
+ break;
+ case AUTODOC_NONE:
+ break;
+ }
+ }
+
+ if (skipAuto) {
+ if ( counter == 0 ) Printf(doc, " call-seq:\n");
+ switch( ad_type )
+ {
+ case AUTODOC_STATICFUNC:
+ case AUTODOC_FUNC:
+ case AUTODOC_METHOD:
+ case AUTODOC_GETTER:
+ {
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, " %s(%s)", symname, paramList);
+ else
+ Printf(doc, " %s", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ case AUTODOC_SETTER:
+ {
+ Printf(doc, " %s=(x)", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ default:
+ break;
+ }
+ } else {
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ {
+ // Only do the autodoc if there isn't a docstring for the class
+ String *str = Getattr(n, "feature:docstring");
+ if (counter == 0 && (str == 0 || Len(str) == 0)) {
+ if (CPlusPlus) {
+ Printf(doc, " Proxy of C++ %s class", full_name);
+ } else {
+ Printf(doc, " Proxy of C %s struct", full_name);
+ }
+ }
+ }
+ break;
+ case AUTODOC_CTOR:
+ if (counter == 0)
+ Printf(doc, " call-seq:\n");
+ if (Strcmp(class_name, symname) == 0) {
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, " %s.new(%s)", class_name, paramList);
+ else
+ Printf(doc, " %s.new", class_name);
+ } else {
+ Printf(doc, " %s.new(%s)", class_name, make_autodocParmList(n, showTypes));
+ }
+ break;
+
+ case AUTODOC_DTOR:
+ break;
+
+ case AUTODOC_STATICFUNC:
+ case AUTODOC_FUNC:
+ case AUTODOC_METHOD:
+ case AUTODOC_GETTER:
+ {
+ if (counter == 0)
+ Printf(doc, " call-seq:\n");
+ String *paramList = make_autodocParmList(n, showTypes);
+ if (Len(paramList))
+ Printf(doc, " %s(%s)", symname, paramList);
+ else
+ Printf(doc, " %s", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ case AUTODOC_SETTER:
+ {
+ Printf(doc, " call-seq:\n");
+ Printf(doc, " %s=(x)", symname);
+ if (type_str)
+ Printf(doc, " -> %s", type_str);
+ break;
+ }
+ case AUTODOC_NONE:
+ break;
+ }
+ }
+
+ // if it's overloaded then get the next decl and loop around again
+ n = Getattr(n, "sym:nextSibling");
+ if (n)
+ Append(doc, "\n");
+ Delete(type_str);
+ }
+
+ Printf(doc, "\n\n");
+ if (!skipAuto) {
+ switch (ad_type) {
+ case AUTODOC_CLASS:
+ case AUTODOC_DTOR:
+ break;
+ case AUTODOC_CTOR:
+ Printf(doc, "Class constructor.\n");
+ break;
+ case AUTODOC_STATICFUNC:
+ Printf(doc, "A class method.\n");
+ break;
+ case AUTODOC_FUNC:
+ Printf(doc, "A module function.\n");
+ break;
+ case AUTODOC_METHOD:
+ Printf(doc, "An instance method.\n");
+ break;
+ case AUTODOC_GETTER:
+ Printf(doc, "Get value of attribute.\n");
+ break;
+ case AUTODOC_SETTER:
+ Printf(doc, "Set new value for attribute.\n");
+ break;
+ case AUTODOC_NONE:
+ break;
+ }
+ }
+
+
+ n = on;
+ while ( n ) {
+ String *autodoc = Getattr(n, "feature:autodoc");
+ autodoc_l dlevel = autodoc_level(autodoc);
+
+ switch (dlevel) {
+ case NO_AUTODOC:
+ case NAMES_AUTODOC:
+ case TYPES_AUTODOC:
+ extended = 0;
+ break;
+ case STRING_AUTODOC:
+ extended = 2;
+ Replaceall( autodoc, "$class", class_name );
+ Printv(doc, autodoc, ".", NIL);
+ break;
+ case EXTEND_AUTODOC:
+ case EXTEND_TYPES_AUTODOC:
+ extended = 1;
+ break;
+ }
+
+
+ if (extended) {
+ String *pdocs = Getattr(n, "feature:pdocs");
+ if (pdocs) {
+ Printv(doc, "\n\n", pdocs, NULL);
+ break;
+ }
+ if ( extended == 2 ) break;
+ }
+ n = Getattr(n, "sym:nextSibling");
+ }
+
+ Delete(full_name);
+ Delete(class_name);
+ Delete(super_names);
+ Delete(methodName);
+
+ return doc;
+ }
+
+ /* ------------------------------------------------------------
+ * convertValue()
+ * Check if string v can be a Ruby value literal,
+ * (eg. number or string), or translate it to a Ruby literal.
+ * ------------------------------------------------------------ */
+ String *convertValue(String *v, String *numval, String *stringval, SwigType *type) {
+ if (stringval) {
+ return NewStringf("\"%(escape)s\"", stringval);
+ }
+ if (numval) {
+ SwigType *resolved_type = SwigType_typedef_resolve_all(type);
+ SwigType *unqualified_type = SwigType_strip_qualifiers(resolved_type);
+ if (Equal(unqualified_type, "bool")) {
+ Delete(resolved_type);
+ Delete(unqualified_type);
+ return NewString(*Char(numval) == '0' ? "false" : "true");
+ }
+ Delete(resolved_type);
+ Delete(unqualified_type);
+ if (SwigType_ispointer(type) && Equal(v, "0"))
+ return NewString("None");
+ return Copy(v);
+ }
+ if (v && Len(v) > 0) {
+ if (Equal(v, "NULL") || Equal(v, "nullptr"))
+ return SwigType_ispointer(type) ? NewString("nil") : NewString("0");
+ // FIXME: TRUE and FALSE are not standard and could be defined in other ways
+ if (Equal(v, "TRUE"))
+ return NewString("true");
+ if (Equal(v, "FALSE"))
+ return NewString("false");
+ }
+ return 0;
+ }
+
+public:
+
+ /* ---------------------------------------------------------------------
+ * RUBY()
+ *
+ * Initialize member data
+ * --------------------------------------------------------------------- */
+ RUBY() :
+ module(0),
+ modvar(0),
+ feature(0),
+ prefix(0),
+ current(0),
+ classes(0),
+ klass(0),
+ special_methods(0),
+ f_directors(0),
+ f_directors_h(0),
+ f_directors_helpers(0),
+ f_begin(0),
+ f_runtime(0),
+ f_runtime_h(0),
+ f_header(0),
+ f_wrappers(0),
+ f_init(0),
+ f_initbeforefunc(0),
+ useGlobalModule(false),
+ multipleInheritance(false),
+ last_mode(AUTODOC_NONE),
+ last_autodoc(NewString("")) {
+ current = NO_CPP;
+ director_prot_ctor_code = NewString("");
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
+ director_multiple_inheritance = 0;
+ directorLanguage();
+ }
+
+ /* ---------------------------------------------------------------------
+ * main()
+ *
+ * Parse command line options and initializes variables.
+ * --------------------------------------------------------------------- */
+
+ virtual void main(int argc, char *argv[]) {
+
+ int autorename = 0;
+
+ /* Set location of SWIG library */
+ SWIG_library_directory("ruby");
+
+ /* Look for certain command line options */
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-initname") == 0) {
+ if (argv[i + 1]) {
+ char *name = argv[i + 1];
+ feature = NewString(name);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-globalmodule") == 0) {
+ useGlobalModule = true;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-minherit") == 0) {
+ multipleInheritance = true;
+ director_multiple_inheritance = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-autorename") == 0) {
+ autorename = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-noautorename") == 0) {
+ autorename = 0;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ char *name = argv[i + 1];
+ prefix = NewString(name);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ if (autorename) {
+ /* Turn on the autorename mode */
+ Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0);
+ }
+
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGRUBY 1", 0);
+
+ SWIG_config_file("ruby.swg");
+ allow_overloading();
+ }
+
+ /**
+ * Generate initialization code to define the Ruby module(s),
+ * accounting for nested modules as necessary.
+ */
+ void defineRubyModule() {
+ List *modules = Split(module, ':', INT_MAX);
+ if (modules != 0 && Len(modules) > 0) {
+ String *mv = 0;
+ Iterator m;
+ m = First(modules);
+ while (m.item) {
+ if (Len(m.item) > 0) {
+ if (mv != 0) {
+ Printv(f_init, tab4, modvar, " = rb_define_module_under(", modvar, ", \"", m.item, "\");\n", NIL);
+ } else {
+ Printv(f_init, tab4, modvar, " = rb_define_module(\"", m.item, "\");\n", NIL);
+ mv = NewString(modvar);
+ }
+ }
+ m = Next(m);
+ }
+ Delete(mv);
+ Delete(modules);
+ }
+ }
+
+ void registerMagicMethods() {
+
+ special_methods = NewHash();
+
+ /* Python->Ruby style special method name. */
+ /* Basic */
+ Setattr(special_methods, "__repr__", "inspect");
+ Setattr(special_methods, "__str__", "to_s");
+ Setattr(special_methods, "__cmp__", "<=>");
+ Setattr(special_methods, "__hash__", "hash");
+ Setattr(special_methods, "__nonzero__", "nonzero?");
+
+ /* Callable */
+ Setattr(special_methods, "__call__", "call");
+
+ /* Collection */
+ Setattr(special_methods, "__len__", "length");
+ Setattr(special_methods, "__getitem__", "[]");
+ Setattr(special_methods, "__setitem__", "[]=");
+
+ /* Operators */
+ Setattr(special_methods, "__add__", "+");
+ Setattr(special_methods, "__pos__", "+@");
+ Setattr(special_methods, "__sub__", "-");
+ Setattr(special_methods, "__neg__", "-@");
+ Setattr(special_methods, "__mul__", "*");
+ Setattr(special_methods, "__div__", "/");
+ Setattr(special_methods, "__mod__", "%");
+ Setattr(special_methods, "__lshift__", "<<");
+ Setattr(special_methods, "__rshift__", ">>");
+ Setattr(special_methods, "__and__", "&");
+ Setattr(special_methods, "__or__", "|");
+ Setattr(special_methods, "__xor__", "^");
+ Setattr(special_methods, "__invert__", "~");
+ Setattr(special_methods, "__lt__", "<");
+ Setattr(special_methods, "__le__", "<=");
+ Setattr(special_methods, "__gt__", ">");
+ Setattr(special_methods, "__ge__", ">=");
+ Setattr(special_methods, "__eq__", "==");
+
+ /* Other numeric */
+ Setattr(special_methods, "__divmod__", "divmod");
+ Setattr(special_methods, "__pow__", "**");
+ Setattr(special_methods, "__abs__", "abs");
+ Setattr(special_methods, "__int__", "to_i");
+ Setattr(special_methods, "__float__", "to_f");
+ Setattr(special_methods, "__coerce__", "coerce");
+ }
+
+ /* ---------------------------------------------------------------------
+ * top()
+ * --------------------------------------------------------------------- */
+
+ virtual int top(Node *n) {
+
+ String *mod_docstring = NULL;
+
+ /**
+ * See if any Ruby module options have been specified as options
+ * to the %module directive.
+ */
+ Node *swigModule = Getattr(n, "module");
+ if (swigModule) {
+ Node *options = Getattr(swigModule, "options");
+ if (options) {
+ if (Getattr(options, "directors")) {
+ allow_directors();
+ }
+ if (Getattr(options, "dirprot")) {
+ allow_dirprot();
+ }
+ if (Getattr(options, "ruby_globalmodule")) {
+ useGlobalModule = true;
+ }
+ if (Getattr(options, "ruby_minherit")) {
+ multipleInheritance = true;
+ director_multiple_inheritance = 1;
+ }
+ mod_docstring = Getattr(options, "docstring");
+ }
+ }
+
+ /* Set comparison with none for ConstructorToFunction */
+
+
+ setSubclassInstanceCheck(NewStringf("strcmp(rb_obj_classname(self), classname) != 0"));
+ // setSubclassInstanceCheck(NewString("CLASS_OF(self) != cFoo.klass"));
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+ f_directors_helpers = NewString("");
+ f_initbeforefunc = NewString("");
+
+ if (Swig_directors_enabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+ Swig_register_filebyname("director_helpers", f_directors_helpers);
+ Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
+
+ modvar = 0;
+ current = NO_CPP;
+ klass = 0;
+ classes = NewHash();
+
+ registerMagicMethods();
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "RUBY");
+
+ if (Swig_directors_enabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+ }
+
+ Printf(f_runtime, "\n");
+
+ /* typedef void *VALUE */
+ SwigType *value = NewSwigType(T_VOID);
+ SwigType_add_pointer(value);
+ SwigType_typedef(value, "VALUE");
+ Delete(value);
+
+ /* Set module name */
+ set_module(Char(Getattr(n, "name")));
+
+ if (Swig_directors_enabled()) {
+ /* Build a version of the module name for use in a C macro name. */
+ String *module_macro = Copy(module);
+ Replaceall(module_macro, "::", "__");
+
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_macro);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_macro);
+ Printf(f_directors_h, "namespace Swig {\n");
+ Printf(f_directors_h, " class Director;\n");
+ Printf(f_directors_h, "}\n\n");
+
+ Printf(f_directors_helpers, "/* ---------------------------------------------------\n");
+ Printf(f_directors_helpers, " * C++ director class helpers\n");
+ Printf(f_directors_helpers, " * --------------------------------------------------- */\n\n");
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h) {
+ String *filename = Swig_file_filename(outfile_h);
+ Printf(f_directors, "#include \"%s\"\n\n", filename);
+ Delete(filename);
+ }
+
+ Delete(module_macro);
+ }
+
+ Printf(f_header, "#define SWIG_init Init_%s\n", feature);
+ Printf(f_header, "#define SWIG_name \"%s\"\n\n", module);
+
+ if (mod_docstring) {
+ if (Len(mod_docstring)) {
+ Printf(f_header, "/*\n Document-module: %s\n\n%s\n*/\n", module, mod_docstring);
+ }
+ Delete(mod_docstring);
+ mod_docstring = NULL;
+ }
+
+ Printf(f_header, "static VALUE %s;\n", modvar);
+
+ /* Start generating the initialization function */
+ String* docs = docstring(n, AUTODOC_CLASS);
+ Printf(f_init, "/*\n%s\n*/", docs );
+ Printv(f_init, "\n", "#ifdef __cplusplus\n", "extern \"C\"\n", "#endif\n", "SWIGEXPORT void Init_", feature, "(void) {\n", "size_t i;\n", "\n", NIL);
+
+ Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL);
+
+ if (!useGlobalModule)
+ defineRubyModule();
+
+ Printv(f_init, "\n", "SWIG_InitializeModule(0);\n", "for (i = 0; i < swig_module.size; i++) {\n", "SWIG_define_class(swig_module.types[i]);\n", "}\n", NIL);
+ Printf(f_init, "\n");
+
+ /* Initialize code to keep track of objects */
+ Printf(f_init, "SWIG_RubyInitializeTrackings();\n");
+
+ Language::top(n);
+
+ if (Swig_directors_enabled()) {
+ // Insert director runtime into the f_runtime file (make it occur before %header section)
+ Swig_insert_file("director_common.swg", f_runtime);
+ Swig_insert_file("director_guard.swg", f_runtime);
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ /* Finish off our init function */
+ Printf(f_init, "}\n");
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (Swig_directors_enabled()) {
+ Dump(f_directors_helpers, f_begin);
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+ Delete(f_runtime_h);
+ }
+
+ Dump(f_wrappers, f_begin);
+ Dump(f_initbeforefunc, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_initbeforefunc);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * importDirective()
+ * ----------------------------------------------------------------------------- */
+
+ virtual int importDirective(Node *n) {
+ String *modname = Getattr(n, "module");
+ if (modname) {
+ if (prefix) {
+ Insert(modname, 0, prefix);
+ }
+
+ List *modules = Split(modname, ':', INT_MAX);
+ if (modules && Len(modules) > 0) {
+ modname = NewString("");
+ String *last = NULL;
+ Iterator m = First(modules);
+ while (m.item) {
+ if (Len(m.item) > 0) {
+ if (last) {
+ Append(modname, "/");
+ }
+ Append(modname, m.item);
+ last = m.item;
+ }
+ m = Next(m);
+ }
+ Printf(f_init, "rb_require(\"%s\");\n", modname);
+ Delete(modname);
+ }
+ Delete(modules);
+ }
+ return Language::importDirective(n);
+ }
+
+ /* ---------------------------------------------------------------------
+ * set_module(const char *mod_name)
+ *
+ * Sets the module name. Does nothing if it's already set (so it can
+ * be overridden as a command line option).
+ *---------------------------------------------------------------------- */
+
+ void set_module(const char *s) {
+ String *mod_name = NewString(s);
+ if (module == 0) {
+ /* Start with the empty string */
+ module = NewString("");
+
+ if (prefix) {
+ Insert(mod_name, 0, prefix);
+ }
+
+ /* Account for nested modules */
+ List *modules = Split(mod_name, ':', INT_MAX);
+ if (modules != 0 && Len(modules) > 0) {
+ String *last = 0;
+ Iterator m = First(modules);
+ while (m.item) {
+ if (Len(m.item) > 0) {
+ String *cap = NewString(m.item);
+ (Char(cap))[0] = (char)toupper((Char(cap))[0]);
+ if (last != 0) {
+ Append(module, "::");
+ }
+ Append(module, cap);
+ last = m.item;
+ }
+ m = Next(m);
+ }
+ if (last) {
+ if (feature == 0) {
+ feature = Copy(last);
+ }
+ (Char(last))[0] = (char)toupper((Char(last))[0]);
+ modvar = NewStringf("m%s", last);
+ }
+ }
+ Delete(modules);
+ }
+ Delete(mod_name);
+ }
+
+ /* --------------------------------------------------------------------------
+ * nativeWrapper()
+ * -------------------------------------------------------------------------- */
+ virtual int nativeWrapper(Node *n) {
+ String *funcname = Getattr(n, "wrap:name");
+ Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "Adding native function %s not supported (ignored).\n", funcname);
+ return SWIG_NOWRAP;
+ }
+
+ /**
+ * Process the comma-separated list of aliases (if any).
+ */
+ void defineAliases(Node *n, const_String_or_char_ptr iname) {
+ String *aliasv = Getattr(n, "feature:alias");
+ if (aliasv) {
+ List *aliases = Split(aliasv, ',', INT_MAX);
+ if (aliases && Len(aliases) > 0) {
+ Iterator alias = First(aliases);
+ while (alias.item) {
+ if (Len(alias.item) > 0) {
+ if (current == NO_CPP) {
+ if (useGlobalModule) {
+ Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ } else {
+ Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ }
+ } else if (multipleInheritance) {
+ Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ } else {
+ Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
+ }
+ }
+ alias = Next(alias);
+ }
+ }
+ Delete(aliases);
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * create_command(Node *n, char *iname)
+ *
+ * Creates a new command from a C function.
+ * iname = Name of function in scripting language
+ *
+ * A note about what "protected" and "private" mean in Ruby:
+ *
+ * A private method is accessible only within the class or its subclasses,
+ * and it is callable only in "function form", with 'self' (implicit or
+ * explicit) as a receiver.
+ *
+ * A protected method is callable only from within its class, but unlike
+ * a private method, it can be called with a receiver other than self, such
+ * as another instance of the same class.
+ * --------------------------------------------------------------------- */
+
+ void create_command(Node *n, const_String_or_char_ptr iname) {
+
+ String *alloc_func = Swig_name_wrapper(iname);
+ String *wname = Swig_name_wrapper(iname);
+ if (CPlusPlus) {
+ Insert(wname, 0, "VALUEFUNC(");
+ Append(wname, ")");
+ }
+ if (current != NO_CPP)
+ iname = klass->strip(iname);
+ if (Getattr(special_methods, iname)) {
+ iname = GetChar(special_methods, iname);
+ }
+
+ String *s = NewString("");
+ String *temp = NewString("");
+
+#ifdef SWIG_PROTECTED_TARGET_METHODS
+ const char *rb_define_method = is_public(n) ? "rb_define_method" : "rb_define_protected_method";
+#else
+ const char *rb_define_method = "rb_define_method";
+#endif
+ switch (current) {
+ case MEMBER_FUNC:
+ {
+ if (multipleInheritance) {
+ Printv(klass->init, tab4, rb_define_method, "(", klass->mImpl, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ } else {
+ Printv(klass->init, tab4, rb_define_method, "(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ }
+ }
+ break;
+ case CONSTRUCTOR_ALLOCATE:
+ Printv(s, tab4, "rb_define_alloc_func(", klass->vname, ", ", alloc_func, ");\n", NIL);
+ Replaceall(klass->init, "$allocator", s);
+ break;
+ case CONSTRUCTOR_INITIALIZE:
+ Printv(s, tab4, rb_define_method, "(", klass->vname, ", \"initialize\", ", wname, ", -1);\n", NIL);
+ Replaceall(klass->init, "$initializer", s);
+ break;
+ case MEMBER_VAR:
+ Append(temp, iname);
+ /* Check for _set or _get at the end of the name. */
+ if (Len(temp) > 4) {
+ const char *p = Char(temp) + (Len(temp) - 4);
+ if (strcmp(p, "_set") == 0) {
+ Delslice(temp, Len(temp) - 4, DOH_END);
+ Append(temp, "=");
+ } else if (strcmp(p, "_get") == 0) {
+ Delslice(temp, Len(temp) - 4, DOH_END);
+ }
+ }
+ if (multipleInheritance) {
+ Printv(klass->init, tab4, "rb_define_method(", klass->mImpl, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
+ } else {
+ Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
+ }
+ break;
+ case STATIC_FUNC:
+ Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ break;
+ case NO_CPP:
+ if (!useGlobalModule) {
+ Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
+ Printv(f_init, s, NIL);
+ } else {
+ Printv(s, tab4, "rb_define_global_function(\"", iname, "\", ", wname, ", -1);\n", NIL);
+ Printv(f_init, s, NIL);
+ }
+ break;
+ case DESTRUCTOR:
+ case CLASS_CONST:
+ case STATIC_VAR:
+ default:
+ assert(false); // Should not have gotten here for these types
+ }
+
+ defineAliases(n, iname);
+
+ Delete(temp);
+ Delete(s);
+ Delete(wname);
+ Delete(alloc_func);
+ }
+
+ /* ---------------------------------------------------------------------
+ * applyInputTypemap()
+ *
+ * Look up the appropriate "in" typemap for this parameter (p),
+ * substitute the correct strings for the typemap parameters, and dump the
+ * resulting code to the wrapper file.
+ * --------------------------------------------------------------------- */
+
+ Parm *applyInputTypemap(Parm *p, String *source, Wrapper *f, String *symname) {
+ String *tm;
+ SwigType *pt = Getattr(p, "type");
+ if ((tm = Getattr(p, "tmap:in"))) {
+ Replaceall(tm, "$input", source);
+ Replaceall(tm, "$symname", symname);
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ Setattr(p, "emit:input", Copy(source));
+ Printf(f->code, "%s\n", tm);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ }
+ return p;
+ }
+
+ Parm *skipIgnoredArgs(Parm *p) {
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+ return p;
+ }
+
+ /* ---------------------------------------------------------------------
+ * marshalInputArgs()
+ *
+ * Process all of the arguments passed into the scripting language
+ * method and convert them into C/C++ function arguments using the
+ * supplied typemaps.
+ * --------------------------------------------------------------------- */
+
+ void marshalInputArgs(Node *n, ParmList *l, int numarg, int numreq, String *kwargs, bool allow_kwargs, Wrapper *f) {
+ int i;
+ Parm *p;
+ String *tm;
+ String *source;
+
+ source = NewString("");
+
+ bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
+
+ /**
+ * The 'start' value indicates which of the C/C++ function arguments
+ * produced here corresponds to the first value in Ruby's argv[] array.
+ * The value of start is either zero or one. If start is zero, then
+ * the first argument (with name arg1) is based on the value of argv[0].
+ * If start is one, then arg1 is based on the value of argv[1].
+ */
+ int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
+
+ int varargs = emit_isvarargs(l);
+
+ Printf(kwargs, "{ ");
+ for (i = 0, p = l; i < numarg; i++) {
+
+ p = skipIgnoredArgs(p);
+
+ String *pn = Getattr(p, "name");
+
+ /* Produce string representation of source argument */
+ Clear(source);
+
+ /* First argument is a special case */
+ if (i == 0) {
+ Printv(source, (start == 0) ? "argv[0]" : "self", NIL);
+ } else {
+ Printf(source, "argv[%d]", i - start);
+ }
+
+ if (i >= (numreq)) { /* Check if parsing an optional argument */
+ Printf(f->code, " if (argc > %d) {\n", i - start);
+ }
+
+ /* Record argument name for keyword argument handling */
+ if (Len(pn)) {
+ Printf(kwargs, "\"%s\",", pn);
+ } else {
+ Printf(kwargs, "\"arg%d\",", i + 1);
+ }
+
+ /* Look for an input typemap */
+ p = applyInputTypemap(p, source, f, Getattr(n, "name"));
+ if (i >= numreq) {
+ Printf(f->code, "}\n");
+ }
+ }
+
+ /* Finish argument marshalling */
+ Printf(kwargs, " NULL }");
+ if (allow_kwargs) {
+// kwarg support not implemented
+// Printv(f->locals, tab4, "const char *kwnames[] = ", kwargs, ";\n", NIL);
+ }
+
+ /* Trailing varargs */
+ if (varargs) {
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ Clear(source);
+ Printf(source, "argv[%d]", i - start);
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", Copy(source));
+ Printf(f->code, "if (argc > %d) {\n", i - start);
+ Printv(f->code, tm, "\n", NIL);
+ Printf(f->code, "}\n");
+ }
+ }
+
+ Delete(source);
+ }
+
+ /* ---------------------------------------------------------------------
+ * insertConstraintCheckingCode(ParmList *l, Wrapper *f)
+ *
+ * Checks each of the parameters in the parameter list for a "check"
+ * typemap and (if it finds one) inserts the typemapping code into
+ * the function wrapper.
+ * --------------------------------------------------------------------- */
+
+ void insertConstraintCheckingCode(ParmList *l, Wrapper *f) {
+ Parm *p;
+ String *tm;
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * insertCleanupCode(ParmList *l, String *cleanup)
+ *
+ * Checks each of the parameters in the parameter list for a "freearg"
+ * typemap and (if it finds one) inserts the typemapping code into
+ * the function wrapper.
+ * --------------------------------------------------------------------- */
+
+ void insertCleanupCode(ParmList *l, String *cleanup) {
+ String *tm;
+ for (Parm *p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ if (Len(tm) != 0) {
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * insertArgOutputCode(ParmList *l, String *outarg, int& need_result)
+ *
+ * Checks each of the parameters in the parameter list for a "argout"
+ * typemap and (if it finds one) inserts the typemapping code into
+ * the function wrapper.
+ * --------------------------------------------------------------------- */
+
+ void insertArgOutputCode(ParmList *l, String *outarg, int &need_result) {
+ String *tm;
+ for (Parm *p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ Replaceall(tm, "$result", "vresult");
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+
+ Printv(outarg, tm, "\n", NIL);
+ need_result += 1;
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------
+ * validIdentifier()
+ *
+ * Is this a valid identifier in the scripting language?
+ * Ruby method names can include any combination of letters, numbers
+ * and underscores. A Ruby method name may optionally end with
+ * a question mark ("?"), exclamation point ("!") or equals sign ("=").
+ *
+ * Methods whose names end with question marks are, by convention,
+ * predicate methods that return true or false (e.g. Array#empty?).
+ *
+ * Methods whose names end with exclamation points are, by convention,
+ * called bang methods that modify the instance in place (e.g. Array#sort!).
+ *
+ * Methods whose names end with an equals sign are attribute setters
+ * (e.g. Thread#critical=).
+ * --------------------------------------------------------------------- */
+
+ virtual int validIdentifier(String *s) {
+ char *c = Char(s);
+ while (*c) {
+ if (!(isalnum(*c) || (*c == '_') || (*c == '?') || (*c == '!') || (*c == '=')))
+ return 0;
+ c++;
+ }
+ return 1;
+ }
+
+ /* ---------------------------------------------------------------------
+ * functionWrapper()
+ *
+ * Create a function declaration and register it with the interpreter.
+ * --------------------------------------------------------------------- */
+
+ virtual int functionWrapper(Node *n) {
+
+ String *nodeType;
+ bool destructor;
+
+ String *symname = Copy(Getattr(n, "sym:name"));
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ int director_method = 0;
+ String *tm;
+
+ int need_result = 0;
+
+ /* Ruby needs no destructor wrapper */
+ if (current == DESTRUCTOR)
+ return SWIG_NOWRAP;
+
+ nodeType = Getattr(n, "nodeType");
+ destructor = (!Cmp(nodeType, "destructor"));
+
+ /* If the C++ class constructor is overloaded, we only want to
+ * write out the "new" singleton method once since it is always
+ * the same. (It's the "initialize" method that will handle the
+ * overloading). */
+
+ if (current == CONSTRUCTOR_ALLOCATE && Swig_symbol_isoverloaded(n) && Getattr(n, "sym:nextSibling") != 0)
+ return SWIG_OK;
+
+ String *overname = 0;
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+ }
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *kwargs = NewString("");
+ Wrapper *f = NewWrapper();
+
+ /* Rename predicate methods */
+ if (GetFlag(n, "feature:predicate")) {
+ Append(symname, "?");
+ }
+
+ /* Rename bang methods */
+ if (GetFlag(n, "feature:bang")) {
+ Append(symname, "!");
+ }
+
+ /* Determine the name of the SWIG wrapper function */
+ String *wname = Swig_name_wrapper(symname);
+ if (overname && current != CONSTRUCTOR_ALLOCATE) {
+ Append(wname, overname);
+ }
+
+ /* Emit arguments */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ emit_parameter_variables(l, f);
+ }
+
+ /* Attach standard typemaps */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ emit_attach_parmmaps(l, f);
+ }
+ Setattr(n, "wrap:parms", l);
+
+ /* Get number of arguments */
+ int numarg = emit_num_arguments(l);
+ int numreq = emit_num_required(l);
+ int varargs = emit_isvarargs(l);
+ bool allow_kwargs = GetFlag(n, "feature:kwargs") ? true : false;
+
+ bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
+ int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
+
+ /* Now write the wrapper function itself */
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ Printv(f->def, "SWIGINTERN VALUE\n", NIL);
+ Printf(f->def, "#ifdef HAVE_RB_DEFINE_ALLOC_FUNC\n");
+ Printv(f->def, wname, "(VALUE self)\n", NIL);
+ Printf(f->def, "#else\n");
+ Printv(f->def, wname, "(int argc, VALUE *argv, VALUE self)\n", NIL);
+ Printf(f->def, "#endif\n");
+ Printv(f->def, "{\n", NIL);
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
+ if (!varargs) {
+ Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
+ } else {
+ Printf(f->code, "if (argc < %d) ", numreq - start);
+ }
+ Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
+ } else {
+
+ if ( current == NO_CPP )
+ {
+ String* docs = docstring(n, AUTODOC_FUNC);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+ }
+
+ Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
+ if (!varargs) {
+ Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
+ } else {
+ Printf(f->code, "if (argc < %d) ", numreq - start);
+ }
+ Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
+ }
+
+ /* Now walk the function parameter list and generate code */
+ /* to get arguments */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ marshalInputArgs(n, l, numarg, numreq, kwargs, allow_kwargs, f);
+ }
+ // FIXME?
+ if (ctor_director) {
+ numarg--;
+ numreq--;
+ }
+
+ /* Insert constraint checking code */
+ insertConstraintCheckingCode(l, f);
+
+ /* Insert cleanup code */
+ insertCleanupCode(l, cleanup);
+
+ /* Insert argument output code */
+ insertArgOutputCode(l, outarg, need_result);
+
+ /* if the object is a director, and the method call originated from its
+ * underlying Ruby object, resolve the call by going up the c++
+ * inheritance chain. otherwise try to resolve the method in Ruby.
+ * without this check an infinite loop is set up between the director and
+ * shadow class method calls.
+ */
+
+ // NOTE: this code should only be inserted if this class is the
+ // base class of a director class. however, in general we haven't
+ // yet analyzed all classes derived from this one to see if they are
+ // directors. furthermore, this class may be used as the base of
+ // a director class defined in a completely different module at a
+ // later time, so this test must be included whether or not directorbase
+ // is true. we do skip this code if directors have not been enabled
+ // at the command line to preserve source-level compatibility with
+ // non-polymorphic swig. also, if this wrapper is for a smart-pointer
+ // method, there is no need to perform the test since the calling object
+ // (the smart-pointer) and the director object (the "pointee") are
+ // distinct.
+
+ director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
+ if (director_method) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
+ Wrapper_add_local(f, "upcall", "bool upcall = false");
+ Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n");
+ }
+
+ /* Now write code to make the function call */
+ if (current != CONSTRUCTOR_ALLOCATE) {
+ if (current == CONSTRUCTOR_INITIALIZE) {
+ Node *pn = Swig_methodclass(n);
+ String *symname = Getattr(pn, "sym:name");
+ String *action = Getattr(n, "wrap:action");
+ if (Swig_directors_enabled()) {
+ String *classname = NewStringf("const char *classname SWIGUNUSED = \"%s::%s\"", module, symname);
+ Wrapper_add_local(f, "classname", classname);
+ }
+ if (action) {
+ SwigType *smart = Getattr(pn, "smart");
+ String *result_name = NewStringf("%s%s", smart ? "smart" : "", Swig_cresult_name());
+ if (smart) {
+ String *result_var = NewStringf("%s *%s = 0", SwigType_namestr(smart), result_name);
+ Wrapper_add_local(f, result_name, result_var);
+ Printf(action, "\n%s = new %s(%s);", result_name, SwigType_namestr(smart), Swig_cresult_name());
+ }
+ Printf(action, "\nDATA_PTR(self) = %s;", result_name);
+ if (GetFlag(pn, "feature:trackobjects")) {
+ Printf(action, "\nSWIG_RubyAddTracking(%s, self);", result_name);
+ }
+ Delete(result_name);
+ }
+ }
+
+ /* Emit the function call */
+ if (director_method) {
+ Printf(f->code, "try {\n");
+ }
+
+ Setattr(n, "wrap:name", wname);
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (director_method) {
+ Printf(actioncode, "} catch (Swig::DirectorException& e) {\n");
+ Printf(actioncode, " rb_exc_raise(e.getError());\n");
+ Printf(actioncode, " SWIG_fail;\n");
+ Printf(actioncode, "}\n");
+ }
+
+ /* Return value if necessary */
+ if (SwigType_type(returntype) != T_VOID && current != CONSTRUCTOR_INITIALIZE) {
+ need_result = 1;
+ if (GetFlag(n, "feature:predicate")) {
+ Printv(actioncode, tab4, "vresult = (", Swig_cresult_name(), " ? Qtrue : Qfalse);\n", NIL);
+ } else {
+ tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
+ actioncode = 0;
+ if (tm) {
+ Replaceall(tm, "$result", "vresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ // Unwrap return values that are director classes so that the original Ruby object is returned instead.
+ if (Swig_director_can_unwrap(n)) {
+ Wrapper_add_local(f, "director", "Swig::Director *director = 0");
+ Printf(f->code, "director = dynamic_cast<Swig::Director *>(%s);\n", Swig_cresult_name());
+ Printf(f->code, "if (director) {\n");
+ Printf(f->code, " vresult = director->swig_get_self();\n");
+ Printf(f->code, "} else {\n");
+ Printf(f->code, "%s\n", tm);
+ Printf(f->code, "}\n");
+ director_method = 0;
+ } else {
+ Printf(f->code, "%s\n", tm);
+ }
+
+ Delete(tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(returntype, 0));
+ }
+ }
+ }
+ if (actioncode) {
+ Append(f->code, actioncode);
+ Delete(actioncode);
+ }
+ emit_return_variable(n, returntype, f);
+ }
+
+ /* Extra code needed for new and initialize methods */
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ Node *pn = Swig_methodclass(n);
+ SwigType *smart = Getattr(pn, "smart");
+ SwigType *psmart = smart ? Copy(smart) : 0;
+ if (psmart)
+ SwigType_add_pointer(psmart);
+ SwigType *classtype = psmart ? psmart : returntype;
+ need_result = 1;
+ Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(classtype)));
+ Printf(f->code, "#ifndef HAVE_RB_DEFINE_ALLOC_FUNC\n");
+ Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n");
+ Printf(f->code, "#endif\n");
+ Delete(psmart);
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ need_result = 1;
+ }
+ else
+ {
+ if ( need_result > 1 ) {
+ if ( SwigType_type(returntype) == T_VOID )
+ Printf(f->code, "vresult = rb_ary_new();\n");
+ else
+ {
+ Printf(f->code, "if (vresult == Qnil) vresult = rb_ary_new();\n");
+ Printf(f->code, "else vresult = SWIG_Ruby_AppendOutput( "
+ "rb_ary_new(), vresult);\n");
+ }
+ }
+ }
+
+ /* Dump argument output code; */
+ Printv(f->code, outarg, NIL);
+
+ /* Dump the argument cleanup code */
+ int need_cleanup = (current != CONSTRUCTOR_ALLOCATE) && (Len(cleanup) != 0);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+
+
+ /* Look for any remaining cleanup. This processes the %newobject directive */
+ if (current != CONSTRUCTOR_ALLOCATE && GetFlag(n, "feature:new")) {
+ tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Printv(f->code, tm, "\n", NIL);
+ Delete(tm);
+ }
+ }
+
+ /* Special processing on return value. */
+ tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0);
+ if (tm) {
+ Printv(f->code, tm, NIL);
+ Delete(tm);
+ }
+
+ if (director_method) {
+ if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ Replaceall(tm, "$result", "vresult");
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+
+ /* Wrap things up (in a manner of speaking) */
+ if (need_result) {
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ Printv(f->code, tab4, "return vresult;\n", NIL);
+ } else if (current == CONSTRUCTOR_INITIALIZE) {
+ Printv(f->code, tab4, "return self;\n", NIL);
+ Printv(f->code, "fail:\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ } else {
+ Wrapper_add_local(f, "vresult", "VALUE vresult = Qnil");
+ Printv(f->code, tab4, "return vresult;\n", NIL);
+ Printv(f->code, "fail:\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ }
+ } else {
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ Printv(f->code, "fail:\n", NIL);
+ if (need_cleanup) {
+ Printv(f->code, cleanup, NIL);
+ }
+ Printv(f->code, tab4, "return Qnil;\n", NIL);
+ }
+
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Emit the function */
+ Wrapper_print(f, f_wrappers);
+
+ /* Now register the function with the interpreter */
+ if (!Swig_symbol_isoverloaded(n)) {
+ create_command(n, symname);
+ } else {
+ if (current == CONSTRUCTOR_ALLOCATE) {
+ create_command(n, symname);
+ } else {
+ if (!Getattr(n, "sym:nextSibling"))
+ dispatchFunction(n);
+ }
+ }
+
+ Delete(kwargs);
+ Delete(cleanup);
+ Delete(outarg);
+ DelWrapper(f);
+ Delete(symname);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * dispatchFunction()
+ * ------------------------------------------------------------ */
+
+ void dispatchFunction(Node *n) {
+ /* Last node in overloaded chain */
+
+ int maxargs;
+ String *tmp = NewString("");
+ String *dispatch = Swig_overload_dispatch(n, "return %s(nargs, args, self);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *f = NewWrapper();
+ String *symname = Getattr(n, "sym:name");
+ String *wname = Swig_name_wrapper(symname);
+
+ Printv(f->def, "SWIGINTERN VALUE ", wname, "(int nargs, VALUE *args, VALUE self) {", NIL);
+
+ Wrapper_add_local(f, "argc", "int argc");
+ bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
+ if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
+ Printf(tmp, "VALUE argv[%d]", maxargs + 1);
+ } else {
+ Printf(tmp, "VALUE argv[%d]", maxargs);
+ }
+ Wrapper_add_local(f, "argv", tmp);
+ Wrapper_add_local(f, "ii", "int ii");
+
+ if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
+ maxargs += 1;
+ Printf(f->code, "argc = nargs + 1;\n");
+ Printf(f->code, "argv[0] = self;\n");
+ Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
+ Printf(f->code, "for (ii = 1; (ii < argc); ++ii) {\n");
+ Printf(f->code, "argv[ii] = args[ii-1];\n");
+ Printf(f->code, "}\n");
+ } else {
+ Printf(f->code, "argc = nargs;\n");
+ Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
+ Printf(f->code, "for (ii = 0; (ii < argc); ++ii) {\n");
+ Printf(f->code, "argv[ii] = args[ii];\n");
+ Printf(f->code, "}\n");
+ }
+
+ Replaceall(dispatch, "$args", "nargs, args, self");
+ Printv(f->code, dispatch, "\n", NIL);
+
+
+
+ // Generate prototype list, go to first node
+ Node *sibl = n;
+
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+
+ // Constructors will be treated specially
+ String *siblNodeType = Getattr(sibl, "nodeType");
+ const bool isCtor = (Equal(siblNodeType, "constructor"));
+ const bool isMethod = (Equal(siblNodeType, "cdecl") && GetFlag(sibl, "ismember") && !isCtor);
+
+ // Construct real method name
+ String* methodName = NewString("");
+ if ( isMethod ) {
+ // Sometimes a method node has no parent (SF#3034054).
+ // This value is used in an exception message, so just skip the class
+ // name in this case so at least we don't segfault. This is probably
+ // just working around a problem elsewhere though.
+ Node *parent_node = parentNode(sibl);
+ if (parent_node)
+ Printv( methodName, Getattr(parent_node,"sym:name"), ".", NIL );
+ }
+ Append( methodName, Getattr(sibl,"sym:name" ) );
+ if ( isCtor ) Append( methodName, ".new" );
+
+ // Generate prototype list
+ String *protoTypes = NewString("");
+ do {
+ Append( protoTypes, "\n\" ");
+ if (!isCtor && !Equal(siblNodeType, "using")) {
+ SwigType *type = SwigType_str(Getattr(sibl, "type"), NULL);
+ Printv(protoTypes, type, " ", NIL);
+ Delete(type);
+ }
+ Printv(protoTypes, methodName, NIL );
+ Parm* p = Getattr(sibl, "wrap:parms");
+ if (p && (current == MEMBER_FUNC || current == MEMBER_VAR ||
+ ctor_director) )
+ p = nextSibling(p); // skip self
+ Append( protoTypes, "(" );
+ while(p)
+ {
+ Append( protoTypes, SwigType_str(Getattr(p,"type"), Getattr(p,"name")) );
+ if ( ( p = nextSibling(p)) ) Append(protoTypes, ", ");
+ }
+ Append( protoTypes, ")\\n\"" );
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+
+ Append(f->code, "fail:\n");
+ Printf(f->code, "Ruby_Format_OverloadedError( argc, %d, \"%s\", %s);\n",
+ maxargs, methodName, protoTypes);
+ Append(f->code, "\nreturn Qnil;\n");
+
+ Delete(methodName);
+ Delete(protoTypes);
+
+ Printv(f->code, "}\n", NIL);
+ Wrapper_print(f, f_wrappers);
+ create_command(n, Char(symname));
+
+ DelWrapper(f);
+ Delete(dispatch);
+ Delete(tmp);
+ Delete(wname);
+ }
+
+ /* ---------------------------------------------------------------------
+ * variableWrapper()
+ * --------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *n) {
+ String* docs = docstring(n, AUTODOC_GETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+
+ char *name = GetChar(n, "name");
+ char *iname = GetChar(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ String *tm;
+ String *getfname, *setfname;
+ Wrapper *getf, *setf;
+ int assignable = !is_immutable(n);
+
+ // Determine whether virtual global variables shall be used
+ // which have different getter and setter signatures,
+ // see https://docs.ruby-lang.org/en/2.6.0/extension_rdoc.html#label-Global+Variables+Shared+Between+C+and+Ruby
+ const bool use_virtual_var = (current == NO_CPP && useGlobalModule);
+
+ getf = NewWrapper();
+ setf = NewWrapper();
+
+ /* create getter */
+ int addfail = 0;
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ getfname = Swig_name_wrapper(getname);
+ Setattr(n, "wrap:name", getfname);
+ Printv(getf->def, "SWIGINTERN VALUE\n", getfname, "(", NIL);
+ Printf(getf->def, (use_virtual_var) ? "ID id, VALUE *data" : "VALUE self");
+ Printf(getf->def, ") {");
+ Wrapper_add_local(getf, "_val", "VALUE _val");
+
+ tm = Swig_typemap_lookup("varout", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$result", "_val");
+ /* Printv(getf->code,tm, NIL); */
+ addfail = emit_action_code(n, getf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ }
+ Printv(getf->code, tab4, "return _val;\n", NIL);
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Append(getf->code, " return Qnil;\n");
+ }
+ Append(getf->code, "}\n");
+
+ Wrapper_print(getf, f_wrappers);
+
+ if (!assignable) {
+ setfname = NewString("(rb_gvar_setter_t *)NULL");
+ } else {
+ /* create setter */
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ String *setname = Swig_name_set(NSPACE_TODO, iname);
+ setfname = Swig_name_wrapper(setname);
+ Setattr(n, "wrap:name", setfname);
+ Printf(setf->def, "SWIGINTERN ");
+ if (use_virtual_var) {
+ Printv(setf->def, "void\n", setfname, "(VALUE _val, ID id, VALUE *data) {", NIL);
+ } else {
+ Printv(setf->def, "VALUE\n", setfname, "(VALUE self, VALUE _val) {", NIL);
+ }
+ tm = Swig_typemap_lookup("varin", n, name, 0);
+ if (tm) {
+ Replaceall(tm, "$input", "_val");
+ /* Printv(setf->code,tm,"\n",NIL); */
+ emit_action_code(n, setf->code, tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0));
+ }
+ if (use_virtual_var) {
+ Printf(setf->code, "fail:\n");
+ Printv(setf->code, tab4, "return;\n", NIL);
+ } else {
+ Printv(setf->code, tab4, "return _val;\n", NIL);
+ Printf(setf->code, "fail:\n");
+ Printv(setf->code, tab4, "return Qnil;\n", NIL);
+ }
+ Printf(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+ Delete(setname);
+ }
+
+ /* define accessor methods */
+ Insert(getfname, 0, "VALUEFUNC(");
+ Append(getfname, ")");
+ Insert(setfname, 0, (use_virtual_var) ? "SWIG_RUBY_VOID_ANYARGS_FUNC(" : "VALUEFUNC(");
+ Append(setfname, ")");
+
+ String *s = NewString("");
+ switch (current) {
+ case STATIC_VAR:
+ /* C++ class variable */
+ Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "\", ", getfname, ", 0);\n", NIL);
+ if (assignable) {
+ Printv(s, tab4, "rb_define_singleton_method(", klass->vname, ", \"", klass->strip(iname), "=\", ", setfname, ", 1);\n", NIL);
+ }
+ Printv(klass->init, s, NIL);
+ break;
+ default:
+ /* C global variable */
+ /* wrapped in Ruby module attribute */
+ assert(current == NO_CPP);
+ if (!useGlobalModule) {
+ Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "\", ", getfname, ", 0);\n", NIL);
+ if (assignable) {
+ Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "=\", ", setfname, ", 1);\n", NIL);
+ }
+ } else {
+ Printv(s, tab4, "rb_define_virtual_variable(\"$", iname, "\", ", getfname, ", ", setfname, ");\n", NIL);
+ }
+ Printv(f_init, s, NIL);
+ Delete(s);
+ break;
+ }
+ Delete(getname);
+ Delete(getfname);
+ Delete(setfname);
+ DelWrapper(setf);
+ DelWrapper(getf);
+ return SWIG_OK;
+ }
+
+
+ /* ---------------------------------------------------------------------
+ * validate_const_name(char *name)
+ *
+ * Validate constant name.
+ * --------------------------------------------------------------------- */
+
+ char *validate_const_name(char *name, const char *reason) {
+ if (!name || name[0] == '\0')
+ return name;
+
+ if (isupper(name[0]))
+ return name;
+
+ if (islower(name[0])) {
+ name[0] = (char)toupper(name[0]);
+ Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name (corrected to `%s')\n", reason, name);
+ return name;
+ }
+
+ Swig_warning(WARN_RUBY_WRONG_NAME, input_file, line_number, "Wrong %s name %s\n", reason, name);
+
+ return name;
+ }
+
+ /* ---------------------------------------------------------------------
+ * constantWrapper()
+ * --------------------------------------------------------------------- */
+
+ virtual int constantWrapper(Node *n) {
+ Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL);
+
+ char *iname = GetChar(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+
+ if (current == CLASS_CONST) {
+ iname = klass->strip(iname);
+ }
+ validate_const_name(iname, "constant");
+ SetChar(n, "sym:name", iname);
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+ String *tm = Swig_typemap_lookup("constant", n, value, 0);
+ if (!tm)
+ tm = Swig_typemap_lookup("constcode", n, value, 0);
+ if (tm) {
+ Replaceall(tm, "$symname", iname);
+ Replaceall(tm, "$value", value);
+ if (current == CLASS_CONST) {
+ if (multipleInheritance) {
+ Replaceall(tm, "$module", klass->mImpl);
+ Printv(klass->init, tm, "\n", NIL);
+ } else {
+ Replaceall(tm, "$module", klass->vname);
+ Printv(klass->init, tm, "\n", NIL);
+ }
+ } else {
+ if (!useGlobalModule) {
+ Replaceall(tm, "$module", modvar);
+ } else {
+ Replaceall(tm, "$module", "rb_cObject");
+ }
+ Printf(f_init, "%s\n", tm);
+ }
+ } else {
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value);
+ }
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------------
+ * classDeclaration()
+ *
+ * Records information about classes---even classes that might be defined in
+ * other modules referenced by %import.
+ * ----------------------------------------------------------------------------- */
+
+ virtual int classDeclaration(Node *n) {
+ if (!Getattr(n, "feature:onlychildren")) {
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+
+ String *namestr = SwigType_namestr(name);
+ klass = RCLASS(classes, Char(namestr));
+ if (!klass) {
+ klass = new RClass();
+ String *valid_name = NewString(symname ? symname : namestr);
+ validate_const_name(Char(valid_name), "class");
+ klass->set_name(namestr, symname, valid_name);
+ SET_RCLASS(classes, Char(namestr), klass);
+ Delete(valid_name);
+ }
+ Delete(namestr);
+ }
+ return Language::classDeclaration(n);
+ }
+
+ /**
+ * Process the comma-separated list of mixed-in module names (if any).
+ */
+ void includeRubyModules(Node *n) {
+ String *mixin = Getattr(n, "feature:mixin");
+ if (mixin) {
+ List *modules = Split(mixin, ',', INT_MAX);
+ if (modules && Len(modules) > 0) {
+ Iterator mod = First(modules);
+ while (mod.item) {
+ if (Len(mod.item) > 0) {
+ Printf(klass->init, "rb_include_module(%s, rb_eval_string(\"%s\"));\n", klass->vname, mod.item);
+ }
+ mod = Next(mod);
+ }
+ }
+ Delete(modules);
+ }
+ }
+
+ void handleBaseClasses(Node *n) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ while (base.item) {
+ String *basename = Getattr(base.item, "name");
+ String *basenamestr = SwigType_namestr(basename);
+ RClass *super = RCLASS(classes, Char(basenamestr));
+ Delete(basenamestr);
+ if (super) {
+ SwigType *btype = NewString(basename);
+ SwigType_add_pointer(btype);
+ SwigType_remember(btype);
+ SwigType *smart = Getattr(base.item, "smart");
+ SwigType *psmart = smart ? Copy(smart) : 0;
+ if (psmart) {
+ SwigType_add_pointer(psmart);
+ SwigType_remember(psmart);
+ }
+ String *bmangle = SwigType_manglestr(psmart ? psmart : btype);
+ if (multipleInheritance) {
+ Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
+ Append(bmangle, "->clientdata)->mImpl");
+ Printv(klass->init, "rb_include_module(", klass->mImpl, ", ", bmangle, ");\n", NIL);
+ } else {
+ Insert(bmangle, 0, "((swig_class *) SWIGTYPE");
+ Append(bmangle, "->clientdata)->klass");
+ Replaceall(klass->init, "$super", bmangle);
+ }
+ Delete(bmangle);
+ Delete(psmart);
+ Delete(btype);
+ }
+ base = Next(base);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ if (!multipleInheritance) {
+ /* Warn about multiple inheritance for additional base class(es) */
+ while (base.item) {
+ if (GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ continue;
+ }
+ String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
+ String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
+ Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s, base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname);
+ base = Next(base);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Check to see if a %markfunc was specified.
+ */
+ void handleMarkFuncDirective(Node *n) {
+ String *markfunc = Getattr(n, "feature:markfunc");
+ if (markfunc) {
+ Printf(klass->init, "SwigClass%s.mark = (void (*)(void *)) %s;\n", klass->name, markfunc);
+ } else {
+ Printf(klass->init, "SwigClass%s.mark = 0;\n", klass->name);
+ }
+ }
+
+ /**
+ * Check to see if a %freefunc was specified.
+ */
+ void handleFreeFuncDirective(Node *n) {
+ String *freefunc = Getattr(n, "feature:freefunc");
+ if (freefunc) {
+ Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) %s;\n", klass->name, freefunc);
+ } else {
+ if (klass->destructor_defined) {
+ Printf(klass->init, "SwigClass%s.destroy = (void (*)(void *)) free_%s;\n", klass->name, klass->mname);
+ }
+ }
+ }
+
+ /**
+ * Check to see if tracking is enabled for this class.
+ */
+ void handleTrackDirective(Node *n) {
+ int trackObjects = GetFlag(n, "feature:trackobjects");
+ if (trackObjects) {
+ Printf(klass->init, "SwigClass%s.trackObjects = 1;\n", klass->name);
+ } else {
+ Printf(klass->init, "SwigClass%s.trackObjects = 0;\n", klass->name);
+ }
+ }
+
+ /* ----------------------------------------------------------------------
+ * classHandler()
+ * ---------------------------------------------------------------------- */
+
+ virtual int classHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_CLASS);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *namestr = SwigType_namestr(name); // does template expansion
+
+ klass = RCLASS(classes, Char(namestr));
+ assert(klass != 0);
+ Delete(namestr);
+ String *valid_name = NewString(symname);
+ validate_const_name(Char(valid_name), "class");
+
+ Clear(klass->type);
+ Printv(klass->type, Getattr(n, "classtype"), NIL);
+ Printv(f_wrappers, "static swig_class SwigClass", valid_name, ";\n\n", NIL);
+ Printv(klass->init, "\n", tab4, NIL);
+
+ if (!useGlobalModule) {
+ Printv(klass->init, klass->vname, " = rb_define_class_under(", modvar, ", \"", klass->name, "\", $super);\n", NIL);
+ } else {
+ Printv(klass->init, klass->vname, " = rb_define_class(\"", klass->name,
+ "\", $super);\n", NIL);
+ }
+
+ if (multipleInheritance) {
+ Printv(klass->init, klass->mImpl, " = rb_define_module_under(", klass->vname, ", \"Impl\");\n", NIL);
+ }
+
+ SwigType *tt = NewString(name);
+ SwigType_add_pointer(tt);
+ SwigType_remember(tt);
+ SwigType *smart = Getattr(n, "smart");
+ SwigType *psmart = smart ? Copy(smart) : 0;
+ if (psmart) {
+ SwigType_add_pointer(psmart);
+ SwigType_remember(psmart);
+ }
+ String *tm = SwigType_manglestr(psmart ? psmart : tt);
+ Printf(klass->init, "SWIG_TypeClientData(SWIGTYPE%s, (void *) &SwigClass%s);\n", tm, valid_name);
+ Delete(tm);
+ Delete(psmart);
+ Delete(tt);
+ Delete(valid_name);
+
+ includeRubyModules(n);
+
+ Printv(klass->init, "$allocator", NIL);
+ Printv(klass->init, "$initializer", NIL);
+
+ Language::classHandler(n);
+
+ handleBaseClasses(n);
+ handleMarkFuncDirective(n);
+ handleFreeFuncDirective(n);
+ handleTrackDirective(n);
+
+ if (multipleInheritance) {
+ Printv(klass->init, "rb_include_module(", klass->vname, ", ", klass->mImpl, ");\n", NIL);
+ }
+
+ String *s = NewString("");
+ Printv(s, tab4, "rb_undef_alloc_func(", klass->vname, ");\n", NIL);
+ Replaceall(klass->init, "$allocator", s);
+ Replaceall(klass->init, "$initializer", "");
+
+ if (GetFlag(n, "feature:exceptionclass")) {
+ Replaceall(klass->init, "$super", "rb_eRuntimeError");
+ } else {
+ Replaceall(klass->init, "$super", "rb_cObject");
+ }
+ Delete(s);
+
+ Printv(f_init, klass->init, NIL);
+ klass = 0;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberfunctionHandler()
+ *
+ * Method for adding C++ member function
+ *
+ * By default, we're going to create a function of the form :
+ *
+ * Foo_bar(this,args)
+ *
+ * Where Foo is the classname, bar is the member name and the this pointer
+ * is explicitly attached to the beginning.
+ *
+ * The renaming only applies to the member function part, not the full
+ * classname.
+ *
+ * --------------------------------------------------------------------- */
+
+ virtual int memberfunctionHandler(Node *n) {
+ current = MEMBER_FUNC;
+
+ String* docs = docstring(n, AUTODOC_METHOD);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ Language::memberfunctionHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * constructorHandler()
+ *
+ * Method for adding C++ member constructor
+ * -------------------------------------------------------------------- */
+
+ void set_director_ctor_code(Node *n) {
+ /* director ctor code is specific for each class */
+ Delete(director_prot_ctor_code);
+ director_prot_ctor_code = NewString("");
+ Node *pn = Swig_methodclass(n);
+ String *symname = Getattr(pn, "sym:name");
+ String *name = Copy(symname);
+ char *cname = Char(name);
+ if (cname)
+ cname[0] = (char)toupper(cname[0]);
+ Printv(director_prot_ctor_code,
+ "if ( $comparison ) { /* subclassed */\n",
+ " $director_new \n",
+ "} else {\n", " rb_raise(rb_eNameError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("");
+ Printv(director_ctor_code, "if ( $comparison ) { /* subclassed */\n", " $director_new \n", "} else {\n", " $nondirector_new \n", "}\n", NIL);
+ Delete(name);
+ }
+
+ virtual int constructorHandler(Node *n) {
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ set_director_ctor_code(n);
+ }
+
+ /* First wrap the allocate method */
+ current = CONSTRUCTOR_ALLOCATE;
+ Swig_name_register("construct", "%n%c_allocate");
+
+ Language::constructorHandler(n);
+
+ String* docs = docstring(n, AUTODOC_CTOR);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ /*
+ * If we're wrapping the constructor of a C++ director class, prepend a new parameter
+ * to receive the scripting language object (e.g. 'self')
+ *
+ */
+ Swig_save("ruby:constructorHandler", n, "parms", NIL);
+ if (use_director) {
+ Parm *parms = Getattr(n, "parms");
+ Parm *self;
+ String *name = NewString("self");
+ String *type = NewString("VALUE");
+ self = NewParm(type, name, n);
+ Delete(type);
+ Delete(name);
+ Setattr(self, "lname", "Qnil");
+ if (parms)
+ set_nextSibling(self, parms);
+ Setattr(n, "parms", self);
+ Setattr(n, "wrap:self", "1");
+ Delete(self);
+ }
+
+ /* Now do the instance initialize method */
+ current = CONSTRUCTOR_INITIALIZE;
+ Swig_name_register("construct", "new_%n%c");
+ Language::constructorHandler(n);
+
+ /* Restore original parameter list */
+ Delattr(n, "wrap:self");
+ Swig_restore(n);
+
+ /* Done */
+ Swig_name_unregister("construct");
+ current = NO_CPP;
+ klass->constructor_defined = 1;
+ return SWIG_OK;
+ }
+
+ virtual int copyconstructorHandler(Node *n) {
+ int use_director = Swig_directorclass(n);
+ if (use_director) {
+ set_director_ctor_code(n);
+ }
+
+ /* First wrap the allocate method */
+ current = CONSTRUCTOR_ALLOCATE;
+ Swig_name_register("construct", "%n%c_allocate");
+
+ return Language::copyconstructorHandler(n);
+ }
+
+
+ /* ---------------------------------------------------------------------
+ * destructorHandler()
+ * -------------------------------------------------------------------- */
+
+ virtual int destructorHandler(Node *n) {
+
+ /* Do no spit free function if user defined his own for this class */
+ Node *pn = Swig_methodclass(n);
+ String *freefunc = Getattr(pn, "feature:freefunc");
+ if (freefunc) return SWIG_OK;
+
+ current = DESTRUCTOR;
+ Language::destructorHandler(n);
+
+ freefunc = NewString("");
+ String *freebody = NewString("");
+ String *pname0 = Swig_cparm_name(0, 0);
+
+ Printv(freefunc, "free_", klass->mname, NIL);
+ Printv(freebody, "SWIGINTERN void\n", freefunc, "(void *self) {\n", NIL);
+ Printv(freebody, tab4, klass->type, " *", pname0, " = (", klass->type, " *)self;\n", NIL);
+ Printv(freebody, tab4, NIL);
+
+ /* Check to see if object tracking is activated for the class
+ that owns this destructor. */
+ if (GetFlag(pn, "feature:trackobjects")) {
+ Printf(freebody, "SWIG_RubyRemoveTracking(%s);\n", pname0);
+ Printv(freebody, tab4, NIL);
+ }
+
+ if (Extend) {
+ String *wrap = Getattr(n, "wrap:code");
+ if (wrap) {
+ Printv(f_wrappers, wrap, NIL);
+ }
+ /* Printv(freebody, Swig_name_destroy(name), "(", pname0, ")", NIL); */
+ Printv(freebody, Getattr(n, "wrap:action"), "\n", NIL);
+ } else {
+ String *action = Getattr(n, "wrap:action");
+ if (action) {
+ Printv(freebody, action, "\n", NIL);
+ } else {
+ /* In the case swig emits no destroy function. */
+ if (CPlusPlus)
+ Printf(freebody, "delete %s;\n", pname0);
+ else
+ Printf(freebody, "free((char*) %s);\n", pname0);
+ }
+ }
+
+ Printv(freebody, "}\n\n", NIL);
+
+ Printv(f_wrappers, freebody, NIL);
+
+ klass->destructor_defined = 1;
+ current = NO_CPP;
+ Delete(freefunc);
+ Delete(freebody);
+ Delete(pname0);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * membervariableHandler()
+ *
+ * This creates a pair of functions to set/get the variable of a member.
+ * -------------------------------------------------------------------- */
+
+ virtual int membervariableHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_GETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ if (!is_immutable(n)) {
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+ }
+
+ current = MEMBER_VAR;
+ Language::membervariableHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * staticmemberfunctionHandler()
+ *
+ * Wrap a static C++ function
+ * ---------------------------------------------------------------------- */
+
+ virtual int staticmemberfunctionHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_STATICFUNC);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ current = STATIC_FUNC;
+ Language::staticmemberfunctionHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ----------------------------------------------------------------------
+ * memberconstantHandler()
+ *
+ * Create a C++ constant
+ * --------------------------------------------------------------------- */
+
+ virtual int memberconstantHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_STATICFUNC);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ current = CLASS_CONST;
+ Language::memberconstantHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * staticmembervariableHandler()
+ * --------------------------------------------------------------------- */
+
+ virtual int staticmembervariableHandler(Node *n) {
+ String* docs = docstring(n, AUTODOC_GETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+
+ if (!is_immutable(n)) {
+ String* docs = docstring(n, AUTODOC_SETTER);
+ Printf(f_wrappers, "%s", docs);
+ Delete(docs);
+ }
+
+ current = STATIC_VAR;
+ Language::staticmembervariableHandler(n);
+ current = NO_CPP;
+ return SWIG_OK;
+ }
+
+ /* C++ director class generation */
+ virtual int classDirector(Node *n) {
+ return Language::classDirector(n);
+ }
+
+ virtual int classDirectorInit(Node *n) {
+ String *declaration;
+ declaration = Swig_director_declaration(n);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "%s\n", declaration);
+ Printf(f_directors_h, "public:\n");
+ Delete(declaration);
+ return Language::classDirectorInit(n);
+ }
+
+ virtual int classDirectorEnd(Node *n) {
+ Printf(f_directors_h, "};\n\n");
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorConstructor()
+ * ------------------------------------------------------------ */
+
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = Getattr(n, "parentNode");
+ String *sub = NewString("");
+ String *decl = Getattr(n, "decl");
+ String *supername = Swig_class_name(parent);
+ String *classname = NewString("");
+ Printf(classname, "SwigDirector_%s", supername);
+
+ /* insert self parameter */
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms = CopyParmList(superparms);
+ String *type = NewString("VALUE");
+ p = NewParm(type, NewString("self"), n);
+ set_nextSibling(p, parms);
+ parms = p;
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ Wrapper *w = NewWrapper();
+ String *call;
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0);
+ call = Swig_csuperclass_call(0, basetype, superparms);
+ Printf(w->def, "%s::%s: %s, Swig::Director(self) { }", classname, target, call);
+ Delete(target);
+ Wrapper_print(w, f_directors);
+ Delete(call);
+ DelWrapper(w);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(classname);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDirectorDefaultConstructor()
+ * ------------------------------------------------------------ */
+
+ virtual int classDirectorDefaultConstructor(Node *n) {
+ String *classname;
+ Wrapper *w;
+ classname = Swig_class_name(n);
+ w = NewWrapper();
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s(VALUE self) : Swig::Director(self) { }", classname, classname);
+ Wrapper_print(w, f_directors);
+ DelWrapper(w);
+ Printf(f_directors_h, " SwigDirector_%s(VALUE self);\n", classname);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------
+ * exceptionSafeMethodCall()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying Ruby instance.
+ *
+ * --------------------------------------------------------------- */
+
+ void exceptionSafeMethodCall(String *className, Node *n, Wrapper *w, int argc, String *args, bool initstack) {
+ Wrapper *body = NewWrapper();
+ Wrapper *rescue = NewWrapper();
+
+ String *methodName = Getattr(n, "sym:name");
+
+ String *bodyName = NewStringf("%s_%s_body", className, methodName);
+ String *rescueName = NewStringf("%s_%s_rescue", className, methodName);
+ String *depthCountName = NewStringf("%s_%s_call_depth", className, methodName);
+
+ // Check for an exception typemap of some kind
+ String *tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
+ if (!tm) {
+ tm = Getattr(n, "feature:director:except");
+ }
+
+ if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) {
+ // Declare a global to hold the depth count
+ if (!Getattr(n, "sym:nextSibling")) {
+ Printf(body->def, "static int %s = 0;\n", depthCountName);
+
+ // Function body
+ Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName);
+ Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL);
+ Wrapper_add_localv(body, Swig_cresult_name(), "VALUE", Swig_cresult_name(), "= Qnil", NIL);
+ Printf(body->code, "%s++;\n", depthCountName);
+ Printv(body->code, Swig_cresult_name(), " = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
+ Printf(body->code, "%s--;\n", depthCountName);
+ Printv(body->code, "return ", Swig_cresult_name(), ";\n", NIL);
+ Printv(body->code, "}", NIL);
+
+ // Exception handler
+ Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName);
+ Replaceall(tm, "$error", "error");
+ Printf(rescue->code, "%s--;\n", depthCountName);
+ Printf(rescue->code, "if (%s == 0) ", depthCountName);
+ Printv(rescue->code, Str(tm), "\n", NIL);
+ Printv(rescue->code, "rb_exc_raise(error);\n", NIL);
+ Printv(rescue->code, "return Qnil;\n", NIL);
+ Printv(rescue->code, "}", NIL);
+ }
+
+ // Main code
+ Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL);
+ Wrapper_add_localv(w, "status", "int", "status", NIL);
+ Printv(w->code, "args.recv = swig_get_self();\n", NIL);
+ Printf(w->code, "args.id = rb_intern(\"%s\");\n", methodName);
+ Printf(w->code, "args.argc = %d;\n", argc);
+ if (argc > 0) {
+ Printf(w->code, "args.argv = new VALUE[%d];\n", argc);
+ for (int i = 0; i < argc; i++) {
+ Printf(w->code, "args.argv[%d] = obj%d;\n", i, i);
+ }
+ } else {
+ Printv(w->code, "args.argv = 0;\n", NIL);
+ }
+ Printf(w->code, "%s = rb_protect(PROTECTFUNC(%s), reinterpret_cast<VALUE>(&args), &status);\n", Swig_cresult_name(), bodyName);
+ if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
+ Printf(w->code, "if (status) {\n");
+ Printf(w->code, "VALUE lastErr = rb_gv_get(\"$!\");\n");
+ Printf(w->code, "%s(reinterpret_cast<VALUE>(&args), lastErr);\n", rescueName);
+ Printf(w->code, "}\n");
+ if (argc > 0) {
+ Printv(w->code, "delete [] args.argv;\n", NIL);
+ }
+ // Dump wrapper code
+ Wrapper_print(body, f_directors_helpers);
+ Wrapper_print(rescue, f_directors_helpers);
+ } else {
+ if (argc > 0) {
+ Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), %d%s);\n", Swig_cresult_name(), methodName, argc, args);
+ } else {
+ Printf(w->code, "%s = rb_funcall(swig_get_self(), rb_intern(\"%s\"), 0, Qnil);\n", Swig_cresult_name(), methodName);
+ }
+ if ( initstack ) Printf(w->code, "SWIG_RELEASE_STACK;\n");
+ }
+
+ // Clean up
+ Delete(bodyName);
+ Delete(rescueName);
+ Delete(depthCountName);
+ DelWrapper(body);
+ DelWrapper(rescue);
+ }
+
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ int is_void = 0;
+ int is_pointer = 0;
+ String *decl = Getattr(n, "decl");
+ String *name = Getattr(n, "name");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *symname = Getattr(n, "sym:name");
+ String *declaration = NewString("");
+ ParmList *l = Getattr(n, "parms");
+ Wrapper *w = NewWrapper();
+ String *tm;
+ String *wrap_args = NewString("");
+ SwigType *returntype = Getattr(n, "type");
+ Parm *p;
+ String *value = Getattr(n, "value");
+ String *storage = Getattr(n, "storage");
+ bool pure_virtual = false;
+ int status = SWIG_OK;
+ int idx;
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+ bool asvoid = checkAttribute( n, "feature:numoutputs", "0") ? true : false;
+ bool initstack = checkAttribute( n, "feature:initstack", "1") ? true : false;
+
+ if (Cmp(storage, "virtual") == 0) {
+ if (Cmp(value, "0") == 0) {
+ pure_virtual = true;
+ }
+ }
+ String *overnametmp = NewString(Getattr(n, "sym:name"));
+ if (Getattr(n, "sym:overloaded")) {
+ Printf(overnametmp, "::%s", Getattr(n, "sym:overname"));
+ }
+
+ /* determine if the method returns a pointer */
+ is_pointer = SwigType_ispointer_return(decl);
+ is_void = (!Cmp(returntype, "void") && !is_pointer);
+
+ /* virtual method definition */
+ String *target;
+ String *pclassname = NewStringf("SwigDirector_%s", classname);
+ String *qualified_name = NewStringf("%s::%s", pclassname, name);
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ /* header declaration */
+ target = Swig_method_decl(rtype, decl, name, l, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Get any exception classes in the throws typemap
+ if (Getattr(n, "noexcept")) {
+ Append(w->def, " noexcept");
+ Append(declaration, " noexcept");
+ }
+ ParmList *throw_parm_list = 0;
+
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ Parm *p;
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if (Getattr(p, "tmap:throws")) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ if (initstack && !(ignored_method && !pure_virtual)) {
+ Append(w->def, "\nSWIG_INIT_STACK;\n");
+ }
+
+ /* declare method return value
+ * if the return value is a reference or const reference, a specialized typemap must
+ * handle it, including declaration of c_result ($result).
+ */
+ if (!is_void && (!ignored_method || pure_virtual)) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ }
+ } else {
+ String *cres = SwigType_lstr(returntype, "c_result");
+ Printf(w->code, "%s;\n", cres);
+ Delete(cres);
+ }
+ }
+
+ if (ignored_method) {
+ if (!pure_virtual) {
+ if (!is_void)
+ Printf(w->code, "return ");
+ String *super_call = Swig_method_call(super, l);
+ Printf(w->code, "%s;\n", super_call);
+ Delete(super_call);
+ } else {
+ Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
+ SwigType_namestr(name));
+ }
+ } else {
+ /* attach typemaps to arguments (C/C++ -> Ruby) */
+ String *arglist = NewString("");
+
+ Swig_director_parms_fixup(l);
+
+ Swig_typemap_attach_parms("in", l, 0);
+ Swig_typemap_attach_parms("directorin", l, w);
+ Swig_typemap_attach_parms("directorargout", l, w);
+
+ char source[256];
+
+ int outputs = 0;
+ if (!is_void && !asvoid)
+ outputs++;
+
+ /* build argument list and type conversion string */
+ idx = 0; p = l;
+ while ( p ) {
+ if (Getattr(p, "tmap:directorargout") != 0)
+ outputs++;
+
+ if ( checkAttribute( p, "tmap:in:numinputs", "0") ) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ String *parameterName = Getattr(p, "name");
+ String *parameterType = Getattr(p, "type");
+
+ Putc(',', arglist);
+ if ((tm = Getattr(p, "tmap:directorin")) != 0) {
+ sprintf(source, "obj%d", idx++);
+ String *input = NewString(source);
+ Setattr(p, "emit:directorinput", input);
+ Replaceall(tm, "$input", input);
+ Replaceall(tm, "$owner", "0");
+ Delete(input);
+ Printv(wrap_args, tm, "\n", NIL);
+ Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
+ Printv(arglist, source, NIL);
+ p = Getattr(p, "tmap:directorin:next");
+ continue;
+ } else if (Cmp(parameterType, "void")) {
+ /**
+ * Special handling for pointers to other C++ director classes.
+ * Ideally this would be left to a typemap, but there is currently no
+ * way to selectively apply the dynamic_cast<> to classes that have
+ * directors. In other words, the type "SwigDirector_$1_lname" only exists
+ * for classes with directors. We avoid the problem here by checking
+ * module.wrap::directormap, but it's not clear how to get a typemap to
+ * do something similar. Perhaps a new default typemap (in addition
+ * to SWIGTYPE) called DIRECTORTYPE?
+ */
+ if (SwigType_ispointer(parameterType) || SwigType_isreference(parameterType)) {
+ Node *modname = Getattr(parent, "module");
+ Node *target = Swig_directormap(modname, parameterType);
+ sprintf(source, "obj%d", idx++);
+ String *nonconst = 0;
+ /* strip pointer/reference --- should move to Swig/stype.c */
+ String *nptype = NewString(Char(parameterType) + 2);
+ /* name as pointer */
+ String *ppname = Copy(parameterName);
+ if (SwigType_isreference(parameterType)) {
+ Insert(ppname, 0, "&");
+ }
+ /* if necessary, cast away const since Ruby doesn't support it! */
+ if (SwigType_isconst(nptype)) {
+ nonconst = NewStringf("nc_tmp_%s", parameterName);
+ String *nonconst_i = NewStringf("= const_cast< %s >(%s)", SwigType_lstr(parameterType, 0), ppname);
+ Wrapper_add_localv(w, nonconst, SwigType_lstr(parameterType, 0), nonconst, nonconst_i, NIL);
+ Delete(nonconst_i);
+ Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
+ "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(parameterType, parameterName),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ } else {
+ nonconst = Copy(ppname);
+ }
+ Delete(nptype);
+ Delete(ppname);
+ String *mangle = SwigType_manglestr(parameterType);
+ if (target) {
+ String *director = NewStringf("director_%s", mangle);
+ Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
+ Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
+ Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst);
+ Printf(wrap_args, "if (!%s) {\n", director);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ Printf(wrap_args, "} else {\n");
+ Printf(wrap_args, "%s = %s->swig_get_self();\n", source, director);
+ Printf(wrap_args, "}\n");
+ Delete(director);
+ Printv(arglist, source, NIL);
+ } else {
+ Wrapper_add_localv(w, source, "VALUE", source, "= Qnil", NIL);
+ Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
+ //Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
+ // source, nonconst, base);
+ Printv(arglist, source, NIL);
+ }
+ Delete(mangle);
+ Delete(nonconst);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
+ "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(parameterType, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_NOWRAP;
+ break;
+ }
+ }
+ p = nextSibling(p);
+ }
+
+ /* declare Ruby return value */
+ String *value_result = NewStringf("VALUE SWIGUNUSED %s", Swig_cresult_name());
+ Wrapper_add_local(w, Swig_cresult_name(), value_result);
+ Delete(value_result);
+
+ /* wrap complex arguments to VALUEs */
+ Printv(w->code, wrap_args, NIL);
+
+ /* pass the method call on to the Ruby object */
+ exceptionSafeMethodCall(classname, n, w, idx, arglist, initstack);
+
+ /*
+ * Ruby method may return a simple object, or an Array of objects.
+ * For in/out arguments, we have to extract the appropriate VALUEs from the Array,
+ * then marshal everything back to C/C++ (return value and output arguments).
+ */
+
+ /* Marshal return value and other outputs (if any) from VALUE to C/C++ type */
+
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+
+ if (outputs > 1) {
+ Wrapper_add_local(w, "output", "VALUE output");
+ Printf(w->code, "if (TYPE(%s) != T_ARRAY) {\n", Swig_cresult_name());
+ Printf(w->code, "Ruby_DirectorTypeMismatchException(\"Ruby method failed to return an array.\");\n");
+ Printf(w->code, "}\n");
+ }
+
+ idx = 0;
+
+ /* Marshal return value */
+ if (!is_void) {
+ tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
+ if (tm != 0) {
+ if (outputs > 1 && !asvoid ) {
+ Printf(w->code, "output = rb_ary_entry(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$input", "output");
+ } else {
+ Replaceall(tm, "$input", Swig_cresult_name());
+ }
+ /* TODO check this */
+ if (Getattr(n, "wrap:disown")) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+ Replaceall(tm, "$result", "c_result");
+ Printv(w->code, tm, "\n", NIL);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0),
+ SwigType_namestr(c_classname), SwigType_namestr(name));
+ status = SWIG_ERROR;
+ }
+ }
+
+ /* Marshal outputs */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
+ if (outputs > 1) {
+ Printf(w->code, "output = rb_ary_entry(%s, %d);\n", Swig_cresult_name(), idx++);
+ Replaceall(tm, "$result", "output");
+ } else {
+ Replaceall(tm, "$result", Swig_cresult_name());
+ }
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ Delete(arglist);
+ Delete(cleanup);
+ Delete(outarg);
+ }
+
+ /* any existing helper functions to handle this? */
+ if (!is_void) {
+ if (!(ignored_method && !pure_virtual)) {
+ String *rettype = SwigType_str(returntype, 0);
+ if (!SwigType_isreference(returntype)) {
+ Printf(w->code, "return (%s) c_result;\n", rettype);
+ } else {
+ Printf(w->code, "return (%s) *c_result;\n", rettype);
+ }
+ Delete(rettype);
+ }
+ }
+
+ Printf(w->code, "}\n");
+
+ // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit the director method */
+ if (status == SWIG_OK) {
+ Replaceall(w->code, "$isvoid", is_void ? "1" : "0");
+ if (!Getattr(n, "defaultargs")) {
+ Replaceall(w->code, "$symname", symname);
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ /* clean up */
+ Delete(wrap_args);
+ Delete(pclassname);
+ DelWrapper(w);
+ return status;
+ }
+
+ virtual int classDirectorConstructors(Node *n) {
+ return Language::classDirectorConstructors(n);
+ }
+
+ virtual int classDirectorMethods(Node *n) {
+ return Language::classDirectorMethods(n);
+ }
+
+ virtual int classDirectorDisown(Node *n) {
+ return Language::classDirectorDisown(n);
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *shead = Swig_include_sys("rubyhead.swg");
+ if (!shead) {
+ Printf(stderr, "*** Unable to open 'rubyhead.swg'\n");
+ } else {
+ Append(s, shead);
+ Delete(shead);
+ }
+ String *serrors = Swig_include_sys("rubyerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'rubyerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *strack = Swig_include_sys("rubytracking.swg");
+ if (!strack) {
+ Printf(stderr, "*** Unable to open 'rubytracking.swg'\n");
+ } else {
+ Append(s, strack);
+ Delete(strack);
+ }
+ String *sapi = Swig_include_sys("rubyapi.swg");
+ if (!sapi) {
+ Printf(stderr, "*** Unable to open 'rubyapi.swg'\n");
+ } else {
+ Append(s, sapi);
+ Delete(sapi);
+ }
+ String *srun = Swig_include_sys("rubyrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'rubyrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigrubyrun.h");
+ }
+
+ /*----------------------------------------------------------------------
+ * kwargsSupport()
+ *--------------------------------------------------------------------*/
+
+ bool kwargsSupport() const {
+ // kwargs support isn't actually implemented, but changing to return false may break something now as it turns on compactdefaultargs
+ return true;
+ }
+}; /* class RUBY */
+
+/* -----------------------------------------------------------------------------
+ * swig_ruby() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+
+static Language *new_swig_ruby() {
+ return new RUBY();
+}
+extern "C" Language *swig_ruby(void) {
+ return new_swig_ruby();
+}
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * End:
+ */
diff --git a/contrib/tools/swig/Source/Modules/scilab.cxx b/contrib/tools/swig/Source/Modules/scilab.cxx
new file mode 100644
index 00000000000..8a0af8928c2
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/scilab.cxx
@@ -0,0 +1,1223 @@
+/* ----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * scilab.cxx
+ *
+ * Scilab language module for SWIG.
+ * --------------------------------------------------------------------------*/
+
+#include "swigmod.h"
+#include <cstddef>
+#include <cstdlib>
+
+static const int SCILAB_IDENTIFIER_NAME_CHAR_MAX = 24;
+
+static const char *usage = (char *) " \
+Scilab options (available with -scilab)\n \
+ -builder - Generate a Scilab builder script\n \
+ -buildercflags <cflags> - Add <cflags> to the builder compiler flags\n \
+ -builderflagscript <file> - Set the Scilab script <file> to use by builder to configure the build flags\n \
+ -builderldflags <ldflags> - Add <ldflags> to the builder linker flags\n \
+ -buildersources <files> - Add the (comma separated) files <files> to the builder sources\n \
+ -builderverbositylevel <level> - Set the builder verbosity level to <level> (default 0: off, 2: high)\n \
+ -gatewayxml <gateway_id> - Generate gateway xml with the given <gateway_id>\n \
+ -gatewayxml6 - Generate gateway xml for Scilab 6\n \
+\n";
+
+
+class SCILAB:public Language {
+protected:
+ /* General objects used for holding the strings */
+ File *beginSection;
+ File *runtimeSection;
+ File *headerSection;
+ File *wrappersSection;
+ File *initSection;
+
+ String *variablesCode;
+
+ bool generateBuilder;
+ File *builderFile;
+ String *builderCode;
+ String *builderCode5;
+ String *builderCode6;
+ int builderFunctionCount;
+
+ List *sourceFileList;
+ List *cflags;
+ List *ldflags;
+
+ String *verboseBuildLevel;
+ String *buildFlagsScript;
+
+ String *gatewayHeader;
+ String *gatewayHeaderV5;
+ String *gatewayHeaderV6;
+
+ bool createGatewayXML;
+ File *gatewayXMLFile;
+ String *gatewayXML;
+ String *gatewayID;
+ int primitiveID;
+
+ bool createGatewayXMLV6;
+ File *gatewayXMLFileV6;
+ String *gatewayXMLV6;
+
+ bool createLoader;
+ File *loaderFile;
+ String *loaderScript;
+ String *loaderScript5;
+ String *loaderScript6;
+ int loaderFunctionCount;
+public:
+
+ /* ------------------------------------------------------------------------
+ * main()
+ * ----------------------------------------------------------------------*/
+
+ virtual void main(int argc, char *argv[]) {
+ generateBuilder = false;
+ sourceFileList = NewList();
+ cflags = NewList();
+ ldflags = NewList();
+ verboseBuildLevel = NULL;
+ buildFlagsScript = NULL;
+
+ gatewayHeader = NULL;
+ gatewayHeaderV5 = NULL;
+ gatewayHeaderV6 = NULL;
+
+ createGatewayXML = false;
+ gatewayXML = NULL;
+ gatewayXMLFile = NULL;
+ gatewayID = NULL;
+
+ createGatewayXMLV6 = false;
+ gatewayXMLV6 = NULL;
+ gatewayXMLFileV6 = NULL;
+
+ createLoader = true;
+ loaderFile = NULL;
+ loaderScript = NULL;
+
+ /* Manage command line arguments */
+ for (int argIndex = 1; argIndex < argc; argIndex++) {
+ if (argv[argIndex] != NULL) {
+ if (strcmp(argv[argIndex], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ } else if (strcmp(argv[argIndex], "-builder") == 0) {
+ Swig_mark_arg(argIndex);
+ generateBuilder = true;
+ createLoader = false;
+ } else if (strcmp(argv[argIndex], "-buildersources") == 0) {
+ if (argv[argIndex + 1] != NULL) {
+ Swig_mark_arg(argIndex);
+ char *sourceFile = strtok(argv[argIndex + 1], ",");
+ while (sourceFile != NULL) {
+ Insert(sourceFileList, Len(sourceFileList), sourceFile);
+ sourceFile = strtok(NULL, ",");
+ }
+ Swig_mark_arg(argIndex + 1);
+ }
+ } else if (strcmp(argv[argIndex], "-buildercflags") == 0) {
+ Swig_mark_arg(argIndex);
+ if (argv[argIndex + 1] != NULL) {
+ Insert(cflags, Len(cflags), argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ }
+ } else if (strcmp(argv[argIndex], "-builderldflags") == 0) {
+ Swig_mark_arg(argIndex);
+ if (argv[argIndex + 1] != NULL) {
+ Insert(ldflags, Len(ldflags), argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ }
+ } else if (strcmp(argv[argIndex], "-builderverbositylevel") == 0) {
+ Swig_mark_arg(argIndex);
+ verboseBuildLevel = NewString(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ } else if (strcmp(argv[argIndex], "-builderflagscript") == 0) {
+ Swig_mark_arg(argIndex);
+ buildFlagsScript = NewString(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ } else if (strcmp(argv[argIndex], "-gatewayxml") == 0) {
+ Swig_mark_arg(argIndex);
+ createGatewayXML = true;
+ gatewayID = NewString(argv[argIndex + 1]);
+ Swig_mark_arg(argIndex + 1);
+ } else if (strcmp(argv[argIndex], "-gatewayxml6") == 0) {
+ Swig_mark_arg(argIndex);
+ createGatewayXMLV6 = true;
+ }
+ }
+ }
+
+ if (verboseBuildLevel == NULL) {
+ verboseBuildLevel = NewString("0");
+ }
+
+ /* Set language-specific subdirectory in SWIG library */
+ SWIG_library_directory("scilab");
+
+ /* Add a symbol to the parser for conditional compilation */
+ Preprocessor_define("SWIGSCILAB 1", 0);
+
+ /* Set scilab configuration file */
+ SWIG_config_file("scilab.swg");
+
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------------------
+ * top()
+ * ----------------------------------------------------------------------*/
+
+ virtual int top(Node *node) {
+
+ /* Get the module name */
+ String *gatewayName = Getattr(node, "name");
+
+ // Set library name
+ String *gatewayLibraryName = NewStringf("lib%s", gatewayName);
+
+ /* Get the output file name */
+ String *outputFilename = Getattr(node, "outfile");
+
+ /* Initialize I/O */
+ beginSection = NewFile(outputFilename, "w", SWIG_output_files());
+ if (!beginSection) {
+ FileErrorDisplay(outputFilename);
+ Exit(EXIT_FAILURE);
+ }
+ runtimeSection = NewString("");
+ initSection = NewString("");
+ headerSection = NewString("");
+ wrappersSection = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("begin", beginSection);
+ Swig_register_filebyname("header", headerSection);
+ Swig_register_filebyname("wrapper", wrappersSection);
+ Swig_register_filebyname("runtime", runtimeSection);
+ Swig_register_filebyname("init", initSection);
+
+ /* Output module initialization code */
+ Swig_banner(beginSection);
+
+ Swig_obligatory_macros(runtimeSection, "SCILAB");
+
+ // Gateway header source merged with wrapper source in nobuilder mode
+ if (!generateBuilder)
+ startGatewayHeader(gatewayLibraryName);
+
+ // Create builder file if required
+ if (generateBuilder) {
+ createBuilderFile(outputFilename);
+ }
+
+ // Create gateway XML if required
+ if (createGatewayXML) {
+ createGatewayXMLFile(gatewayName);
+ }
+
+ // Create gateway XML V6 if required
+ if (createGatewayXMLV6) {
+ createGatewayXMLFileV6(gatewayName);
+ }
+
+ // Create loader script if required
+ if (createLoader) {
+ createLoaderFile(gatewayLibraryName);
+ }
+
+ // Module initialization function
+ String *smallFunctionName = createSmallIdentifierName(gatewayName, SCILAB_IDENTIFIER_NAME_CHAR_MAX - 5);
+ String *gatewayInitFunctionName = NewStringf("%s_Init", gatewayName);
+ String *gatewayInitSmallFunctionName = NewStringf("%s_Init", smallFunctionName);
+ String *wrapperFunctionName = NewStringf("SWIG_%s_Init", gatewayName);
+
+ /* Add initialization function to builder table */
+ addFunctionToScilab(gatewayInitFunctionName, gatewayInitSmallFunctionName, wrapperFunctionName);
+
+ // Add helper functions to builder table
+ addHelperFunctions();
+
+ // Open Scilab wrapper variables creation function
+ variablesCode = NewString("");
+ Printf(variablesCode, "int SWIG_CreateScilabVariables(void *_pvApiCtx) {");
+
+ /* Emit code for children */
+ if (CPlusPlus) {
+ Printf(wrappersSection, "extern \"C\" {\n");
+ }
+
+ Language::top(node);
+
+ if (CPlusPlus) {
+ Printf(wrappersSection, "}\n");
+ }
+ // Close Scilab wrapper variables creation function
+ Printf(variablesCode, " return SWIG_OK;\n}\n");
+
+ // Add Builder footer code and save
+ if (generateBuilder) {
+ saveBuilderFile(gatewayLibraryName);
+ }
+
+ /* Close the init function and rename with module name */
+ Printf(initSection, "return 0;\n}\n");
+ Replaceall(initSection, "<module>", gatewayName);
+
+ /* Write all to the wrapper file */
+ SwigType_emit_type_table(runtimeSection, wrappersSection); // Declare pointer types, ... (Ex: SWIGTYPE_p_p_double)
+
+ // Gateway header source merged with wrapper source in nobuilder mode
+ if (!generateBuilder) {
+ terminateGatewayHeader(gatewayLibraryName);
+ Printv(initSection, gatewayHeader, NIL);
+ }
+
+ Dump(runtimeSection, beginSection);
+ Dump(headerSection, beginSection);
+ Dump(wrappersSection, beginSection);
+ Dump(variablesCode, beginSection);
+ Wrapper_pretty_print(initSection, beginSection);
+
+ if (createGatewayXML) {
+ saveGatewayXMLFile();
+ }
+ if (createGatewayXMLV6) {
+ saveGatewayXMLFileV6();
+ }
+
+ if (createLoader) {
+ saveLoaderFile(gatewayLibraryName);
+ }
+
+ /* Cleanup files */
+ Delete(runtimeSection);
+ Delete(headerSection);
+ Delete(wrappersSection);
+ Delete(initSection);
+ Delete(beginSection);
+
+ Delete(sourceFileList);
+ Delete(cflags);
+ Delete(ldflags);
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------------------
+ * emitBanner()
+ * ----------------------------------------------------------------------*/
+
+ void emitBanner(File *f) {
+ Printf(f, "// ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, "// ");
+ Printf(f, "// ----------------------------------------------------------------------------- */\n\n");
+ }
+
+ /* ------------------------------------------------------------------------
+ * functionWrapper()
+ * ----------------------------------------------------------------------*/
+
+ virtual int functionWrapper(Node *node) {
+
+ /* Get some useful attributes of this function */
+ String *functionName = Getattr(node, "sym:name");
+ String *smallFunctionName = createSmallIdentifierName(functionName);
+
+ SwigType *functionReturnType = Getattr(node, "type");
+ ParmList *functionParamsList = Getattr(node, "parms");
+
+ int paramIndex = 0; // Used for loops over ParmsList
+ Parm *param = NULL; // Used for loops over ParamsList
+
+ /* Create the wrapper object */
+ Wrapper *wrapper = NewWrapper();
+
+ /* Create the function wrapper name */
+ String *wrapperName = Swig_name_wrapper(functionName);
+
+ /* Deal with overloading */
+ String *overloadedName = Copy(wrapperName);
+ /* Determine whether the function is overloaded or not */
+ bool isOverloaded = ! !Getattr(node, "sym:overloaded");
+ /* Determine whether the function is the last overloaded */
+ bool isLastOverloaded = isOverloaded && !Getattr(node, "sym:nextSibling");
+
+ if (!isOverloaded && !addSymbol(functionName, node)) {
+ DelWrapper(wrapper);
+ return SWIG_ERROR;
+ }
+
+ if (isOverloaded) {
+ Append(overloadedName, Getattr(node, "sym:overname"));
+ }
+
+ /* Write the wrapper function definition (standard Scilab gateway function prototype) */
+ Printv(wrapper->def, "SWIGEXPORT int ", overloadedName, "(SWIG_GatewayParameters) {", NIL);
+
+ /* Emit all of the local variables for holding arguments */
+ // E.g.: double arg1;
+ emit_parameter_variables(functionParamsList, wrapper);
+
+ /* Attach typemaps to the parameter list */
+ // Add local variables used in typemaps (iRows, iCols, ...)
+ emit_attach_parmmaps(functionParamsList, wrapper);
+ Setattr(node, "wrap:parms", functionParamsList);
+
+ /* Check input/output arguments count */
+ int maxInputArguments = emit_num_arguments(functionParamsList);
+ int minInputArguments = emit_num_required(functionParamsList);
+ int minOutputArguments = 0;
+ int maxOutputArguments = 0;
+
+ if (!emit_isvarargs(functionParamsList)) {
+ Printf(wrapper->code, "SWIG_CheckInputArgument(pvApiCtx, $mininputarguments, $maxinputarguments);\n");
+ }
+ else {
+ Printf(wrapper->code, "SWIG_CheckInputArgumentAtLeast(pvApiCtx, $mininputarguments-1);\n");
+ }
+ Printf(wrapper->code, "SWIG_CheckOutputArgument(pvApiCtx, $minoutputarguments, $maxoutputarguments);\n");
+
+ /* Set context */
+ Printf(wrapper->code, "SWIG_Scilab_SetFuncName(fname);\n");
+ Printf(wrapper->code, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ /* Write typemaps(in) */
+
+ for (paramIndex = 0, param = functionParamsList; paramIndex < maxInputArguments; ++paramIndex) {
+ // Ignore parameter if the typemap specifies numinputs=0
+ while (checkAttribute(param, "tmap:in:numinputs", "0")) {
+ param = Getattr(param, "tmap:in:next");
+ }
+
+ SwigType *paramType = Getattr(param, "type");
+ String *paramTypemap = Getattr(param, "tmap:in");
+
+ if (paramTypemap) {
+ // Replace $input by the position on Scilab stack
+ String *source = NewString("");
+ Printf(source, "%d", paramIndex + 1);
+ Setattr(param, "emit:input", source);
+ Replaceall(paramTypemap, "$input", Getattr(param, "emit:input"));
+
+ if (Getattr(param, "wrap:disown") || (Getattr(param, "tmap:in:disown"))) {
+ Replaceall(paramTypemap, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(paramTypemap, "$disown", "0");
+ }
+
+ if (paramIndex >= minInputArguments) { /* Optional input argument management */
+ Printf(wrapper->code, "if (SWIG_NbInputArgument(pvApiCtx) > %d) {\n%s\n}\n", paramIndex, paramTypemap);
+ } else {
+ Printf(wrapper->code, "%s\n", paramTypemap);
+ }
+ param = Getattr(param, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(paramType, 0));
+ break;
+ }
+ }
+
+ /* TODO write constraints */
+
+ Setattr(node, "wrap:name", overloadedName);
+
+ /* Emit the function call */
+ Swig_director_emit_dynamic_cast(node, wrapper);
+ String *functionActionCode = emit_action(node);
+
+ /* Insert the return variable */
+ emit_return_variable(node, functionReturnType, wrapper);
+
+ /* Return the function value if necessary */
+ String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, Swig_cresult_name(), wrapper, functionActionCode);
+ if (functionReturnTypemap) {
+ // Result is actually the position of output value on stack
+ if (Len(functionReturnTypemap) > 0) {
+ Printf(wrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1);
+ }
+ Replaceall(functionReturnTypemap, "$result", "1");
+
+ if (GetFlag(node, "feature:new")) {
+ Replaceall(functionReturnTypemap, "$owner", "1");
+ } else {
+ Replaceall(functionReturnTypemap, "$owner", "0");
+ }
+
+ Printf(wrapper->code, "%s\n", functionReturnTypemap);
+
+ /* If the typemap is not empty, the function return one more argument than the typemaps gives */
+ if (Len(functionReturnTypemap) > 0) {
+ minOutputArguments++;
+ maxOutputArguments++;
+ }
+ Delete(functionReturnTypemap);
+
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(functionReturnType, 0),
+ functionName);
+ }
+
+ /* Write typemaps(out) */
+ for (param = functionParamsList; param;) {
+ String *paramTypemap = Getattr(param, "tmap:argout");
+ if (paramTypemap) {
+ minOutputArguments++;
+ maxOutputArguments++;
+ Printf(wrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", minOutputArguments);
+ String *result = NewString("");
+ Printf(result, "%d", minOutputArguments);
+ Replaceall(paramTypemap, "$result", result);
+ Printf(wrapper->code, "%s\n", paramTypemap);
+ Delete(paramTypemap);
+ param = Getattr(param, "tmap:argout:next");
+ } else {
+ param = nextSibling(param);
+ }
+ }
+ /* Add cleanup code */
+ for (param = functionParamsList; param;) {
+ String *tm;
+ if ((tm = Getattr(param, "tmap:freearg"))) {
+ if (tm && (Len(tm) != 0)) {
+ Printf(wrapper->code, "%s\n", tm);
+ }
+ param = Getattr(param, "tmap:freearg:next");
+ } else {
+ param = nextSibling(param);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ String *tm;
+ if ((tm = Swig_typemap_lookup("ret", node, Swig_cresult_name(), 0))) {
+ Printf(wrapper->code, "%s\n", tm);
+ Delete(tm);
+ }
+
+ /* Close the function(ok) */
+ Printv(wrapper->code, "return SWIG_OK;\n", NIL);
+ Printv(wrapper->code, "}\n", NIL);
+
+ /* Add the failure cleanup code */
+ /* TODO */
+
+ /* Final substitutions if applicable */
+ bool isvoid = !Cmp(functionReturnType, "void");
+ Replaceall(wrapper->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(wrapper->code, "$symname", functionName);
+
+ /* Set CheckInputArgument and CheckOutputArgument input arguments */
+ if (maxOutputArguments < 1) {
+ maxOutputArguments = 1;
+ }
+ if (minOutputArguments == 1) {
+ minOutputArguments = 0;
+ }
+ String *argnumber = NewString("");
+ Printf(argnumber, "%d", minInputArguments);
+ Replaceall(wrapper->code, "$mininputarguments", argnumber);
+
+ argnumber = NewString("");
+ Printf(argnumber, "%d", maxInputArguments);
+ Replaceall(wrapper->code, "$maxinputarguments", argnumber);
+
+ argnumber = NewString("");
+ Printf(argnumber, "%d", minOutputArguments);
+ Replaceall(wrapper->code, "$minoutputarguments", argnumber);
+
+ argnumber = NewString("");
+ Printf(argnumber, "%d", maxOutputArguments);
+ Replaceall(wrapper->code, "$maxoutputarguments", argnumber);
+
+ /* Dump the function out */
+ Wrapper_print(wrapper, wrappersSection);
+
+ /* Update builder.sce contents */
+ if (isLastOverloaded) {
+ addFunctionToScilab(functionName, smallFunctionName, wrapperName);
+ dispatchFunction(node);
+ }
+
+ if (!isOverloaded) {
+ addFunctionToScilab(functionName, smallFunctionName, wrapperName);
+ }
+
+ /* tidy up */
+ Delete(overloadedName);
+ Delete(wrapperName);
+ DelWrapper(wrapper);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * dispatchFunction()
+ * ----------------------------------------------------------------------- */
+
+ void dispatchFunction(Node *node) {
+ Wrapper *wrapper = NewWrapper();
+
+ String *functionName = Getattr(node, "sym:name");
+ String *wrapperName = Swig_name_wrapper(functionName);
+ int maxargs = 0;
+
+ /* Generate the dispatch function */
+ String *dispatch = Swig_overload_dispatch(node, "return %s(SWIG_GatewayArguments);", &maxargs);
+ String *tmp = NewString("");
+
+ Printv(wrapper->def, "SWIGEXPORT int ", wrapperName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Get the number of the parameters */
+ Wrapper_add_local(wrapper, "argc", "int argc = SWIG_NbInputArgument(pvApiCtx)");
+ Printf(tmp, "int argv[%d] = {", maxargs);
+ for (int j = 0; j < maxargs; ++j) {
+ Printf(tmp, "%s%d", j ? "," : " ", j + 1);
+ }
+ Printf(tmp, "}");
+ Wrapper_add_local(wrapper, "argv", tmp);
+
+ Printf(wrapper->code, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ /* Dump the dispatch function */
+ Printv(wrapper->code, dispatch, "\n", NIL);
+ Printf(wrapper->code, "Scierror(999, _(\"No matching function for overload\"));\n");
+ Printf(wrapper->code, "return SWIG_ERROR;\n");
+ Printv(wrapper->code, "}\n", NIL);
+ Wrapper_print(wrapper, wrappersSection);
+
+ Delete(tmp);
+ DelWrapper(wrapper);
+ Delete(dispatch);
+ Delete(wrapperName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * variableWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int variableWrapper(Node *node) {
+
+ /* Get information about variable */
+ String *origVariableName = Getattr(node, "name"); // Ex: Shape::nshapes
+ String *variableName = Getattr(node, "sym:name"); // Ex; Shape_nshapes (can be used for function names, ...)
+ String *smallVariableName = createSmallIdentifierName(variableName, SCILAB_IDENTIFIER_NAME_CHAR_MAX - 4);
+
+ /* Manage GET function */
+ Wrapper *getFunctionWrapper = NewWrapper();
+ String *getFunctionName = Swig_name_get(NSPACE_TODO, variableName);
+ String *scilabGetFunctionName = Swig_name_get(NSPACE_TODO, variableName);
+ String *scilabGetSmallFunctionName = Swig_name_get(NSPACE_TODO, smallVariableName);
+
+ Setattr(node, "wrap:name", getFunctionName);
+ Printv(getFunctionWrapper->def, "SWIGEXPORT int ", getFunctionName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Check the number of input and output */
+ Printf(getFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 0, 0);\n");
+ Printf(getFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 0, 1);\n");
+ Printf(getFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ String *varoutTypemap = Swig_typemap_lookup("varout", node, origVariableName, 0);
+ if (varoutTypemap != NULL) {
+ Printf(getFunctionWrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1);
+ Replaceall(varoutTypemap, "$value", origVariableName);
+ Replaceall(varoutTypemap, "$result", "1");
+ emit_action_code(node, getFunctionWrapper->code, varoutTypemap);
+ Delete(varoutTypemap);
+ }
+ Append(getFunctionWrapper->code, "return SWIG_OK;\n");
+ Append(getFunctionWrapper->code, "}\n");
+ Wrapper_print(getFunctionWrapper, wrappersSection);
+
+ /* Add function to builder table */
+ addFunctionToScilab(scilabGetFunctionName, scilabGetSmallFunctionName, getFunctionName);
+
+ /* Manage SET function */
+ if (!is_immutable(node)) {
+ Wrapper *setFunctionWrapper = NewWrapper();
+ String *setFunctionName = Swig_name_set(NSPACE_TODO, variableName);
+ String *scilabSetFunctionName = Swig_name_set(NSPACE_TODO, variableName);
+ String *scilabSetSmallFunctionName = Swig_name_set(NSPACE_TODO, smallVariableName);
+
+ Setattr(node, "wrap:name", setFunctionName);
+ Printv(setFunctionWrapper->def, "SWIGEXPORT int ", setFunctionName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Check the number of input and output */
+ Printf(setFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 1, 1);\n");
+ Printf(setFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 0, 1);\n");
+ Printf(setFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ String *varinTypemap = Swig_typemap_lookup("varin", node, origVariableName, 0);
+ if (varinTypemap != NULL) {
+ Replaceall(varinTypemap, "$input", "1");
+ emit_action_code(node, setFunctionWrapper->code, varinTypemap);
+ Delete(varinTypemap);
+ }
+ Append(setFunctionWrapper->code, "return SWIG_OK;\n");
+ Append(setFunctionWrapper->code, "}\n");
+ Wrapper_print(setFunctionWrapper, wrappersSection);
+
+ /* Add function to builder table */
+ addFunctionToScilab(scilabSetFunctionName, scilabSetSmallFunctionName, setFunctionName);
+
+ DelWrapper(setFunctionWrapper);
+ }
+ DelWrapper(getFunctionWrapper);
+
+ return SWIG_OK;
+ }
+
+ /* -----------------------------------------------------------------------
+ * constantWrapper()
+ * ----------------------------------------------------------------------- */
+
+ virtual int constantWrapper(Node *node) {
+
+ /* Get the useful information from the node */
+ String *nodeName = Getattr(node, "name");
+ SwigType *type = Getattr(node, "type");
+ String *constantName = Getattr(node, "sym:name");
+ String *constantValue = Getattr(node, "value");
+ String *constantTypemap = NULL;
+
+ // If feature scilab:const enabled, constants & enums are wrapped to Scilab variables
+ if (GetFlag(node, "feature:scilab:const")) {
+ bool isConstant = ((SwigType_issimple(type)) || (SwigType_type(type) == T_STRING));
+ bool isEnum = (Cmp(nodeType(node), "enumitem") == 0);
+
+ if (isConstant || isEnum) {
+ if (isEnum) {
+ Setattr(node, "type", "double");
+ constantValue = Getattr(node, "value");
+ }
+
+ constantTypemap = Swig_typemap_lookup("scilabconstcode", node, nodeName, 0);
+ if (constantTypemap != NULL) {
+
+ Setattr(node, "wrap:name", constantName);
+ Replaceall(constantTypemap, "$result", constantName);
+ Replaceall(constantTypemap, "$value", constantValue);
+
+ emit_action_code(node, variablesCode, constantTypemap);
+ Delete(constantTypemap);
+ return SWIG_OK;
+ }
+ }
+ }
+
+ /* Create variables for member pointer constants, not supported by typemaps (like Python wrapper does) */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(constantName);
+ String *str = SwigType_str(type, wname);
+ Printf(headerSection, "static %s = %s;\n", str, constantValue);
+ Delete(str);
+ constantValue = wname;
+ }
+
+ // Constant names can have SCILAB_VARIABLE_NAME_CHAR_MAX because of suffixes "_get" added to function
+ String *smallConstantName = createSmallIdentifierName(constantName, SCILAB_IDENTIFIER_NAME_CHAR_MAX - 4);
+
+ /* Create GET function to get the constant value */
+ Wrapper *getFunctionWrapper = NewWrapper();
+ String *getFunctionName = Swig_name_get(NSPACE_TODO, constantName);
+ String *scilabGetSmallFunctionName = Swig_name_get(NSPACE_TODO, smallConstantName);
+ Setattr(node, "wrap:name", getFunctionName);
+ Setattr(node, "wrap:name", getFunctionName);
+ Printv(getFunctionWrapper->def, "SWIGEXPORT int ", getFunctionName, "(SWIG_GatewayParameters) {\n", NIL);
+
+ /* Check the number of input and output */
+ Printf(getFunctionWrapper->def, "SWIG_CheckInputArgument(pvApiCtx, 0, 0);\n");
+ Printf(getFunctionWrapper->def, "SWIG_CheckOutputArgument(pvApiCtx, 0, 1);\n");
+ Printf(getFunctionWrapper->def, "SWIG_Scilab_SetApiContext(pvApiCtx);\n");
+
+ constantTypemap = Swig_typemap_lookup("constcode", node, nodeName, 0);
+ if (constantTypemap != NULL) {
+ Printf(getFunctionWrapper->code, "SWIG_Scilab_SetOutputPosition(%d);\n", 1);
+ Replaceall(constantTypemap, "$value", constantValue);
+ Replaceall(constantTypemap, "$result", "1");
+ emit_action_code(node, getFunctionWrapper->code, constantTypemap);
+ Delete(constantTypemap);
+ }
+
+ /* Dump the wrapper function */
+ Append(getFunctionWrapper->code, "return SWIG_OK;\n");
+ Append(getFunctionWrapper->code, "}\n");
+ Wrapper_print(getFunctionWrapper, wrappersSection);
+
+ /* Add the function to Scilab */
+ addFunctionToScilab(getFunctionName, scilabGetSmallFunctionName, getFunctionName);
+
+ DelWrapper(getFunctionWrapper);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------
+ * enumvalueDeclaration()
+ * --------------------------------------------------------------------- */
+
+ virtual int enumvalueDeclaration(Node *node) {
+ static int iPreviousEnumValue = 0;
+
+ if (GetFlag(node, "feature:scilab:const")) {
+ // Compute the "absolute" value of enum if needed
+ // (most of time enum values are a linked list of relative values)
+ String *enumValue = Getattr(node, "enumvalue");
+ String *enumValueEx = Getattr(node, "enumvalueex");
+
+ // First enum value ?
+ String *firstenumitem = Getattr(node, "firstenumitem");
+ if (firstenumitem) {
+ if (enumValue) {
+ // Value is in 'enumvalue'
+ iPreviousEnumValue = atoi(Char(enumValue));
+ } else if (enumValueEx) {
+ // Or value is in 'enumValueEx'
+ iPreviousEnumValue = atoi(Char(enumValueEx));
+
+ enumValue = NewString("");
+ Printf(enumValue, "%d", iPreviousEnumValue);
+ Setattr(node, "enumvalue", enumValue);
+ }
+ } else if (!enumValue && enumValueEx) {
+ // Value is not specified, set it by incrementing last value
+ enumValue = NewString("");
+ Printf(enumValue, "%d", ++iPreviousEnumValue);
+ Setattr(node, "enumvalue", enumValue);
+ }
+ // Enums in Scilab are mapped to double
+ Setattr(node, "type", "double");
+ }
+
+ return Language::enumvalueDeclaration(node);
+ }
+
+ /* -----------------------------------------------------------------------
+ * addHelperFunctions()
+ * ----------------------------------------------------------------------- */
+
+ void addHelperFunctions() {
+ addFunctionToScilab("SWIG_this", "SWIG_this", "SWIG_this");
+ addFunctionToScilab("SWIG_ptr", "SWIG_ptr", "SWIG_ptr");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionToScilab()
+ * Declare a wrapped function in Scilab (builder, gateway, XML, ...)
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionToScilab(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName, const_String_or_char_ptr wrapperFunctionName) {
+ if (!generateBuilder)
+ addFunctionInGatewayHeader(scilabFunctionName, scilabSmallFunctionName, wrapperFunctionName);
+
+ if (generateBuilder) {
+ addFunctionInScriptTable(scilabFunctionName, scilabSmallFunctionName, wrapperFunctionName, builderCode5, builderCode6);
+ }
+
+ if (createLoader) {
+ addFunctionInLoader(scilabFunctionName, scilabSmallFunctionName);
+ }
+
+ if (gatewayXMLFile) {
+ Printf(gatewayXML, "<PRIMITIVE gatewayId=\"%s\" primitiveId=\"%d\" primitiveName=\"%s\"/>\n", gatewayID, primitiveID++, scilabSmallFunctionName);
+ }
+
+ if (gatewayXMLFileV6) {
+ Printf(gatewayXMLV6, "<gateway name=\"%s\" function=\"%s\" type=\"0\"/>\n", scilabFunctionName, scilabFunctionName);
+ }
+ }
+
+
+ /* -----------------------------------------------------------------------
+ * createBuilderCode()
+ * ----------------------------------------------------------------------- */
+
+ void createBuilderFile(String *outputFilename) {
+ String *builderFilename = NewStringf("builder.sce");
+ builderFile = NewFile(builderFilename, "w", SWIG_output_files());
+ if (!builderFile) {
+ FileErrorDisplay(builderFilename);
+ Exit(EXIT_FAILURE);
+ }
+ emitBanner(builderFile);
+
+ builderFunctionCount = 0;
+ builderCode = NewString("");
+ builderCode5 = NewString("");
+ builderCode6 = NewString("");
+ Printf(builderCode, "mode(-1);\n");
+ Printf(builderCode, "lines(0);\n"); /* Useful for automatic tests */
+
+ // Scilab needs to be in the build directory
+ Printf(builderCode, "originaldir = pwd();\n");
+ Printf(builderCode, "builddir = get_absolute_file_path('builder.sce');\n");
+ Printf(builderCode, "cd(builddir);\n");
+
+ Printf(builderCode, "ilib_verbose(%s);\n", verboseBuildLevel);
+
+ Printf(builderCode, "libs = [];\n");
+
+ // Flags from command line arguments
+ Printf(builderCode, "cflags = \"\";\n");
+ for (int i = 0; i < Len(cflags); i++) {
+ String *cflag = Getitem(cflags, i);
+ Printf(builderCode, "cflags = cflags + \" %s\";\n", cflag);
+ }
+
+ if (Len(ldflags) > 0) {
+ for (int i = 0; i < Len(ldflags); i++) {
+ String *ldflag = Getitem(ldflags, i);
+ if (i == 0) {
+ Printf(builderCode, "ldflags = \"%s\";\n", ldflag);
+ } else {
+ Printf(builderCode, "ldflags = ldflags + \" %s\";\n", ldflag);
+ }
+ }
+ } else {
+ Printf(builderCode, "ldflags = \"\";\n");
+ }
+
+ // External script to set flags
+ if (buildFlagsScript) {
+ Printf(builderCode, "exec(\"%s\");\n", buildFlagsScript);
+ Printf(builderCode, "cflags = cflags + getCompilationFlags();\n");
+ Printf(builderCode, "ldflags = ldflags + getLinkFlags();\n");
+ }
+ // Additional sources
+ Insert(sourceFileList, 0, outputFilename);
+ for (int i = 0; i < Len(sourceFileList); i++) {
+ String *sourceFile = Getitem(sourceFileList, i);
+ if (i == 0) {
+ Printf(builderCode, "files = \"%s\";\n", sourceFile);
+ } else {
+ Printf(builderCode, "files($ + 1) = \"%s\";\n", sourceFile);
+ }
+ }
+
+ Printf(builderCode5, "table = [ ..\n");
+ Printf(builderCode6, "table = [ ..\n");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionInBuilderCode()
+ * Add a function wrapper in the function table of generated builder script
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionInScriptTable(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName, const_String_or_char_ptr wrapperFunctionName, String *scriptCode5, String *scriptCode6) {
+ if (++builderFunctionCount % 10 == 0) {
+ Printf(scriptCode5, "];\ntable = [table; ..\n");
+ Printf(scriptCode6, "];\ntable = [table; ..\n");
+ }
+ Printf(scriptCode5, "\"%s\",\"%s\"; ..\n", scilabSmallFunctionName, wrapperFunctionName);
+ Printf(scriptCode6, "\"%s\",\"%s\"; ..\n", scilabFunctionName, wrapperFunctionName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveBuilderFile()
+ * ----------------------------------------------------------------------- */
+
+ void saveBuilderFile(String *gatewayName) {
+ Printf(builderCode5, "];\n");
+ Printf(builderCode6, "];\n");
+
+ if (Equal(builderCode5, builderCode6)) {
+ Append(builderCode, builderCode6);
+ } else {
+ Printf(builderCode, "ver = getversion('scilab');\n");
+ Printf(builderCode, "if ver(1) < 6 then\n");
+ Printf(builderCode, " // version is less or equal to 5.5.2\n");
+ Printf(builderCode, " \n");
+ Append(builderCode, builderCode5);
+ Printf(builderCode, " \n");
+ Printf(builderCode, "else\n");
+ Printf(builderCode, " // version is 6.0.0 or more\n");
+ Printf(builderCode, " \n");
+ Append(builderCode, builderCode6);
+ Printf(builderCode, " \n");
+ Printf(builderCode, "end\n");
+ }
+
+ Printf(builderCode, "ierr = 0;\n");
+ Printf(builderCode, "if ~isempty(table) then\n");
+ Printf(builderCode, " ierr = execstr(\"ilib_build(''%s'', table, files, libs, [], ldflags, cflags);\", 'errcatch');\n", gatewayName);
+ Printf(builderCode, " if ierr <> 0 then\n");
+ Printf(builderCode, " err_msg = lasterror();\n");
+ Printf(builderCode, " end\n");
+ Printf(builderCode, "end\n");
+ Printf(builderCode, "cd(originaldir);\n");
+ Printf(builderCode, "if ierr <> 0 then\n");
+ Printf(builderCode, " error(ierr, err_msg);\n");
+ Printf(builderCode, "end\n");
+ Printv(builderFile, builderCode, NIL);
+
+ Delete(builderCode);
+ Delete(builderFile);
+ }
+
+ /* -----------------------------------------------------------------------
+ * createGatewayXMLFileV6()
+ * This XML file is used by Scilab 6 in the context of internal modules or
+ * to get the function list.
+ * ----------------------------------------------------------------------- */
+
+ void createGatewayXMLFileV6(String *gatewayName) {
+ String *gatewayXMLFilename = NewStringf("%s_gateway.xml", gatewayName);
+ gatewayXMLFileV6 = NewFile(gatewayXMLFilename, "w", SWIG_output_files());
+ if (!gatewayXMLFileV6) {
+ FileErrorDisplay(gatewayXMLFilename);
+ Exit(EXIT_FAILURE);
+ }
+ // Add a slightly modified SWIG banner to the gateway XML ("--modify" is illegal in XML)
+ gatewayXMLV6 = NewString("");
+ Printf(gatewayXMLV6, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+ Printf(gatewayXMLV6, "<!DOCTYPE module SYSTEM \"../../functions/xml/gateway.dtd\">\n");
+ Printf(gatewayXMLV6, "<!--\n");
+ Swig_banner_target_lang(gatewayXMLV6, "");
+ Printf(gatewayXMLV6, "-->\n");
+ Printf(gatewayXMLV6, "<module name=\"%s\">\n", gatewayName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveGatewayXMLFileV6()
+ * ----------------------------------------------------------------------- */
+
+ void saveGatewayXMLFileV6() {
+ Printf(gatewayXMLV6, "</module>\n");
+ Printv(gatewayXMLFileV6, gatewayXMLV6, NIL);
+ Delete(gatewayXMLFileV6);
+ }
+
+ /* -----------------------------------------------------------------------
+ * createGatewayXMLFile()
+ * This XML file is used by Scilab in the context of internal modules
+ * ----------------------------------------------------------------------- */
+
+ void createGatewayXMLFile(String *gatewayName) {
+ String *gatewayXMLFilename = NewStringf("%s_gateway.xml", gatewayName);
+ gatewayXMLFile = NewFile(gatewayXMLFilename, "w", SWIG_output_files());
+ if (!gatewayXMLFile) {
+ FileErrorDisplay(gatewayXMLFilename);
+ Exit(EXIT_FAILURE);
+ }
+ // Add a slightly modified SWIG banner to the gateway XML ("--modify" is illegal in XML)
+ gatewayXML = NewString("");
+ Printf(gatewayXML, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+ Printf(gatewayXML, "<!--\n");
+ Swig_banner_target_lang(gatewayXML, "");
+ Printf(gatewayXML, "-->\n");
+ Printf(gatewayXML, "<GATEWAY name=\"%s\">\n", gatewayName);
+
+ primitiveID = 1;
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveGatewayXMLFile()
+ * ----------------------------------------------------------------------- */
+
+ void saveGatewayXMLFile() {
+ Printf(gatewayXML, "</GATEWAY>\n");
+ Printv(gatewayXMLFile, gatewayXML, NIL);
+ Delete(gatewayXMLFile);
+ }
+
+ /* -----------------------------------------------------------------------
+ * startGatewayHeader()
+ * Start the gateway header
+ * ----------------------------------------------------------------------- */
+ void startGatewayHeader(String *gatewayLibraryName) {
+ gatewayHeader = NewString("");
+ Printf(gatewayHeader, "\n");
+
+ gatewayHeaderV6 = NewString("");
+ Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV6, "extern \"C\" {\n");
+ Printf(gatewayHeaderV6, "#endif\n");
+ Printf(gatewayHeaderV6, "#include \"c_gateway_prototype.h\"\n");
+ Printf(gatewayHeaderV6, "#include \"addfunction.h\"\n");
+ Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV6, "}\n");
+ Printf(gatewayHeaderV6, "#endif\n");
+ Printf(gatewayHeaderV6, "\n");
+ Printf(gatewayHeaderV6, "#define MODULE_NAME L\"%s\"\n", gatewayLibraryName);
+ Printf(gatewayHeaderV6, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV6, "extern \"C\"\n");
+ Printf(gatewayHeaderV6, "#endif\n");
+ Printf(gatewayHeaderV6, "SWIGEXPORT int %s(wchar_t *pwstFuncName) {\n", gatewayLibraryName);
+ Printf(gatewayHeaderV6, "\n");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionInGatewayHeader()
+ * Add a function in the gateway header
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionInGatewayHeader(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName, const_String_or_char_ptr wrapperFunctionName) {
+ if (gatewayHeaderV5 == NULL) {
+ gatewayHeaderV5 = NewString("");
+ Printf(gatewayHeaderV5, "static GenericTable Tab[] = {\n");
+ } else
+ Printf(gatewayHeaderV5, ",\n");
+ Printf(gatewayHeaderV5, " {(Myinterfun)sci_gateway, (GT)%s, (char *)\"%s\"}", wrapperFunctionName, scilabSmallFunctionName);
+
+ Printf(gatewayHeaderV6, "if (wcscmp(pwstFuncName, L\"%s\") == 0) { addCStackFunction((wchar_t *)L\"%s\", &%s, (wchar_t *)MODULE_NAME); }\n", scilabFunctionName, scilabFunctionName, wrapperFunctionName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * terminateGatewayHeader()
+ * Terminates the gateway header
+ * ----------------------------------------------------------------------- */
+
+ void terminateGatewayHeader(String *gatewayLibraryName) {
+ Printf(gatewayHeaderV5, "};\n");
+ Printf(gatewayHeaderV5, "\n");
+ Printf(gatewayHeaderV5, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV5, "extern \"C\" {\n");
+ Printf(gatewayHeaderV5, "#endif\n");
+ Printf(gatewayHeaderV5, "SWIGEXPORT int C2F(%s)() {\n", gatewayLibraryName);
+ Printf(gatewayHeaderV5, " Rhs = Max(0, Rhs);\n");
+ Printf(gatewayHeaderV5, " if (*(Tab[Fin-1].f) != NULL) {\n");
+ Printf(gatewayHeaderV5, " if(pvApiCtx == NULL) {\n");
+ Printf(gatewayHeaderV5, " pvApiCtx = (StrCtx *)MALLOC(sizeof(StrCtx));\n");
+ Printf(gatewayHeaderV5, " }\n");
+ Printf(gatewayHeaderV5, " pvApiCtx->pstName = (char *)Tab[Fin-1].name;\n");
+ Printf(gatewayHeaderV5, " (*(Tab[Fin-1].f))(Tab[Fin-1].name,(GatefuncH)Tab[Fin-1].F);\n");
+ Printf(gatewayHeaderV5, " }\n");
+ Printf(gatewayHeaderV5, " return 0;\n");
+ Printf(gatewayHeaderV5, "}\n");
+ Printf(gatewayHeaderV5, "\n");
+ Printf(gatewayHeaderV5, "#ifdef __cplusplus\n");
+ Printf(gatewayHeaderV5, "}\n");
+ Printf(gatewayHeaderV5, "#endif\n");
+
+ Printf(gatewayHeaderV6, "return 1;\n");
+ Printf(gatewayHeaderV6, "};\n");
+
+ Printf(gatewayHeader, "#if SCI_VERSION_MAJOR < 6\n");
+ Printv(gatewayHeader, gatewayHeaderV5, NIL);
+ Printf(gatewayHeader, "#else\n");
+ Printv(gatewayHeader, gatewayHeaderV6, NIL);
+ Printf(gatewayHeader, "#endif\n");
+ }
+
+
+ /* -----------------------------------------------------------------------
+ * createLoaderScriptFile()
+ * Creates the loader script file (loader.sce)
+ * ----------------------------------------------------------------------- */
+
+ void createLoaderFile(String *gatewayLibraryName) {
+ String *loaderFilename = NewString("loader.sce");
+ loaderFile = NewFile(loaderFilename, "w", SWIG_output_files());
+ if (!loaderFile) {
+ FileErrorDisplay(loaderFilename);
+ Exit(EXIT_FAILURE);
+ }
+
+ emitBanner(loaderFile);
+
+ loaderFunctionCount = 0;
+ loaderScript = NewString("function loader_function()\n");
+ Printf(loaderScript, " p = get_absolute_file_path('loader.sce');\n", gatewayLibraryName);
+ Printf(loaderScript, " [bOK, ilib] = c_link('%s');\n", gatewayLibraryName);
+ Printf(loaderScript, " if bOK then\n");
+ Printf(loaderScript, " ulink(ilib);\n");
+ Printf(loaderScript, " end\n");
+ loaderScript5 = NewString(" list_functions = [ ..\n");
+ loaderScript6 = NewString(" list_functions = [ ..\n");
+ }
+
+ /* -----------------------------------------------------------------------
+ * addFunctionInLoaderScript()
+ * Add a function in the loader script table
+ * ----------------------------------------------------------------------- */
+
+ void addFunctionInLoader(const_String_or_char_ptr scilabFunctionName, const_String_or_char_ptr scilabSmallFunctionName) {
+ if (++loaderFunctionCount % 10 == 0) {
+ Printf(loaderScript5, " ];\n list_functions = [list_functions; ..\n");
+ Printf(loaderScript6, " ];\n list_functions = [list_functions; ..\n");
+ }
+ Printf(loaderScript5, " '%s'; ..\n", scilabSmallFunctionName);
+ Printf(loaderScript6, " '%s'; ..\n", scilabFunctionName);
+ }
+
+ /* -----------------------------------------------------------------------
+ * saveLoaderScriptFile()
+ * Terminates and saves the loader script
+ * ----------------------------------------------------------------------- */
+
+ void saveLoaderFile(String *gatewayLibraryName) {
+ Printf(loaderScript5, " ];\n");
+ Printf(loaderScript6, " ];\n");
+
+ if (Equal(loaderScript5, loaderScript6)) {
+ Append(loaderScript, loaderScript6);
+ } else {
+ Printf(loaderScript, " ver = getversion('scilab');\n");
+ Printf(loaderScript, " if ver(1) < 6 then\n");
+ Printf(loaderScript, " // version is less or equal to 5.5.2\n");
+ Printf(loaderScript, " \n");
+ Append(loaderScript, loaderScript5);
+ Delete(loaderScript5);
+ Printf(loaderScript, " \n");
+ Printf(loaderScript, " else\n");
+ Printf(loaderScript, " // version is 6.0.0 or more\n");
+ Printf(loaderScript, " \n");
+ Append(loaderScript, loaderScript6);
+ Delete(loaderScript6);
+ Printf(loaderScript, " \n");
+ Printf(loaderScript, " end\n");
+ }
+
+ Printf(loaderScript, " addinter(p + '%s' + getdynlibext(), '%s', list_functions);\n", gatewayLibraryName, gatewayLibraryName);
+ Printf(loaderScript, "endfunction\n");
+ Printf(loaderScript, "loader_function();\n");
+ Printf(loaderScript, "clear loader_function;\n");
+ Printv(loaderFile, loaderScript, NIL);
+
+ Delete(loaderScript);
+ Delete(loaderFile);
+ }
+
+ /* -----------------------------------------------------------------------
+ * createSmallIdentifierName()
+ * Create a Scilab small identifier to be used by Scilab 5
+ * ----------------------------------------------------------------------- */
+
+ String* createSmallIdentifierName(String* name, int outputLen = SCILAB_IDENTIFIER_NAME_CHAR_MAX) {
+ char* s = Char(name);
+ int nameLen = Len(s);
+
+ // truncate and preserve common suffix
+ if (outputLen > 4 && nameLen > outputLen) {
+ String* smallName = NewStringWithSize(name, outputLen);
+ char* smallNameStr = (char*) Data(smallName);
+
+ if (s[nameLen-4] == '_' && s[nameLen - 3] == 'g' && s[nameLen - 2] == 'e' && s[nameLen - 1] == 't') {
+ // get
+ memcpy(&smallNameStr[outputLen - 4], &s[nameLen - 4], 4);
+ } else if (s[nameLen-4] == '_' && s[nameLen - 3] == 's' && s[nameLen - 2] == 'e' && s[nameLen - 1] == 't') {
+ // set
+ memcpy(&smallNameStr[outputLen - 4], &s[nameLen - 4], 4);
+ }
+
+ return smallName;
+ }
+
+ return name;
+ }
+
+};
+
+extern "C" Language *swig_scilab(void) {
+ return new SCILAB();
+}
diff --git a/contrib/tools/swig/Source/Modules/swigmain.cxx b/contrib/tools/swig/Source/Modules/swigmain.cxx
new file mode 100644
index 00000000000..0df02cd005f
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/swigmain.cxx
@@ -0,0 +1,278 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigmain.cxx
+ *
+ * Simplified Wrapper and Interface Generator (SWIG)
+ *
+ * This file is the main entry point to SWIG. It collects the command
+ * line options, registers built-in language modules, and instantiates
+ * a module for code generation. If adding new language modules
+ * to SWIG, you would modify this file.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include <ctype.h>
+
+/* Module factories. These functions are used to instantiate
+ the built-in language modules. If adding a new language
+ module to SWIG, place a similar function here. Make sure
+ the function has "C" linkage. This is required so that modules
+ can be dynamically loaded in future versions. */
+
+extern "C" {
+ Language *swig_c(void);
+ Language *swig_csharp(void);
+ Language *swig_d(void);
+ Language *swig_go(void);
+ Language *swig_guile(void);
+ Language *swig_java(void);
+ Language *swig_javascript(void);
+ Language *swig_lua(void);
+ Language *swig_mzscheme(void);
+ Language *swig_ocaml(void);
+ Language *swig_octave(void);
+ Language *swig_perl5(void);
+ Language *swig_php(void);
+ Language *swig_python(void);
+ Language *swig_r(void);
+ Language *swig_ruby(void);
+ Language *swig_scilab(void);
+ Language *swig_tcl(void);
+ Language *swig_xml(void);
+}
+
+/* Association of command line options to language modules.
+ Place an entry for new language modules here, keeping the
+ list sorted alphabetically. */
+
+static TargetLanguageModule modules[] = {
+ {"-allegrocl", NULL, "ALLEGROCL", Disabled},
+ {"-c", swig_c, "C", Experimental},
+ {"-chicken", NULL, "CHICKEN", Disabled},
+ {"-clisp", NULL, "CLISP", Disabled},
+ {"-csharp", swig_csharp, "C#", Supported},
+ {"-d", swig_d, "D", Supported},
+ {"-go", swig_go, "Go", Supported},
+ {"-guile", swig_guile, "Guile", Supported},
+ {"-java", swig_java, "Java", Supported},
+ {"-javascript", swig_javascript, "Javascript", Supported},
+ {"-lua", swig_lua, "Lua", Supported},
+ {"-modula3", NULL, "Modula 3", Disabled},
+ {"-mzscheme", swig_mzscheme, "MzScheme/Racket", Deprecated},
+ {"-ocaml", swig_ocaml, "OCaml", Experimental},
+ {"-octave", swig_octave, "Octave", Supported},
+ {"-perl", swig_perl5, NULL, Supported},
+ {"-perl5", swig_perl5, "Perl 5", Supported},
+ {"-php", swig_php, NULL, Supported},
+ {"-php5", NULL, "PHP 5", Disabled},
+ {"-php7", swig_php, "PHP 8 or later", Supported},
+ {"-pike", NULL, "Pike", Disabled},
+ {"-python", swig_python, "Python", Supported},
+ {"-r", swig_r, "R (aka GNU S)", Supported},
+ {"-ruby", swig_ruby, "Ruby", Supported},
+ {"-scilab", swig_scilab, "Scilab", Supported},
+ {"-sexp", NULL, "Lisp S-Expressions", Disabled},
+ {"-tcl", swig_tcl, NULL, Supported},
+ {"-tcl8", swig_tcl, "Tcl 8", Supported},
+ {"-uffi", NULL, "Common Lisp / UFFI", Disabled},
+ {"-xml", swig_xml, "XML", Supported},
+ {NULL, NULL, NULL, Disabled}
+};
+
+//-----------------------------------------------------------------
+// main()
+//
+// Main program. Initializes the files and starts the parser.
+//-----------------------------------------------------------------
+
+static void SWIG_merge_envopt(const char *env, int oargc, char *oargv[], int *nargc, char ***nargv) {
+ if (!env) {
+ *nargc = oargc;
+ *nargv = (char **)Malloc(sizeof(char *) * (oargc + 1));
+ memcpy(*nargv, oargv, sizeof(char *) * (oargc + 1));
+ return;
+ }
+
+ int argc = 1;
+ int arge = oargc + 1024;
+ char **argv = (char **) Malloc(sizeof(char *) * (arge + 1));
+ char *buffer = (char *) Malloc(2048);
+ char *b = buffer;
+ char *be = b + 1023;
+ const char *c = env;
+ while ((b != be) && *c && (argc < arge)) {
+ while (isspace(*c) && *c)
+ ++c;
+ if (*c) {
+ argv[argc] = b;
+ ++argc;
+ }
+ while ((b != be) && *c && !isspace(*c)) {
+ *(b++) = *(c++);
+ }
+ *b++ = 0;
+ }
+
+ argv[0] = oargv[0];
+ for (int i = 1; (i < oargc) && (argc < arge); ++i, ++argc) {
+ argv[argc] = oargv[i];
+ }
+ argv[argc] = NULL;
+
+ *nargc = argc;
+ *nargv = argv;
+}
+
+static void insert_option(int *argc, char ***argv, int index, char const *start, char const *end) {
+ int new_argc = *argc;
+ char **new_argv = *argv;
+ size_t option_len = end - start;
+
+ // Preserve the NULL pointer at argv[argc]
+ new_argv = (char **)Realloc(new_argv, (new_argc + 2) * sizeof(char *));
+ memmove(&new_argv[index + 1], &new_argv[index], sizeof(char *) * (new_argc + 1 - index));
+ new_argc++;
+
+ new_argv[index] = (char *)Malloc(option_len + 1);
+ memcpy(new_argv[index], start, option_len);
+ new_argv[index][option_len] = '\0';
+
+ *argc = new_argc;
+ *argv = new_argv;
+}
+
+static void merge_options_files(int *argc, char ***argv) {
+ static const int BUFFER_SIZE = 4096;
+ char buffer[BUFFER_SIZE];
+ int i;
+ int insert;
+ char **new_argv = *argv;
+ int new_argc = *argc;
+ FILE *f;
+
+ i = 1;
+ while (i < new_argc) {
+ if (new_argv[i] && new_argv[i][0] == '@' && (f = fopen(&new_argv[i][1], "r"))) {
+ int ci;
+ char *b;
+ char *be = &buffer[BUFFER_SIZE];
+ int quote = 0;
+ bool escape = false;
+
+ new_argc--;
+ memmove(&new_argv[i], &new_argv[i + 1], sizeof(char *) * (new_argc - i));
+ insert = i;
+ b = buffer;
+
+ while ((ci = fgetc(f)) != EOF) {
+ const char c = static_cast<char>(ci);
+ if (escape) {
+ if (b != be) {
+ *b = c;
+ ++b;
+ }
+ escape = false;
+ } else if (c == '\\') {
+ escape = true;
+ } else if (!quote && (c == '\'' || c == '"')) {
+ quote = c;
+ } else if (quote && c == quote) {
+ quote = 0;
+ } else if (isspace(c) && !quote) {
+ if (b != buffer) {
+ insert_option(&new_argc, &new_argv, insert, buffer, b);
+ insert++;
+
+ b = buffer;
+ }
+ } else if (b != be) {
+ *b = c;
+ ++b;
+ }
+ }
+ if (b != buffer)
+ insert_option(&new_argc, &new_argv, insert, buffer, b);
+ fclose(f);
+ } else {
+ ++i;
+ }
+ }
+
+ *argv = new_argv;
+ *argc = new_argc;
+}
+
+int main(int margc, char **margv) {
+ int i;
+ const TargetLanguageModule *language_module = 0;
+
+ int argc;
+ char **argv;
+
+ /* Check for SWIG_FEATURES environment variable */
+
+ SWIG_merge_envopt(getenv("SWIG_FEATURES"), margc, margv, &argc, &argv);
+ merge_options_files(&argc, &argv);
+
+ Swig_init_args(argc, argv);
+
+ /* Get options */
+ for (i = 1; i < argc; i++) {
+ if (argv[i]) {
+ bool is_target_language_module = false;
+ for (int j = 0; modules[j].name; j++) {
+ if (strcmp(modules[j].name, argv[i]) == 0) {
+ if (!language_module) {
+ language_module = &modules[j];
+ is_target_language_module = true;
+ } else {
+ Printf(stderr, "Only one target language can be supported at a time (both %s and %s were specified).\n", language_module->name, argv[i]);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+ if (is_target_language_module) {
+ Swig_mark_arg(i);
+ if (language_module->status == Disabled) {
+ if (language_module->help)
+ Printf(stderr, "Target language option %s (%s) is no longer supported.\n", language_module->name, language_module->help);
+ else
+ Printf(stderr, "Target language option %s is no longer supported.\n", language_module->name);
+ Exit(EXIT_FAILURE);
+ }
+ } else if ((strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
+ if (strcmp(argv[i], "--help") == 0)
+ strcpy(argv[i], "-help");
+ Printf(stdout, "Supported Target Language Options\n");
+ for (int j = 0; modules[j].name; j++) {
+ if (modules[j].help && modules[j].status == Supported) {
+ Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
+ }
+ }
+ Printf(stdout, "\nExperimental Target Language Options\n");
+ for (int j = 0; modules[j].name; j++) {
+ if (modules[j].help && modules[j].status == Experimental) {
+ Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
+ }
+ }
+ Printf(stdout, "\nDeprecated Target Language Options\n");
+ for (int j = 0; modules[j].name; j++) {
+ if (modules[j].help && modules[j].status == Deprecated) {
+ Printf(stdout, " %-15s - Generate %s wrappers\n", modules[j].name, modules[j].help);
+ }
+ }
+ // Swig_mark_arg not called as the general -help options also need to be displayed later on
+ }
+ }
+ }
+
+ int res = SWIG_main(argc, argv, language_module);
+
+ return res;
+}
diff --git a/contrib/tools/swig/Source/Modules/swigmod.h b/contrib/tools/swig/Source/Modules/swigmod.h
new file mode 100644
index 00000000000..ea3503e02f6
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/swigmod.h
@@ -0,0 +1,461 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigmod.h
+ *
+ * Main header file for SWIG modules.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_SWIGMOD_H
+#define SWIG_SWIGMOD_H
+
+#include "swig.h"
+#include "preprocessor.h"
+#include "swigwarn.h"
+
+#define NOT_VIRTUAL 0
+#define PLAIN_VIRTUAL 1
+#define PURE_VIRTUAL 2
+
+extern String *input_file;
+extern int line_number;
+extern int start_line;
+extern int CPlusPlus; // C++ mode
+extern int Extend; // Extend mode
+extern int Verbose;
+extern int IsVirtual;
+extern int ImportMode;
+extern int NoExcept; // -no_except option
+extern int Abstract; // abstract base class
+extern int SmartPointer; // smart pointer methods being emitted
+
+/* Overload "argc" and "argv" */
+extern String *argv_template_string;
+extern String *argc_template_string;
+
+/* Miscellaneous stuff */
+
+#define tab0 ""
+#define tab2 " "
+#define tab4 " "
+#define tab8 " "
+
+class Dispatcher {
+public:
+
+ Dispatcher ():cplus_mode(PUBLIC) {
+ }
+ virtual ~ Dispatcher () {
+ }
+
+ virtual int emit_one(Node *n);
+ virtual int emit_children(Node *n);
+ virtual int defaultHandler(Node *n);
+
+ /* Top of the parse tree */
+ virtual int top(Node *n) = 0;
+
+ /* SWIG directives */
+
+ virtual int applyDirective(Node *n);
+ virtual int clearDirective(Node *n);
+ virtual int constantDirective(Node *n);
+ virtual int extendDirective(Node *n);
+ virtual int fragmentDirective(Node *n);
+ virtual int importDirective(Node *n);
+ virtual int includeDirective(Node *n);
+ virtual int insertDirective(Node *n);
+ virtual int moduleDirective(Node *n);
+ virtual int nativeDirective(Node *n);
+ virtual int pragmaDirective(Node *n);
+ virtual int typemapDirective(Node *n);
+ virtual int typemapitemDirective(Node *n);
+ virtual int typemapcopyDirective(Node *n);
+ virtual int typesDirective(Node *n);
+
+ /* C/C++ parsing */
+
+ virtual int cDeclaration(Node *n);
+ virtual int externDeclaration(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ virtual int enumforwardDeclaration(Node *n);
+ virtual int classDeclaration(Node *n);
+ virtual int classforwardDeclaration(Node *n);
+ virtual int constructorDeclaration(Node *n);
+ virtual int destructorDeclaration(Node *n);
+ virtual int accessDeclaration(Node *n);
+ virtual int usingDeclaration(Node *n);
+ virtual int namespaceDeclaration(Node *n);
+ virtual int templateDeclaration(Node *n);
+ virtual int lambdaDeclaration(Node *n);
+
+ enum AccessMode { PUBLIC, PRIVATE, PROTECTED };
+
+protected:
+ AccessMode cplus_mode;
+ AccessMode accessModeFromString(String *access);
+ int abstractClassTest(Node *n); /* Is class really abstract? */
+};
+
+/* ----------------------------------------------------------------------------
+ * class language:
+ *
+ * This class defines the functions that need to be supported by the
+ * scripting language being used. The translator calls these virtual
+ * functions to output different types of code for different languages.
+ * ------------------------------------------------------------------------- */
+
+class Language:public Dispatcher {
+public:
+ Language();
+ virtual ~Language();
+ virtual int emit_one(Node *n);
+
+ String *directorClassName(Node *n);
+
+ /* Parse command line options */
+
+ virtual void main(int argc, char *argv[]);
+
+ /* Top of the parse tree */
+
+ virtual int top(Node *n);
+
+ /* SWIG directives */
+
+
+ virtual int applyDirective(Node *n);
+ virtual int clearDirective(Node *n);
+ virtual int constantDirective(Node *n);
+ virtual int extendDirective(Node *n);
+ virtual int fragmentDirective(Node *n);
+ virtual int importDirective(Node *n);
+ virtual int includeDirective(Node *n);
+ virtual int insertDirective(Node *n);
+ virtual int moduleDirective(Node *n);
+ virtual int nativeDirective(Node *n);
+ virtual int pragmaDirective(Node *n);
+ virtual int typemapDirective(Node *n);
+ virtual int typemapcopyDirective(Node *n);
+ virtual int typesDirective(Node *n);
+
+ /* C/C++ parsing */
+
+ virtual int cDeclaration(Node *n);
+ virtual int externDeclaration(Node *n);
+ virtual int enumDeclaration(Node *n);
+ virtual int enumvalueDeclaration(Node *n);
+ virtual int enumforwardDeclaration(Node *n);
+ virtual int classDeclaration(Node *n);
+ virtual int classforwardDeclaration(Node *n);
+ virtual int constructorDeclaration(Node *n);
+ virtual int destructorDeclaration(Node *n);
+ virtual int accessDeclaration(Node *n);
+ virtual int namespaceDeclaration(Node *n);
+ virtual int usingDeclaration(Node *n);
+
+ /* Function handlers */
+
+ virtual int functionHandler(Node *n);
+ virtual int globalfunctionHandler(Node *n);
+ virtual int memberfunctionHandler(Node *n);
+ virtual int staticmemberfunctionHandler(Node *n);
+ virtual int callbackfunctionHandler(Node *n);
+
+ /* Variable handlers */
+
+ virtual int variableHandler(Node *n);
+ virtual int globalvariableHandler(Node *n);
+ virtual int membervariableHandler(Node *n);
+ virtual int staticmembervariableHandler(Node *n);
+
+ /* C++ handlers */
+
+ virtual int memberconstantHandler(Node *n);
+ virtual int constructorHandler(Node *n);
+ virtual int copyconstructorHandler(Node *n);
+ virtual int destructorHandler(Node *n);
+ virtual int classHandler(Node *n);
+
+ /* Miscellaneous */
+
+ virtual int typedefHandler(Node *n);
+
+ /* Low-level code generation */
+
+ virtual int constantWrapper(Node *n);
+ virtual int variableWrapper(Node *n);
+ virtual int functionWrapper(Node *n);
+ virtual int nativeWrapper(Node *n);
+
+ /* C++ director class generation */
+ virtual int classDirector(Node *n);
+ virtual int classDirectorInit(Node *n);
+ virtual int classDirectorEnd(Node *n);
+ virtual int unrollVirtualMethods(Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase = 0);
+ virtual int classDirectorConstructor(Node *n);
+ virtual int classDirectorDefaultConstructor(Node *n);
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super);
+ virtual int classDirectorConstructors(Node *n);
+ virtual int classDirectorDestructor(Node *n);
+ virtual int classDirectorMethods(Node *n);
+ virtual int classDirectorDisown(Node *n);
+
+ /* Miscellaneous */
+ virtual int validIdentifier(String *s); /* valid identifier? */
+ virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */
+ virtual int addInterfaceSymbol(const String *interface_name, Node *n, const_String_or_char_ptr scope = "");
+ virtual void dumpSymbols();
+ virtual Node *symbolLookup(const String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */
+ virtual Hash* symbolAddScope(const_String_or_char_ptr scope/*, Node *n = 0*/);
+ virtual Hash* symbolScopeLookup(const_String_or_char_ptr scope);
+ virtual Hash* symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope);
+ static Node *classLookup(const SwigType *s); /* Class lookup */
+ static Node *enumLookup(SwigType *s); /* Enum lookup */
+ virtual int is_immutable(Node *n); /* Is variable assignable? */
+ virtual String *runtimeCode(); /* returns the language specific runtime code */
+ virtual String *defaultExternalRuntimeFilename(); /* the default filename for the external runtime */
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm); /* Language specific special variable substitutions for $typemap() */
+
+ /* Runtime is C++ based, so extern "C" header section */
+ void enable_cplus_runtime_mode();
+
+ /* Returns the cplus_runtime mode */
+ int cplus_runtime_mode();
+
+ /* Flag for language to support directors */
+ void directorLanguage(int val = 1);
+
+ /* Allow director related code generation */
+ void allow_directors(int val = 1);
+
+ /* Allow director protected members related code generation */
+ void allow_dirprot(int val = 1);
+
+ /* Allow all protected members code generation (for directors) */
+ void allow_allprotected(int val = 0);
+
+ /* Returns the dirprot mode */
+ int dirprot_mode() const;
+
+ /* Check if the non public constructor is needed (for directors) */
+ int need_nonpublic_ctor(Node *n);
+
+ /* Check if the non public member is needed (for directors) */
+ int need_nonpublic_member(Node *n);
+
+ /* Set none comparison string */
+ void setSubclassInstanceCheck(String *s);
+
+ /* Set overload variable templates argc and argv */
+ void setOverloadResolutionTemplates(String *argc, String *argv);
+
+ /* Language instance is a singleton - get instance */
+ static Language* instance();
+
+protected:
+ /* Allow multiple-input typemaps */
+ void allow_multiple_input(int val = 1);
+
+ /* Allow overloaded functions */
+ void allow_overloading(int val = 1);
+
+ /* Wrapping class query */
+ int is_wrapping_class() const;
+
+ /* Return the node for the current class */
+ Node *getCurrentClass() const;
+
+ /* Return C++ mode */
+ int getCPlusMode() const;
+
+ /* Return the namespace for the class/enum - the nspace feature */
+ String *getNSpace() const;
+
+ /* Return the real name of the current class */
+ String *getClassName() const;
+
+ /* Return the classes hash */
+ Hash *getClassHash() const;
+
+ /* Return the current class prefix */
+ String *getClassPrefix() const;
+
+ /* Return the current enum class prefix */
+ String *getEnumClassPrefix() const;
+
+ /* Fully qualified type name to use */
+ String *getClassType() const;
+
+ /* Return true if the current method is part of a smart-pointer */
+ int is_smart_pointer() const;
+
+ /* Return the name to use for the given parameter. */
+ virtual String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter = false) const;
+
+ /* Some language modules require additional wrappers for virtual methods not declared in sub-classes */
+ virtual bool extraDirectorProtectedCPPMethodsRequired() const;
+
+public:
+ enum NestedClassSupport {
+ NCS_None, // Target language does not have an equivalent to nested classes
+ NCS_Full, // Target language does have an equivalent to nested classes and is fully implemented
+ NCS_Unknown // Target language may or may not have an equivalent to nested classes. If it does, it has not been implemented yet.
+ };
+ /* Does target language support nested classes? Default is NCS_Unknown.
+ If NCS_Unknown is returned, then the nested classes will be ignored unless
+ %feature "flatnested" is applied to them, in which case they will appear in global space.
+ If the target language does not support the notion of class
+ nesting, the language module should return NCS_None from this function, and
+ the nested classes will be moved to the global scope (like implicit global %feature "flatnested").
+ */
+ virtual NestedClassSupport nestedClassesSupport() const;
+
+ /* Returns true if the target language supports key word arguments (kwargs) */
+ virtual bool kwargsSupport() 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;
+
+ /* Identify if a wrapped global or member variable n should use the naturalvar feature */
+ int use_naturalvar_mode(Node *n) const;
+
+ /* Director subclass comparison test */
+ String *none_comparison;
+
+ /* Director constructor "template" code */
+ String *director_ctor_code;
+
+ /* Director 'protected' constructor "template" code, disabled by
+ default. Each language that needs it, has to define it. */
+ String *director_prot_ctor_code;
+
+ /* Director allows multiple inheritance */
+ int director_multiple_inheritance;
+
+ /* Used to translate Doxygen comments to target documentation format */
+ class DoxygenTranslator *doxygenTranslator;
+
+private:
+ void unrollOneVirtualMethod(String *classname, Node *n, Node *parent, List *vm, int &virtual_destructor, int protectedbase);
+
+ Hash *symtabs; /* symbol tables */
+ int overloading;
+ int multiinput;
+ int cplus_runtime;
+ static Language *this_;
+};
+
+extern "C" {
+ typedef Language *(*ModuleFactory) (void);
+}
+
+enum Status {Disabled, Deprecated, Experimental, Supported};
+
+struct TargetLanguageModule {
+ const char *name;
+ ModuleFactory fac;
+ const char *help;
+ Status status;
+};
+
+int SWIG_main(int argc, char *argv[], const TargetLanguageModule *tlm);
+void emit_parameter_variables(ParmList *l, Wrapper *f);
+void emit_return_variable(Node *n, SwigType *rt, Wrapper *f);
+void SWIG_config_file(const_String_or_char_ptr );
+const String *SWIG_output_directory();
+void SWIG_config_cppext(const char *ext);
+void Swig_print_xml(Node *obj, String *filename);
+
+/* get the list of generated files */
+List *SWIG_output_files();
+
+void SWIG_library_directory(const char *);
+int emit_num_arguments(ParmList *);
+int emit_num_required(ParmList *);
+int emit_isvarargs(ParmList *p);
+bool emit_isvarargs_function(Node *n);
+void emit_attach_parmmaps(ParmList *, Wrapper *f);
+void emit_mark_varargs(ParmList *l);
+String *emit_action(Node *n);
+int emit_action_code(Node *n, String *wrappercode, String *action);
+void Swig_overload_check(Node *n);
+String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *, const_String_or_char_ptr fmt_fastdispatch = 0);
+String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *);
+List *Swig_overload_rank(Node *n, bool script_lang_wrapping);
+SwigType *cplus_value_type(SwigType *t);
+
+int Swig_directors_enabled();
+/* directors.cxx start */
+String *Swig_csuperclass_call(String *base, String *method, ParmList *l);
+String *Swig_class_declaration(Node *n, String *name);
+String *Swig_class_name(Node *n);
+String *Swig_method_call(const_String_or_char_ptr name, ParmList *parms);
+String *Swig_method_decl(SwigType *return_base_type, SwigType *decl, const_String_or_char_ptr id, List *args, int default_args);
+String *Swig_director_declaration(Node *n);
+void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
+void Swig_director_parms_fixup(ParmList *parms);
+bool Swig_director_can_unwrap(Node *n);
+/* directors.cxx end */
+
+/* Utilities */
+
+int is_public(Node *n);
+int is_private(Node *n);
+int is_protected(Node *n);
+int is_member_director(Node *parentnode, Node *member);
+int is_member_director(Node *member);
+int is_non_virtual_protected_access(Node *n); /* Check if the non-virtual protected members are required (for directors) */
+
+void Wrapper_virtual_elimination_mode_set(int);
+void Wrapper_fast_dispatch_mode_set(int);
+void Wrapper_cast_dispatch_mode_set(int);
+void Wrapper_naturalvar_mode_set(int);
+
+void clean_overloaded(Node *n);
+
+extern "C" {
+ const char *Swig_to_string(DOH *object, int count = -1);
+ const char *Swig_to_string_with_location(DOH *object, int count = -1);
+ void Swig_print(DOH *object, int count = -1);
+ void Swig_print_with_location(DOH *object, int count = -1);
+}
+
+void Swig_default_allocators(Node *n);
+void Swig_process_types(Node *n);
+
+/* Contracts */
+void Swig_contracts(Node *n);
+void Swig_contract_mode_set(int flag);
+int Swig_contract_mode_get();
+
+/* Nested classes */
+void Swig_nested_process_classes(Node *n);
+void Swig_nested_name_unnamed_c_structs(Node *n);
+
+/* Interface feature */
+void Swig_interface_feature_enable();
+void Swig_interface_propagate_methods(Node *n);
+
+/* Miscellaneous */
+template <class T> class save_value {
+ T _value;
+ T& _value_ptr;
+ save_value(const save_value&);
+ save_value& operator=(const save_value&);
+
+public:
+ save_value(T& value) : _value(value), _value_ptr(value) {}
+ save_value(T& value, T new_val) : _value(value), _value_ptr(value) { value = new_val; }
+ ~save_value() { _value_ptr = _value; }
+};
+
+#endif
diff --git a/contrib/tools/swig/Source/Modules/tcl8.cxx b/contrib/tools/swig/Source/Modules/tcl8.cxx
new file mode 100644
index 00000000000..0d07d0b9452
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/tcl8.cxx
@@ -0,0 +1,1293 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * tcl8.cxx
+ *
+ * Tcl8 language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+static const char *usage = "\
+Tcl 8 Options (available with -tcl8)\n\
+ -itcl - Enable ITcl support\n\
+ -nosafe - Leave out SafeInit module function.\n\
+ -prefix <name> - Set a prefix <name> to be prepended to all names\n\
+ -namespace - Build module into a Tcl 8 namespace\n\
+ -pkgversion - Set package version\n\n";
+
+static String *cmd_tab = 0; /* Table of command names */
+static String *var_tab = 0; /* Table of global variables */
+static String *const_tab = 0; /* Constant table */
+static String *methods_tab = 0; /* Methods table */
+static String *attr_tab = 0; /* Attribute table */
+static String *prefix = 0;
+static String *module = 0;
+static int namespace_option = 0;
+static String *init_name = 0;
+static String *ns_name = 0;
+static int have_constructor;
+static String *constructor_name;
+static int have_destructor;
+static int have_base_classes;
+static String *destructor_action = 0;
+static String *version = (String *) "0.0";
+static String *class_name = 0;
+
+static int have_attributes;
+static int have_methods;
+static int nosafe = 0;
+
+static File *f_header = 0;
+static File *f_wrappers = 0;
+static File *f_init = 0;
+static File *f_begin = 0;
+static File *f_runtime = 0;
+
+
+// Itcl support
+static int itcl = 0;
+static File *f_shadow = 0;
+static File *f_shadow_stubs = 0;
+
+static String *constructor = 0;
+static String *destructor = 0;
+static String *base_classes = 0;
+static String *base_class_init = 0;
+static String *methods = 0;
+static String *imethods = 0;
+static String *attributes = 0;
+static String *attribute_traces = 0;
+static String *iattribute_traces = 0;
+
+
+
+class TCL8:public Language {
+public:
+
+ /* ------------------------------------------------------------
+ * TCL8::main()
+ * ------------------------------------------------------------ */
+
+ virtual void main(int argc, char *argv[]) {
+
+ SWIG_library_directory("tcl");
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if (strcmp(argv[i], "-prefix") == 0) {
+ if (argv[i + 1]) {
+ prefix = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else
+ Swig_arg_error();
+ } else if (strcmp(argv[i], "-pkgversion") == 0) {
+ if (argv[i + 1]) {
+ version = NewString(argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ }
+ } else if (strcmp(argv[i], "-namespace") == 0) {
+ namespace_option = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-itcl") == 0) {
+ itcl = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nosafe") == 0) {
+ nosafe = 1;
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-help") == 0) {
+ fputs(usage, stdout);
+ } else if (strcmp(argv[i], "-cppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is now always on.\n", argv[i]);
+ Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-nocppcast") == 0) {
+ Printf(stderr, "Deprecated command line option: %s. This option is no longer supported.\n", argv[i]);
+ Swig_mark_arg(i);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ Preprocessor_define("SWIGTCL 1", 0);
+ // SWIGTCL8 is deprecated, and no longer documented.
+ Preprocessor_define("SWIGTCL8 1", 0);
+ SWIG_config_file("tcl8.swg");
+ allow_overloading();
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+
+ /* Initialize some variables for the object interface */
+
+ cmd_tab = NewString("");
+ var_tab = NewString("");
+ methods_tab = NewString("");
+ const_tab = NewString("");
+
+ Swig_banner(f_begin);
+
+ Swig_obligatory_macros(f_runtime, "TCL");
+
+ /* Set the module name, namespace, and prefix */
+
+ module = NewStringf("%(lower)s", Getattr(n, "name"));
+ init_name = NewStringf("%(title)s_Init", module);
+
+ ns_name = prefix ? Copy(prefix) : Copy(module);
+ if (prefix)
+ Append(prefix, "_");
+
+
+ /* If shadow classing is enabled, we're going to change the module name to "_module" */
+ if (itcl) {
+ String *filen;
+ filen = NewStringf("%s%s.itcl", SWIG_output_directory(), module);
+
+ Insert(module, 0, "_");
+
+ if ((f_shadow = NewFile(filen, "w", SWIG_output_files())) == 0) {
+ FileErrorDisplay(filen);
+ Exit(EXIT_FAILURE);
+ }
+ f_shadow_stubs = NewString("");
+
+ Swig_register_filebyname("shadow", f_shadow);
+ Swig_register_filebyname("itcl", f_shadow);
+
+ Swig_banner_target_lang(f_shadow, "#");
+
+ Printv(f_shadow, "\npackage require Itcl\n\n", NIL);
+ Delete(filen);
+ }
+
+ /* Generate some macros used throughout code generation */
+
+ Printf(f_header, "#define SWIG_init %s\n", init_name);
+ Printf(f_header, "#define SWIG_name \"%s\"\n", module);
+ if (namespace_option) {
+ Printf(f_header, "#define SWIG_prefix \"%s::\"\n", ns_name);
+ Printf(f_header, "#define SWIG_namespace \"%s\"\n\n", ns_name);
+ } else {
+ Printf(f_header, "#define SWIG_prefix \"%s\"\n", prefix);
+ }
+ Printf(f_header, "#define SWIG_version \"%s\"\n", version);
+
+ Printf(cmd_tab, "\nstatic swig_command_info swig_commands[] = {\n");
+ Printf(var_tab, "\nstatic swig_var_info swig_variables[] = {\n");
+ Printf(const_tab, "\nstatic swig_const_info swig_constants[] = {\n");
+
+ Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
+
+ /* Start emitting code */
+ Language::top(n);
+
+ /* Done. Close up the module */
+ Printv(cmd_tab, tab4, "{0, 0, 0}\n", "};\n", NIL);
+ Printv(var_tab, tab4, "{0,0,0,0}\n", "};\n", NIL);
+ Printv(const_tab, tab4, "{0,0,0,0,0,0}\n", "};\n", NIL);
+
+ Printv(f_wrappers, cmd_tab, var_tab, const_tab, NIL);
+
+ /* Dump the pointer equivalency table */
+ SwigType_emit_type_table(f_runtime, f_wrappers);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n}\n#endif\n");
+
+ /* Close the init function and quit */
+ Printf(f_init, "return TCL_OK;\n}\n");
+
+ if (!nosafe) {
+ Printf(f_init, "SWIGEXPORT int %(title)s_SafeInit(Tcl_Interp *interp) {\n", module);
+ Printf(f_init, " return SWIG_init(interp);\n");
+ Printf(f_init, "}\n");
+ }
+
+ if (itcl) {
+ Printv(f_shadow, f_shadow_stubs, "\n", NIL);
+ Delete(f_shadow);
+ }
+
+ /* Close all of the files */
+ Dump(f_runtime, f_begin);
+ Printv(f_begin, f_header, f_wrappers, NIL);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Delete(f_runtime);
+ Delete(f_begin);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * functionWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int functionWrapper(Node *n) {
+ String *name = Getattr(n, "name"); /* Like to get rid of this */
+ String *iname = Getattr(n, "sym:name");
+ SwigType *returntype = Getattr(n, "type");
+ ParmList *parms = Getattr(n, "parms");
+ String *overname = 0;
+
+ Parm *p;
+ int i;
+ String *tm;
+ Wrapper *f;
+ String *incode, *cleanup, *outarg, *argstr, *args;
+ int num_arguments = 0;
+ int num_required = 0;
+ int varargs = 0;
+
+ char source[64];
+
+ if (Getattr(n, "sym:overloaded")) {
+ overname = Getattr(n, "sym:overname");
+ } else {
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ }
+
+ incode = NewString("");
+ cleanup = NewString("");
+ outarg = NewString("");
+ argstr = NewString("\"");
+ args = NewString("");
+
+ f = NewWrapper();
+
+#ifdef SWIG_USE_RESULTOBJ
+ Wrapper_add_local(f, "resultobj", "Tcl_Obj *resultobj = NULL");
+#endif
+
+
+ String *wname = Swig_name_wrapper(iname);
+ if (overname) {
+ Append(wname, overname);
+ }
+ Setattr(n, "wrap:name", wname);
+
+ Printv(f->def, "SWIGINTERN int\n ", wname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(parms, f);
+
+ /* Attach standard typemaps */
+ emit_attach_parmmaps(parms, f);
+ Setattr(n, "wrap:parms", parms);
+
+ /* Get number of require and total arguments */
+ num_arguments = emit_num_arguments(parms);
+ num_required = emit_num_required(parms);
+ varargs = emit_isvarargs(parms);
+
+ /* Unmarshal parameters */
+
+ for (i = 0, p = parms; i < num_arguments; i++) {
+ /* Skip ignored arguments */
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ /* Produce string representations of the source and target arguments */
+ sprintf(source, "objv[%d]", i + 1);
+
+ if (i == num_required)
+ Putc('|', argstr);
+ if ((tm = Getattr(p, "tmap:in"))) {
+ String *parse = Getattr(p, "tmap:in:parse");
+ if (!parse) {
+ Replaceall(tm, "$input", source);
+ Setattr(p, "emit:input", source);
+
+ if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
+ Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
+ } else {
+ Replaceall(tm, "$disown", "0");
+ }
+
+ Putc('o', argstr);
+ Printf(args, ",(void *)0");
+ if (i >= num_required) {
+ Printf(incode, "if (objc > %d) {\n", i + 1);
+ }
+ Printf(incode, "%s\n", tm);
+ if (i >= num_required) {
+ Printf(incode, "}\n");
+ }
+ } else {
+ Printf(argstr, "%s", parse);
+ Printf(args, ",&%s", ln);
+ if (Strcmp(parse, "p") == 0) {
+ SwigType *lt = SwigType_ltype(pt);
+ SwigType_remember(pt);
+ if (Cmp(lt, "p.void") == 0) {
+ Printf(args, ",(void *)0");
+ } else {
+ Printf(args, ",SWIGTYPE%s", SwigType_manglestr(pt));
+ }
+ Delete(lt);
+ }
+ }
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ }
+ p = nextSibling(p);
+ }
+
+ if (!varargs) {
+ Putc(':', argstr);
+ } else {
+ Putc(';', argstr);
+ /* If variable length arguments we need to emit the in typemap here */
+ if (p && (tm = Getattr(p, "tmap:in"))) {
+ sprintf(source, "objv[%d]", i + 1);
+ Printf(incode, "if (objc > %d) {\n", i);
+ Replaceall(tm, "$input", source);
+ Printv(incode, tm, "\n", NIL);
+ Printf(incode, "}\n");
+ }
+ }
+
+ Printf(argstr, "%s\"", usage_string(Char(iname), returntype, parms));
+
+ Printv(f->code, "if (SWIG_GetArgs(interp, objc, objv,", argstr, args, ") == TCL_ERROR) SWIG_fail;\n", NIL);
+
+ Printv(f->code, incode, NIL);
+
+ /* Insert constraint checking code */
+ for (p = parms; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (i = 0, p = parms; p; i++) {
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")
+ && !Getattr(p, "tmap:in:parse") && (tm = Getattr(p, "tmap:freearg"))) {
+ if (Len(tm) != 0) {
+ Printv(cleanup, tm, "\n", NIL);
+ }
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (i = 0, p = parms; p; i++) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+#ifdef SWIG_USE_RESULTOBJ
+ Replaceall(tm, "$result", "resultobj");
+#else
+ Replaceall(tm, "$result", "(Tcl_GetObjResult(interp))");
+#endif
+ Replaceall(tm, "$arg", Getattr(p, "emit:input"));
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Now write code to make the function call */
+ String *actioncode = emit_action(n);
+
+ /* Need to redo all of this code (eventually) */
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
+#ifdef SWIG_USE_RESULTOBJ
+ Replaceall(tm, "$result", "resultobj");
+#else
+ Replaceall(tm, "$result", "(Tcl_GetObjResult(interp))");
+#endif
+ if (GetFlag(n, "feature:new")) {
+ Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
+ } else {
+ Replaceall(tm, "$owner", "0");
+ }
+ Printf(f->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(returntype, 0), name);
+ }
+ emit_return_variable(n, returntype, f);
+
+ /* Dump output argument code */
+ Printv(f->code, outarg, NIL);
+
+ /* Dump the argument cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look for any remaining cleanup */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
+ Printf(f->code, "%s\n", tm);
+ }
+#ifdef SWIG_USE_RESULTOBJ
+ Printv(f->code, "if (resultobj) Tcl_SetObjResult(interp, resultobj);\n", NIL);
+#endif
+ Printv(f->code, "return TCL_OK;\n", NIL);
+ Printv(f->code, "fail:\n", cleanup, "return TCL_ERROR;\n", NIL);
+ Printv(f->code, "}\n", NIL);
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ bool isvoid = !Cmp(returntype, "void");
+ Replaceall(f->code, "$isvoid", isvoid ? "1" : "0");
+
+ Replaceall(f->code, "$symname", iname);
+
+ /* Dump out the function */
+ Wrapper_print(f, f_wrappers);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ /* Register the function with Tcl */
+ Printv(cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", Swig_name_wrapper(iname), ", NULL},\n", NIL);
+ } else {
+ if (!Getattr(n, "sym:nextSibling")) {
+ /* Emit overloading dispatch function */
+
+ int maxargs;
+ String *dispatch = Swig_overload_dispatch(n, "return %s(clientData, interp, objc, argv - 1);", &maxargs);
+
+ /* Generate a dispatch wrapper for all overloaded functions */
+
+ Wrapper *df = NewWrapper();
+ String *dname = Swig_name_wrapper(iname);
+
+ Printv(df->def, "SWIGINTERN int\n", dname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {", NIL);
+ Printf(df->code, "Tcl_Obj *const *argv = objv+1;\n");
+ Printf(df->code, "int argc = objc-1;\n");
+ Printv(df->code, dispatch, "\n", NIL);
+ Node *sibl = n;
+ while (Getattr(sibl, "sym:previousSibling"))
+ sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
+ String *protoTypes = NewString("");
+ do {
+ String *fulldecl = Swig_name_decl(sibl);
+ Printf(protoTypes, "\n\" %s\\n\"", fulldecl);
+ Delete(fulldecl);
+ } while ((sibl = Getattr(sibl, "sym:nextSibling")));
+ Printf(df->code, "Tcl_SetResult(interp,(char *) "
+ "\"Wrong number or type of arguments for overloaded function '%s'.\\n\""
+ "\n\" Possible C/C++ prototypes are:\\n\"%s, TCL_STATIC);\n", iname, protoTypes);
+ Delete(protoTypes);
+ Printf(df->code, "return TCL_ERROR;\n");
+ Printv(df->code, "}\n", NIL);
+ Wrapper_print(df, f_wrappers);
+ Printv(cmd_tab, tab4, "{ SWIG_prefix \"", iname, "\", (swig_wrapper_func) ", dname, ", NULL},\n", NIL);
+ DelWrapper(df);
+ Delete(dispatch);
+ Delete(dname);
+ }
+ }
+
+ Delete(incode);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(argstr);
+ Delete(args);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * variableWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int variableWrapper(Node *n) {
+
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+
+ String *setname = 0;
+ String *setfname = 0;
+ Wrapper *setf = 0, *getf = 0;
+ int readonly = 0;
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+
+ /* Create a function for getting a variable */
+ int addfail = 0;
+ getf = NewWrapper();
+ String *getname = Swig_name_get(NSPACE_TODO, iname);
+ String *getfname = Swig_name_wrapper(getname);
+ Setattr(n, "wrap:name", getfname);
+ Printv(getf->def, "SWIGINTERN const char *", getfname, "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, char *name1, char *name2, int flags) {", NIL);
+ Wrapper_add_local(getf, "value", "Tcl_Obj *value = 0");
+ if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
+ Replaceall(tm, "$result", "value");
+ /* Printf(getf->code, "%s\n",tm); */
+ addfail = emit_action_code(n, getf->code, tm);
+ Printf(getf->code, "if (value) {\n");
+ Printf(getf->code, "Tcl_SetVar2(interp,name1,name2,Tcl_GetString(value), flags);\n");
+ Printf(getf->code, "Tcl_DecrRefCount(value);\n");
+ Printf(getf->code, "}\n");
+ Printf(getf->code, "return NULL;\n");
+ if (addfail) {
+ Append(getf->code, "fail:\n");
+ Printf(getf->code, "return \"%s\";\n", iname);
+ }
+ Printf(getf->code, "}\n");
+ Wrapper_print(getf, f_wrappers);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
+ DelWrapper(getf);
+ return SWIG_NOWRAP;
+ }
+ DelWrapper(getf);
+
+ /* Try to create a function setting a variable */
+ if (!is_immutable(n)) {
+ setf = NewWrapper();
+ setname = Swig_name_set(NSPACE_TODO, iname);
+ setfname = Swig_name_wrapper(setname);
+ Setattr(n, "wrap:name", setfname);
+ if (setf) {
+ Printv(setf->def, "SWIGINTERN const char *", setfname,
+ "(ClientData clientData SWIGUNUSED, Tcl_Interp *interp, char *name1, char *name2 SWIGUNUSED, int flags) {", NIL);
+ Wrapper_add_local(setf, "value", "Tcl_Obj *value = 0");
+ Wrapper_add_local(setf, "name1o", "Tcl_Obj *name1o = 0");
+
+ if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
+ Replaceall(tm, "$input", "value");
+ Printf(setf->code, "name1o = Tcl_NewStringObj(name1,-1);\n");
+ Printf(setf->code, "value = Tcl_ObjGetVar2(interp, name1o, 0, flags);\n");
+ Printf(setf->code, "Tcl_DecrRefCount(name1o);\n");
+ Printf(setf->code, "if (!value) SWIG_fail;\n");
+ /* Printf(setf->code,"%s\n", tm); */
+ emit_action_code(n, setf->code, tm);
+ Printf(setf->code, "return NULL;\n");
+ Printf(setf->code, "fail:\n");
+ Printf(setf->code, "return \"%s\";\n", iname);
+ Printf(setf->code, "}\n");
+ Wrapper_print(setf, f_wrappers);
+ } else {
+ Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
+ readonly = 1;
+ }
+ }
+ DelWrapper(setf);
+ } else {
+ readonly = 1;
+ }
+
+
+ Printv(var_tab, tab4, "{ SWIG_prefix \"", iname, "\", 0, (swig_variable_func) ", getfname, ",", NIL);
+ if (readonly) {
+ static int readonlywrap = 0;
+ if (!readonlywrap) {
+ Wrapper *ro = NewWrapper();
+ Printf(ro->def,
+ "SWIGINTERN const char *swig_readonly(ClientData clientData SWIGUNUSED, Tcl_Interp *interp SWIGUNUSED, char *name1 SWIGUNUSED, char *name2 SWIGUNUSED, int flags SWIGUNUSED) {");
+ Printv(ro->code, "return \"Variable is read-only\";\n", "}\n", NIL);
+ Wrapper_print(ro, f_wrappers);
+ readonlywrap = 1;
+ DelWrapper(ro);
+ }
+ Printf(var_tab, "(swig_variable_func) swig_readonly},\n");
+ } else {
+ Printv(var_tab, "(swig_variable_func) ", setfname, "},\n", NIL);
+ }
+ Delete(getfname);
+ Delete(setfname);
+ Delete(setname);
+ Delete(getname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int constantWrapper(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = Getattr(n, "sym:name");
+ String *nsname = !namespace_option ? Copy(iname) : NewStringf("%s::%s", ns_name, iname);
+ SwigType *type = Getattr(n, "type");
+ String *value = Getattr(n, "value");
+ String *tm;
+
+ if (!addSymbol(iname, n))
+ return SWIG_ERROR;
+ if (namespace_option)
+ Setattr(n, "sym:name", nsname);
+
+ /* Special hook for member pointer */
+ if (SwigType_type(type) == T_MPOINTER) {
+ String *wname = Swig_name_wrapper(iname);
+ Printf(f_wrappers, "static %s = %s;\n", SwigType_str(type, wname), value);
+ value = Char(wname);
+ }
+
+ if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ Printf(const_tab, "%s,\n", tm);
+ } else if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
+ Replaceall(tm, "$value", value);
+ Replaceall(tm, "$nsname", nsname);
+ Printf(f_init, "%s\n", tm);
+ } else {
+ Delete(nsname);
+ Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
+ return SWIG_NOWRAP;
+ }
+ Delete(nsname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * nativeWrapper()
+ * ------------------------------------------------------------ */
+
+ virtual int nativeWrapper(Node *n) {
+ String *name = Getattr(n, "sym:name");
+ String *funcname = Getattr(n, "wrap:name");
+ if (!addSymbol(funcname, n))
+ return SWIG_ERROR;
+
+ Printf(f_init, "\t Tcl_CreateObjCommand(interp, SWIG_prefix \"%s\", (swig_wrapper_func) %s, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);\n", name,
+ funcname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int classHandler(Node *n) {
+ static Hash *emitted = NewHash();
+ String *mangled_classname = 0;
+ SwigType *real_classname = 0;
+
+ have_constructor = 0;
+ have_destructor = 0;
+ destructor_action = 0;
+ constructor_name = 0;
+
+ if (itcl) {
+ constructor = NewString("");
+ destructor = NewString("");
+ base_classes = NewString("");
+ base_class_init = NewString("");
+ methods = NewString("");
+ imethods = NewString("");
+ attributes = NewString("");
+ attribute_traces = NewString("");
+ iattribute_traces = NewString("");
+
+ have_base_classes = 0;
+ have_methods = 0;
+ have_attributes = 0;
+ }
+
+ class_name = Getattr(n, "sym:name");
+ if (!addSymbol(class_name, n))
+ return SWIG_ERROR;
+
+ real_classname = Getattr(n, "name");
+ mangled_classname = Swig_name_mangle_type(real_classname);
+
+ if (Getattr(emitted, mangled_classname))
+ return SWIG_NOWRAP;
+ Setattr(emitted, mangled_classname, "1");
+
+ attr_tab = NewString("");
+ Printf(attr_tab, "static swig_attribute swig_");
+ Printv(attr_tab, mangled_classname, "_attributes[] = {\n", NIL);
+
+ methods_tab = NewStringf("");
+ Printf(methods_tab, "static swig_method swig_");
+ Printv(methods_tab, mangled_classname, "_methods[] = {\n", NIL);
+
+ /* Generate normal wrappers */
+ Language::classHandler(n);
+
+ SwigType *t = Copy(Getattr(n, "name"));
+ SwigType_add_pointer(t);
+
+ // Catch all: eg. a class with only static functions and/or variables will not have 'remembered'
+ // SwigType_remember(t);
+ String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname);
+ SwigType_remember_clientdata(t, wrap_class);
+
+ String *rt = Copy(getClassType());
+ SwigType_add_pointer(rt);
+
+ // Register the class structure with the type checker
+ /* Printf(f_init,"SWIG_TypeClientData(SWIGTYPE%s, (void *) &_wrap_class_%s);\n", SwigType_manglestr(t), mangled_classname); */
+ if (have_destructor) {
+ Printv(f_wrappers, "SWIGINTERN void swig_delete_", class_name, "(void *obj) {\n", NIL);
+ if (destructor_action) {
+ Printv(f_wrappers, SwigType_str(rt, "arg1"), " = (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ Printv(f_wrappers, destructor_action, "\n", NIL);
+ } else {
+ if (CPlusPlus) {
+ Printv(f_wrappers, " delete (", SwigType_str(rt, 0), ") obj;\n", NIL);
+ } else {
+ Printv(f_wrappers, " free((char *) obj);\n", NIL);
+ }
+ }
+ Printf(f_wrappers, "}\n");
+ }
+
+ Printf(methods_tab, " {0,0}\n};\n");
+ Printv(f_wrappers, methods_tab, NIL);
+
+ Printf(attr_tab, " {0,0,0}\n};\n");
+ Printv(f_wrappers, attr_tab, NIL);
+
+ /* Handle inheritance */
+
+ String *base_class = NewString("");
+ String *base_class_names = NewString("");
+
+ if (itcl) {
+ base_classes = NewString("");
+ }
+
+ List *baselist = Getattr(n, "bases");
+ if (baselist && Len(baselist)) {
+ Iterator b;
+ int index = 0;
+ b = First(baselist);
+ while (b.item) {
+ SwigType *bname = Getattr(b.item, "name");
+ if ((!bname) || GetFlag(b.item, "feature:ignore") || (!Getattr(b.item, "module"))) {
+ b = Next(b);
+ continue;
+ }
+ if (itcl) {
+ have_base_classes = 1;
+ Printv(base_classes, bname, " ", NIL);
+ Printv(base_class_init, " ", bname, "Ptr::constructor $ptr\n", NIL);
+ }
+ String *bmangle = Swig_name_mangle_type(bname);
+ // Printv(f_wrappers,"extern swig_class _wrap_class_", bmangle, ";\n", NIL);
+ // Printf(base_class,"&_wrap_class_%s",bmangle);
+ Printf(base_class, "0");
+ Printf(base_class_names, "\"%s *\",", SwigType_namestr(bname));
+ /* Put code to register base classes in init function */
+
+ //Printf(f_init,"/* Register base : %s */\n", bmangle);
+ //Printf(f_init,"swig_%s_bases[%d] = (swig_class *) SWIG_TypeQuery(\"%s *\")->clientdata;\n", mangled_classname, index, SwigType_namestr(bname));
+ (void)index;
+ b = Next(b);
+ index++;
+ Putc(',', base_class);
+ Delete(bmangle);
+ }
+ }
+
+ if (itcl) {
+ String *ptrclass = NewString("");
+
+ // First, build the pointer base class
+ Printv(ptrclass, "itcl::class ", class_name, "Ptr {\n", NIL);
+ if (have_base_classes)
+ Printv(ptrclass, " inherit ", base_classes, "\n", NIL);
+
+ // Define protected variables for SWIG object pointer
+ Printv(ptrclass, " protected variable swigobj\n", " protected variable thisown\n", NIL);
+
+ // Define public variables
+ if (have_attributes) {
+ Printv(ptrclass, attributes, NIL);
+
+ // base class swig_getset was being called for complex inheritance trees
+ if (namespace_option) {
+
+ Printv(ptrclass, " protected method ", class_name, "_swig_getset {var name1 name2 op} {\n", NIL);
+
+ Printv(ptrclass,
+ " switch -exact -- $op {\n",
+ " r {set $var [", ns_name, "::", class_name, "_[set var]_get $swigobj]}\n",
+ " w {", ns_name, "::", class_name, "_${var}_set $swigobj [set $var]}\n", " }\n", " }\n", NIL);
+ } else {
+ Printv(ptrclass,
+ " protected method ", class_name, "_swig_getset {var name1 name2 op} {\n",
+ " switch -exact -- $op {\n",
+ " r {set $var [", class_name, "_[set var]_get $swigobj]}\n",
+ " w {", class_name, "_${var}_set $swigobj [set $var]}\n", " }\n", " }\n", NIL);
+ }
+ }
+ // Add the constructor, which may include
+ // calls to base class class constructors
+
+ Printv(ptrclass, " constructor { ptr } {\n", NIL);
+ if (have_base_classes) {
+ Printv(ptrclass, base_class_init, NIL);
+ Printv(ptrclass, " } {\n", NIL);
+ }
+
+ Printv(ptrclass, " set swigobj $ptr\n", " set thisown 0\n", NIL);
+
+ if (have_attributes) {
+ Printv(ptrclass, attribute_traces, NIL);
+ }
+ Printv(ptrclass, " }\n", NIL);
+
+
+ // Add destructor
+ Printv(ptrclass, " destructor {\n",
+ " set d_func delete_", class_name, "\n",
+ " if { $thisown && ([info command $d_func] != \"\") } {\n" " $d_func $swigobj\n", " }\n", " }\n", NIL);
+
+ // Add methods
+ if (have_methods) {
+ Printv(ptrclass, imethods, NIL);
+ }
+
+ // Close out the pointer class
+ Printv(ptrclass, "}\n\n", NIL);
+ Printv(f_shadow, ptrclass, NIL);
+ // pointer class end
+
+
+ // Create the "real" class.
+ Printv(f_shadow, "itcl::class ", class_name, " {\n", NIL);
+ Printv(f_shadow, " inherit ", class_name, "Ptr\n", NIL);
+
+ // If we have a constructor, then use it.
+ // If not, then we must have an abstract class without
+ // any constructor. So we create a class constructor
+ // which will fail for this class (but not for inherited
+ // classes). Note that the constructor must fail before
+ // calling the ptrclass constructor.
+
+ if (have_constructor) {
+ Printv(f_shadow, constructor, NIL);
+ } else {
+ Printv(f_shadow, " constructor { } {\n", NIL);
+ Printv(f_shadow, " # This constructor will fail if called directly\n", NIL);
+ Printv(f_shadow, " if { [info class] == \"::", class_name, "\" } {\n", NIL);
+ Printv(f_shadow, " error \"No constructor for class ", class_name, (Getattr(n, "abstracts") ? " - class is abstract" : ""), "\"\n", NIL);
+ Printv(f_shadow, " }\n", NIL);
+ Printv(f_shadow, " }\n", NIL);
+ }
+
+ Printv(f_shadow, "}\n\n", NIL);
+ }
+
+ Printv(f_wrappers, "static swig_class *swig_", mangled_classname, "_bases[] = {", base_class, "0};\n", NIL);
+ Printv(f_wrappers, "static const char * swig_", mangled_classname, "_base_names[] = {", base_class_names, "0};\n", NIL);
+ Delete(base_class);
+ Delete(base_class_names);
+
+ Printv(f_wrappers, "static swig_class _wrap_class_", mangled_classname, " = { \"", class_name, "\", &SWIGTYPE", SwigType_manglestr(t), ",", NIL);
+
+ if (have_constructor) {
+ Printf(f_wrappers, "%s", Swig_name_wrapper(Swig_name_construct(NSPACE_TODO, constructor_name)));
+ Delete(constructor_name);
+ constructor_name = 0;
+ } else {
+ Printf(f_wrappers, "0");
+ }
+ if (have_destructor) {
+ Printv(f_wrappers, ", swig_delete_", class_name, NIL);
+ } else {
+ Printf(f_wrappers, ",0");
+ }
+ Printv(f_wrappers, ", swig_", mangled_classname, "_methods, swig_", mangled_classname, "_attributes, swig_", mangled_classname, "_bases,",
+ "swig_", mangled_classname, "_base_names, &swig_module, SWIG_TCL_HASHTABLE_INIT };\n", NIL);
+
+ if (!itcl) {
+ Printv(cmd_tab, tab4, "{ SWIG_prefix \"", class_name, "\", (swig_wrapper_func) SWIG_ObjectConstructor, (ClientData)&_wrap_class_", mangled_classname,
+ "},\n", NIL);
+ }
+
+ Delete(t);
+ Delete(mangled_classname);
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * memberfunctionHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int memberfunctionHandler(Node *n) {
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+
+ String *realname, *rname;
+
+ Language::memberfunctionHandler(n);
+
+ realname = iname ? iname : name;
+ rname = Swig_name_wrapper(Swig_name_member(NSPACE_TODO, class_name, realname));
+ if (!Getattr(n, "sym:nextSibling")) {
+ Printv(methods_tab, tab4, "{\"", realname, "\", ", rname, "}, \n", NIL);
+ }
+
+ if (itcl) {
+ ParmList *l = Getattr(n, "parms");
+ Parm *p = 0;
+ String *pname = NewString("");
+
+ // Add this member to our class handler function
+ Printv(imethods, tab2, "method ", realname, " [list ", NIL);
+
+ int pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ String *pn = Getattr(p, "name");
+ String *dv = Getattr(p, "value");
+ SwigType *pt = Getattr(p, "type");
+
+ Printv(pname, ",(", pt, ")", NIL);
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+
+ if (Len(dv) > 0) {
+ String *defval = NewString(dv);
+ if (namespace_option) {
+ Insert(defval, 0, "::");
+ Insert(defval, 0, ns_name);
+ }
+ if (Strncmp(dv, "(", 1) == 0) {
+ Insert(defval, 0, "$");
+ Replaceall(defval, "(", "");
+ Replaceall(defval, ")", "");
+ }
+ Printv(imethods, "[list ", pname, " ", defval, "] ", NIL);
+ } else {
+ Printv(imethods, pname, " ", NIL);
+ }
+ }
+ ++pnum;
+ }
+ Printv(imethods, "] ", NIL);
+
+ if (namespace_option) {
+ Printv(imethods, "{ ", ns_name, "::", class_name, "_", realname, " $swigobj", NIL);
+ } else {
+ Printv(imethods, "{ ", class_name, "_", realname, " $swigobj", NIL);
+ }
+
+ pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ String *pn = Getattr(p, "name");
+ SwigType *pt = Getattr(p, "type");
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+ Printv(imethods, " $", pname, NIL);
+ }
+ ++pnum;
+ }
+ Printv(imethods, " }\n", NIL);
+ have_methods = 1;
+ }
+
+ Delete(rname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * membervariableHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int membervariableHandler(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ String *rname;
+
+ Language::membervariableHandler(n);
+ Printv(attr_tab, tab4, "{ \"-", symname, "\",", NIL);
+ rname = Swig_name_wrapper(Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
+ Printv(attr_tab, rname, ", ", NIL);
+ Delete(rname);
+ if (!GetFlag(n, "feature:immutable")) {
+ rname = Swig_name_wrapper(Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, class_name, symname)));
+ Printv(attr_tab, rname, "},\n", NIL);
+ Delete(rname);
+ } else {
+ Printf(attr_tab, "0 },\n");
+ }
+
+ if (itcl) {
+ Printv(attributes, " public variable ", symname, "\n", NIL);
+
+ Printv(attribute_traces, " trace variable ", symname, " rw [list ", class_name, "_swig_getset ", symname, "]\n", NIL);
+ Printv(attribute_traces, " set ", symname, "\n", NIL);
+
+ have_attributes = 1;
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+
+ if (itcl) {
+ String *name = Getattr(n, "name");
+ String *iname = GetChar(n, "sym:name");
+
+ String *realname;
+
+ ParmList *l = Getattr(n, "parms");
+ Parm *p = 0;
+
+ String *pname = NewString("");
+
+ realname = iname ? iname : name;
+
+ if (!have_constructor) {
+ // Add this member to our class handler function
+ Printf(constructor, " constructor { ");
+
+ // Add parameter list
+ int pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ String *dv = Getattr(p, "value");
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+
+ if (Len(dv) > 0) {
+ Printv(constructor, "{", pname, " {", dv, "} } ", NIL);
+ } else {
+ Printv(constructor, pname, " ", NIL);
+ }
+ }
+ ++pnum;
+ }
+ Printf(constructor, "} { \n");
+
+ // [BRE] 08/17/00 Added test to see if we are instantiating this object
+ // type, or, if this constructor is being called as part of the itcl
+ // inheritance hierarchy.
+ // In the former case, we need to call the C++ constructor, in the
+ // latter we don't, or we end up with two C++ objects.
+ // Check to see if we are instantiating a 'realname' or something
+ // derived from it.
+ //
+ Printv(constructor, " if { [string equal -nocase \"", realname, "\" \"[namespace tail [info class]]\" ] } {\n", NIL);
+
+ // Call to constructor wrapper and parent Ptr class
+ // [BRE] add -namespace/-prefix support
+
+ if (namespace_option) {
+ Printv(constructor, " ", realname, "Ptr::constructor [", ns_name, "::new_", realname, NIL);
+ } else {
+ Printv(constructor, " ", realname, "Ptr::constructor [new_", realname, NIL);
+ }
+
+ pnum = 0;
+ for (p = l; p; p = nextSibling(p)) {
+
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ Clear(pname);
+
+ /* Only print an argument if not void */
+ if (Cmp(pt, "void") != 0) {
+ if (Len(pn) > 0) {
+ Printv(pname, pn, NIL);
+ } else {
+ Printf(pname, "p%d", pnum);
+ }
+ Printv(constructor, " $", pname, NIL);
+ }
+ ++pnum;
+ }
+
+ Printv(constructor, "]\n", " }\n", " } {\n", " set thisown 1\n", " }\n", NIL);
+ }
+ }
+
+ if (!have_constructor)
+ constructor_name = NewString(Getattr(n, "sym:name"));
+ have_constructor = 1;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorHandler()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ have_destructor = 1;
+ destructor_action = Getattr(n, "wrap:action");
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * validIdentifier()
+ * ------------------------------------------------------------ */
+
+ virtual int validIdentifier(String *s) {
+ if (Strchr(s, ' '))
+ return 0;
+ return 1;
+ }
+
+ /* ------------------------------------------------------------
+ * usage_string()
+ * ------------------------------------------------------------ */
+
+ char *usage_string(char *iname, SwigType *, ParmList *l) {
+ static String *temp = 0;
+ Parm *p;
+ int i, numopt, pcount;
+
+ if (!temp)
+ temp = NewString("");
+ Clear(temp);
+ if (namespace_option) {
+ Printf(temp, "%s::%s ", ns_name, iname);
+ } else {
+ Printf(temp, "%s ", iname);
+ }
+ /* Now go through and print parameters */
+ i = 0;
+ pcount = emit_num_arguments(l);
+ numopt = pcount - emit_num_required(l);
+ for (p = l; p; p = nextSibling(p)) {
+
+ SwigType *pt = Getattr(p, "type");
+ String *pn = Getattr(p, "name");
+ /* Only print an argument if not ignored */
+ if (!checkAttribute(p, "tmap:in:numinputs", "0")) {
+ if (i >= (pcount - numopt))
+ Putc('?', temp);
+ if (Len(pn) > 0) {
+ Printf(temp, "%s", pn);
+ } else {
+ Printf(temp, "%s", SwigType_str(pt, 0));
+ }
+ if (i >= (pcount - numopt))
+ Putc('?', temp);
+ Putc(' ', temp);
+ i++;
+ }
+ }
+ return Char(temp);
+ }
+
+ String *runtimeCode() {
+ String *s = NewString("");
+ String *serrors = Swig_include_sys("tclerrors.swg");
+ if (!serrors) {
+ Printf(stderr, "*** Unable to open 'tclerrors.swg'\n");
+ } else {
+ Append(s, serrors);
+ Delete(serrors);
+ }
+ String *sapi = Swig_include_sys("tclapi.swg");
+ if (!sapi) {
+ Printf(stderr, "*** Unable to open 'tclapi.swg'\n");
+ } else {
+ Append(s, sapi);
+ Delete(sapi);
+ }
+ String *srun = Swig_include_sys("tclrun.swg");
+ if (!srun) {
+ Printf(stderr, "*** Unable to open 'tclrun.swg'\n");
+ } else {
+ Append(s, srun);
+ Delete(srun);
+ }
+
+ return s;
+ }
+
+ String *defaultExternalRuntimeFilename() {
+ return NewString("swigtclrun.h");
+ }
+};
+
+/* ----------------------------------------------------------------------
+ * swig_tcl() - Instantiate module
+ * ---------------------------------------------------------------------- */
+
+static Language *new_swig_tcl() {
+ return new TCL8();
+}
+extern "C" Language *swig_tcl(void) {
+ return new_swig_tcl();
+}
diff --git a/contrib/tools/swig/Source/Modules/typepass.cxx b/contrib/tools/swig/Source/Modules/typepass.cxx
new file mode 100644
index 00000000000..a75be41b355
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/typepass.cxx
@@ -0,0 +1,1195 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * typepass.cxx
+ *
+ * This module builds all of the internal type information by collecting
+ * typedef declarations as well as registering classes, structures, and unions.
+ * This information is needed to correctly handle shadow classes and other
+ * advanced features. This phase of compilation is also used to perform
+ * type-expansion. All types are fully qualified with namespace prefixes
+ * and other information needed for compilation.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+#include "cparse.h"
+
+struct normal_node {
+ Symtab *symtab;
+ Hash *typescope;
+ List *normallist;
+ normal_node *next;
+};
+
+static normal_node *patch_list = 0;
+
+/* Singleton class - all non-static methods in this class are private */
+class TypePass:private Dispatcher {
+ Node *inclass;
+ Node *module;
+ int importmode;
+ String *nsname;
+ String *nssymname;
+ Hash *classhash;
+ List *normalize;
+
+ TypePass() :
+ inclass(0),
+ module(0),
+ importmode(0),
+ nsname(0),
+ nssymname(0),
+ classhash(0),
+ normalize(0) {
+ }
+
+ /* Normalize a type. Replaces type with fully qualified version */
+ void normalize_type(SwigType *ty) {
+ SwigType *qty;
+ if (CPlusPlus) {
+ Replaceall(ty, "struct ", "");
+ Replaceall(ty, "union ", "");
+ Replaceall(ty, "class ", "");
+ }
+
+ qty = SwigType_typedef_qualified(ty);
+ /* Printf(stdout,"%s --> %s\n", ty, qty); */
+ Clear(ty);
+ Append(ty, qty);
+ Delete(qty);
+ }
+
+ /* Normalize a parameter list */
+
+ void normalize_parms(ParmList *p) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ normalize_type(ty);
+ /* This is a check for a function type */
+ {
+ SwigType *qty = SwigType_typedef_resolve_all(ty);
+ if (SwigType_isfunction(qty)) {
+ SwigType_add_pointer(ty);
+ }
+ Delete(qty);
+ }
+
+ String *value = Getattr(p, "value");
+ if (value) {
+ Node *n = Swig_symbol_clookup(value, 0);
+ if (n) {
+ String *q = Swig_symbol_qualified(n);
+ if (q && Len(q)) {
+ String *vb = Swig_scopename_last(value);
+ Clear(value);
+ Printf(value, "%s::%s", SwigType_namestr(q), vb);
+ Delete(q);
+ }
+ }
+ }
+ if (value && SwigType_istemplate(value)) {
+ String *nv = SwigType_namestr(value);
+ Setattr(p, "value", nv);
+ }
+ p = nextSibling(p);
+ }
+ }
+
+ void normalize_later(ParmList *p) {
+ while (p) {
+ SwigType *ty = Getattr(p, "type");
+ Append(normalize, ty);
+ p = nextSibling(p);
+ }
+ }
+
+ /* Walk through entries in normalize list and patch them up */
+ void normalize_list() {
+ Hash *currentsym = Swig_symbol_current();
+
+ normal_node *nn = patch_list;
+ normal_node *np;
+ while (nn) {
+ Swig_symbol_setscope(nn->symtab);
+ SwigType_set_scope(nn->typescope);
+ Iterator t;
+ for (t = First(nn->normallist); t.item; t = Next(t)) {
+ normalize_type(t.item);
+ }
+ Delete(nn->normallist);
+ np = nn->next;
+ delete(nn);
+ nn = np;
+ }
+ Swig_symbol_setscope(currentsym);
+ }
+
+ /* generate C++ inheritance type-relationships */
+ void cplus_inherit_types_impl(Node *first, Node *cls, String *clsname, const char *bases, const char *baselist, int ispublic, String *cast = 0) {
+
+ if (first == cls)
+ return; /* The Marcelo check */
+ if (!cls)
+ cls = first;
+ List *alist = 0;
+ List *ilist = Getattr(cls, bases);
+ if (!ilist) {
+ List *nlist = Getattr(cls, baselist);
+ if (nlist) {
+ int len = Len(nlist);
+ int i;
+ for (i = 0; i < len; i++) {
+ Node *bcls = 0;
+ int clsforward = 0;
+ String *bname = Getitem(nlist, i);
+ String *sname = bname;
+ String *tname = 0;
+
+ /* Try to locate the base class. We look in the symbol table and we chase
+ typedef declarations to get to the base class if necessary */
+ Symtab *st = Getattr(cls, "sym:symtab");
+
+ if (SwigType_istemplate(bname)) {
+ tname = SwigType_typedef_resolve_all(bname);
+ sname = tname;
+ }
+ while (1) {
+ String *qsname = SwigType_typedef_qualified(sname);
+ bcls = Swig_symbol_clookup(qsname, st);
+ Delete(qsname);
+ if (bcls) {
+ if (Strcmp(nodeType(bcls), "class") != 0) {
+ /* Not a class. The symbol could be a typedef. */
+ if (checkAttribute(bcls, "storage", "typedef")) {
+ SwigType *decl = Getattr(bcls, "decl");
+ if (!decl || !(Len(decl))) {
+ sname = Getattr(bcls, "type");
+ st = Getattr(bcls, "sym:symtab");
+ if (SwigType_istemplate(sname)) {
+ if (tname)
+ Delete(tname);
+ tname = SwigType_typedef_resolve_all(sname);
+ sname = tname;
+ }
+ 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 {
+ if (!GetFlag(bcls, "feature:ignore")) {
+ 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));
+ Swig_error(Getfile(bcls), Getline(bcls), "See definition of '%s'.\n", SwigType_namestr(bname));
+ } else {
+ Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bname), Getline(bname), "Base class '%s' is incomplete.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bcls), Getline(bcls), "Only forward declaration '%s' was found.\n", SwigType_namestr(bname));
+ clsforward = 1;
+ }
+ bcls = 0;
+ } else {
+ if (Getattr(bcls, "typepass:visit")) {
+ if (!Getattr(bcls, "feature:onlychildren")) {
+ if (!ilist)
+ ilist = alist = NewList();
+ Append(ilist, bcls);
+ } else {
+ if (!GetFlag(bcls, "feature:ignore")) {
+ 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));
+ }
+ }
+ } else {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname));
+ }
+ }
+ }
+ break;
+ }
+
+ if (tname)
+ Delete(tname);
+ if (!bcls) {
+ if (!clsforward && !GetFlag(cls, "feature:ignore")) {
+ if (ispublic && !Getmeta(bname, "already_warned")) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
+ if (Strchr(bname, '<')) {
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Maybe you forgot to instantiate '%s' using %%template.\n", SwigType_namestr(bname));
+ }
+ Setmeta(bname, "already_warned", "1");
+ }
+ }
+ SwigType_inherit(clsname, bname, cast, 0);
+ }
+ }
+ }
+ if (ilist) {
+ Setattr(cls, bases, ilist);
+ }
+ }
+ if (alist)
+ Delete(alist);
+
+ if (!ilist)
+ return;
+ int len = Len(ilist);
+ int i;
+ for (i = 0; i < len; i++) {
+ Node *bclass = Getitem(ilist, i);
+ SwigType *bname = Getattr(bclass, "name");
+ Hash *scopes = Getattr(bclass, "typescope");
+ SwigType_inherit(clsname, bname, cast, 0);
+ if (ispublic && !GetFlag(bclass, "feature:ignore")) {
+ String *smart = Getattr(first, "smart");
+ if (smart) {
+ /* Record a (fake) inheritance relationship between smart pointer
+ and smart pointer to base class, so that smart pointer upcasts
+ are automatically generated. */
+ SwigType *bsmart = Getattr(bclass, "smart");
+ if (bsmart) {
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(bsmart);
+
+ /* construct casting code */
+ String *convcode = NewStringf("\n *newmemory = SWIG_CAST_NEW_MEMORY;\n return (void *) new %s(*(%s *)$from);\n", bsmartnamestr, smartnamestr);
+
+ /* setup inheritance relationship between smart pointer templates */
+ SwigType_inherit(smart, bsmart, 0, convcode);
+
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ Delete(convcode);
+ } else {
+ Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name")));
+ }
+ } else {
+ if (GetFlag(bclass, "smart"))
+ if (!GetFlag(first, "feature:ignore"))
+ Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Derived class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(first, "name")), SwigType_namestr(Getattr(bclass, "name")));
+ }
+ }
+ if (!importmode) {
+ String *btype = Copy(bname);
+ SwigType_add_pointer(btype);
+ SwigType_remember(btype);
+ Delete(btype);
+ }
+ if (scopes) {
+ SwigType_inherit_scope(scopes);
+ }
+ /* Set up inheritance in the symbol table */
+ Symtab *st = Getattr(cls, "symtab");
+ Symtab *bst = Getattr(bclass, "symtab");
+ if (st == bst) {
+ Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", SwigType_namestr(Getattr(cls, "name")));
+ continue;
+ }
+ Symtab *s = Swig_symbol_current();
+ Swig_symbol_setscope(st);
+ Swig_symbol_inherit(bst);
+ Swig_symbol_setscope(s);
+
+ /* Recursively hit base classes */
+ String *namestr = SwigType_namestr(Getattr(bclass, "name"));
+ String *newcast = NewStringf("(%s *)%s", namestr, cast);
+ Delete(namestr);
+ cplus_inherit_types_impl(first, bclass, clsname, bases, baselist, ispublic, newcast);
+ Delete(newcast);
+ }
+ }
+
+ void append_list(List *lb, List *la) {
+ if (la && lb) {
+ for (Iterator bi = First(la); bi.item; bi = Next(bi)) {
+ Append(lb, bi.item);
+ }
+ }
+ }
+
+ void cplus_inherit_types(Node *first, Node *cls, String *clsname, String *cast = 0) {
+ cplus_inherit_types_impl(first, cls, clsname, "bases", "baselist", 1, cast);
+ cplus_inherit_types_impl(first, cls, clsname, "protectedbases", "protectedbaselist", 0, cast);
+ cplus_inherit_types_impl(first, cls, clsname, "privatebases", "privatebaselist", 0, cast);
+
+ if (!cls)
+ cls = first;
+
+ List *allbases = NewList();
+ append_list(allbases, Getattr(cls, "bases"));
+ append_list(allbases, Getattr(cls, "protectedbases"));
+ append_list(allbases, Getattr(cls, "privatebases"));
+ if (Len(allbases)) {
+ Setattr(cls, "allbases", allbases);
+ }
+ Delete(allbases);
+ }
+
+ /* ------------------------------------------------------------
+ * nspace_setting()
+ *
+ * Configures "sym:nspace" on the node and returns an overridden
+ * nspace value when %nspacemove is used.
+ * outer should point to parent class.
+ * ------------------------------------------------------------ */
+
+ String *nspace_setting(Node *n, Node *outer) {
+ String *nssymname_new = nssymname;
+ String *feature_nspace = GetFlagAttr(n, "feature:nspace");
+ String *nspace = Copy(feature_nspace);
+
+ // Check validity - single colons not allowed
+ const char *c = Char(feature_nspace);
+ int valid = 1;
+ while(c && *c) {
+ if (*(c++) == ':' && *(c++) != ':') {
+ valid = 0;
+ break;
+ }
+ }
+
+ // Remove whitespace
+ Replaceall(nspace, " ", "");
+ Replaceall(nspace, "\t", "");
+
+ valid = valid && (feature_nspace ? Equal(feature_nspace, "1") || Swig_scopename_isvalid(nspace) : 1);
+ Replaceall(nspace, "::", ".");
+ if (valid) {
+ if (outer) {
+ // Nested class or enum in a class
+ String *outer_nspace = Getattr(outer, "sym:nspace");
+ String *nspace_attribute = Getattr(n, "feature:nspace");
+ bool warn = false;
+ if (outer_nspace) {
+ if (Equal(nspace_attribute, "0")) {
+ warn = true;
+ } else if (nspace && !(Equal(nspace, "1") || Equal(nspace, outer_nspace))) {
+ warn = true;
+ }
+ } else if (nspace) {
+ warn = true;
+ }
+ if (warn) {
+ String *outer_nspace_feature = Copy(outer_nspace);
+ Replaceall(outer_nspace_feature, ".", "::");
+ Swig_warning(WARN_TYPE_NSPACE_SETTING, Getfile(n), Getline(n), "Ignoring nspace setting (%s) for '%s',\n", nspace_attribute, Swig_name_decl(n));
+ Swig_warning(WARN_TYPE_NSPACE_SETTING, Getfile(outer), Getline(outer), "as it conflicts with the nspace setting (%s) for outer class '%s'.\n", outer_nspace_feature, Swig_name_decl(outer));
+ }
+ Setattr(n, "sym:nspace", outer_nspace);
+ } else {
+ if (nspace) {
+ if (Equal(nspace, "1")) {
+ if (nssymname)
+ Setattr(n, "sym:nspace", nssymname);
+ } else {
+ Setattr(n, "sym:nspace", nspace);
+ nssymname_new = nspace;
+ }
+ }
+ }
+ } else {
+ Swig_error(Getfile(n), Getline(n), "'%s' is not a valid identifier for nspace.\n", feature_nspace);
+ }
+ Delete(nspace);
+ return nssymname_new;
+ }
+
+ /* ------------------------------------------------------------
+ * top()
+ * ------------------------------------------------------------ */
+
+ virtual int top(Node *n) {
+ importmode = 0;
+ module = Getattr(n, "module");
+ inclass = 0;
+ normalize = 0;
+ nsname = 0;
+ nssymname = 0;
+ classhash = Getattr(n, "classes");
+ emit_children(n);
+ normalize_list();
+ SwigType_set_scope(0);
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * moduleDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int moduleDirective(Node *n) {
+ if (!module) {
+ module = n;
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * importDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int importDirective(Node *n) {
+ String *oldmodule = module;
+ int oldimport = importmode;
+ importmode = 1;
+ module = 0;
+ emit_children(n);
+ importmode = oldimport;
+ module = oldmodule;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * includeDirective()
+ * externDirective()
+ * extendDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int includeDirective(Node *n) {
+ return emit_children(n);
+ }
+ virtual int externDeclaration(Node *n) {
+ return emit_children(n);
+ }
+ virtual int extendDirective(Node *n) {
+ return emit_children(n);
+ }
+
+ /* ------------------------------------------------------------
+ * classDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *tdname = Getattr(n, "tdname");
+ String *unnamed = Getattr(n, "unnamed");
+ String *storage = Getattr(n, "storage");
+ String *kind = Getattr(n, "kind");
+ save_value<Node*> oldinclass(inclass);
+ List *olist = normalize;
+ Symtab *symtab;
+ String *nname = 0;
+ String *fname = 0;
+ String *scopename = 0;
+ String *template_default_expanded = 0;
+
+ normalize = NewList();
+
+ if (name) {
+ if (SwigType_istemplate(name)) {
+ // We need to fully resolve the name and expand default template parameters to make templates work correctly */
+ Node *cn;
+ SwigType *resolved_name = SwigType_typedef_resolve_all(name);
+ SwigType *deftype_name = Swig_symbol_template_deftype(resolved_name, 0);
+ fname = Copy(resolved_name);
+ if (!Equal(resolved_name, deftype_name))
+ template_default_expanded = Copy(deftype_name);
+ if (!Equal(fname, name) && (cn = Swig_symbol_clookup_local(fname, 0))) {
+ if ((n == cn)
+ || (Strcmp(nodeType(cn), "template") == 0)
+ || (Getattr(cn, "feature:onlychildren") != 0)
+ || (Getattr(n, "feature:onlychildren") != 0)) {
+ Swig_symbol_cadd(fname, n);
+ if (template_default_expanded)
+ Swig_symbol_cadd(template_default_expanded, n);
+ SwigType_typedef_class(fname);
+ scopename = Copy(fname);
+ } else {
+ // Arguably the parser should instead ignore these duplicate template instantiations, in particular for ensuring the first parsed instantiation is used
+ SetFlag(n, "feature:ignore");
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(n), Getline(n), "Duplicate template instantiation of '%s' with name '%s' ignored,\n", SwigType_namestr(name), Getattr(n, "sym:name"));
+ Swig_warning(WARN_TYPE_REDEFINED, Getfile(cn), Getline(cn), "previous instantiation of '%s' with name '%s'.\n", SwigType_namestr(Getattr(cn, "name")), Getattr(cn, "sym:name"));
+ scopename = 0;
+ }
+ } else {
+ Swig_symbol_cadd(fname, n);
+ SwigType_typedef_class(fname);
+ scopename = Copy(fname);
+ }
+ Delete(deftype_name);
+ Delete(resolved_name);
+ } else {
+ if ((CPlusPlus) || (unnamed)) {
+ SwigType_typedef_class(name);
+ } else {
+ SwigType_typedef_class(NewStringf("%s %s", kind, name));
+ }
+ scopename = Copy(name);
+ }
+ } else {
+ scopename = 0;
+ }
+
+ Setattr(n, "typepass:visit", "1");
+
+ /* Need to set up a typedef if unnamed */
+ if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
+ SwigType_typedef(unnamed, tdname);
+ }
+ // name of the outer class should already be patched to contain its 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);
+ String *tdname = Getattr(n, "tdname");
+ if (tdname) {
+ tdname = NewStringf("%s::%s", nsname, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+ }
+
+ String *oldnssymname = nssymname;
+ nssymname = nspace_setting(n, Getattr(n, "nested:outer"));
+
+ SwigType_new_scope(scopename);
+ SwigType_attach_symtab(Getattr(n, "symtab"));
+
+ if (!GetFlag(n, "feature:ignore")) {
+ SwigType *smart = Swig_cparse_smartptr(n);
+ if (smart) {
+ // Resolve the type in 'feature:smartptr' in the scope of the class it is attached to
+ normalize_type(smart);
+ Setattr(n, "smart", smart);
+ Delete(smart);
+ }
+ }
+
+ /* Inherit type definitions into the class */
+ if (name && !(GetFlag(n, "nested") && !checkAttribute(n, "access", "public") &&
+ (GetFlag(n, "feature:flatnested") || Language::instance()->nestedClassesSupport() == Language::NCS_None))) {
+ cplus_inherit_types(n, 0, nname ? nname : (fname ? fname : name));
+ }
+
+ inclass = n;
+ symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
+ emit_children(n);
+ Swig_symbol_setscope(symtab);
+
+ Hash *ts = SwigType_pop_scope();
+ Setattr(n, "typescope", ts);
+ Delete(ts);
+ Setattr(n, "module", module);
+
+ // When a fully qualified templated type with default parameters is used in the parsed code,
+ // the following additional symbols and scopes are needed for successful lookups
+ if (template_default_expanded) {
+ Swig_symbol_alias(template_default_expanded, Getattr(n, "symtab"));
+ SwigType_scope_alias(template_default_expanded, Getattr(n, "typescope"));
+ }
+
+ nssymname = oldnssymname;
+
+ /* Normalize deferred types */
+ {
+ normal_node *nn = new normal_node();
+ nn->normallist = normalize;
+ nn->symtab = Getattr(n, "symtab");
+ nn->next = patch_list;
+ nn->typescope = Getattr(n, "typescope");
+ patch_list = nn;
+ }
+
+ normalize = olist;
+
+ /* If in a namespace, patch the class name */
+ if (nname) {
+ Setattr(n, "name", nname);
+ Delete(nname);
+ }
+ Delete(fname);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * templateDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int templateDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *ttype = Getattr(n, "templatetype");
+ if (Strcmp(ttype, "class") == 0) {
+ String *rname = SwigType_typedef_resolve_all(name);
+ SwigType_typedef_class(rname);
+ Delete(rname);
+ } else if (Strcmp(ttype, "classforward") == 0) {
+ String *rname = SwigType_typedef_resolve_all(name);
+ SwigType_typedef_class(rname);
+ Delete(rname);
+ /* SwigType_typedef_class(name); */
+ } else if (Strcmp(ttype, "cdecl") == 0) {
+ String *rname = SwigType_typedef_resolve_all(name);
+ SwigType_typedef_class(rname);
+ Delete(rname);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * lambdaDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int lambdaDeclaration(Node *) {
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * classforwardDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int classforwardDeclaration(Node *n) {
+
+ /* Can't do inside a C struct because it breaks C nested structure wrapping */
+ if ((!inclass) || (CPlusPlus)) {
+ String *name = Getattr(n, "name");
+ SwigType_typedef_class(name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * namespaceDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int namespaceDeclaration(Node *n) {
+ Symtab *symtab;
+ String *name = Getattr(n, "name");
+ String *alias = Getattr(n, "alias");
+ List *olist = normalize;
+ normalize = NewList();
+ if (alias) {
+ Typetab *ts = Getattr(n, "typescope");
+ if (!ts) {
+ /* Create an empty scope for the alias */
+ Node *ns = Getattr(n, "namespace");
+ SwigType_scope_alias(name, Getattr(ns, "typescope"));
+ ts = Getattr(ns, "typescope");
+ Setattr(n, "typescope", ts);
+ }
+ /* Namespace alias */
+ return SWIG_OK;
+ } else {
+ if (name) {
+ Node *nn = Swig_symbol_clookup(name, n);
+ Hash *ts = 0;
+ if (nn)
+ ts = Getattr(nn, "typescope");
+ if (!ts) {
+ SwigType_new_scope(name);
+ SwigType_attach_symtab(Getattr(n, "symtab"));
+ } else {
+ SwigType_set_scope(ts);
+ }
+ }
+ String *oldnsname = nsname;
+ String *oldnssymname = nssymname;
+ nsname = Swig_symbol_qualified(Getattr(n, "symtab"));
+ nssymname = Swig_symbol_qualified_language_scopename(Getattr(n, "symtab"));
+ symtab = Swig_symbol_setscope(Getattr(n, "symtab"));
+ emit_children(n);
+ Swig_symbol_setscope(symtab);
+
+ if (name) {
+ Hash *ts = SwigType_pop_scope();
+ Setattr(n, "typescope", ts);
+ Delete(ts);
+ }
+
+ /* Normalize deferred types */
+ {
+ normal_node *nn = new normal_node();
+ nn->normallist = normalize;
+ nn->symtab = Getattr(n, "symtab");
+ nn->next = patch_list;
+ nn->typescope = Getattr(n, "typescope");
+ patch_list = nn;
+ }
+ normalize = olist;
+
+ Delete(nssymname);
+ nssymname = oldnssymname;
+ Delete(nsname);
+ nsname = oldnsname;
+ return SWIG_OK;
+ }
+ }
+
+ /* ------------------------------------------------------------
+ * cDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int cDeclaration(Node *n) {
+ if (NoExcept) {
+ Delattr(n, "throws");
+ }
+
+ /* Normalize types. */
+ SwigType *ty = Getattr(n, "type");
+ if (!ty) {
+ return SWIG_OK;
+ }
+ normalize_type(ty);
+ SwigType *decl = Getattr(n, "decl");
+ if (decl) {
+ normalize_type(decl);
+ }
+ normalize_parms(Getattr(n, "parms"));
+ normalize_parms(Getattr(n, "throws"));
+ 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);
+ Clear(name);
+ Append(name, qualifiedname);
+ Delete(qualifiedname);
+ }
+
+ if (checkAttribute(n, "storage", "typedef")) {
+ String *name = Getattr(n, "name");
+ ty = Getattr(n, "type");
+ decl = Getattr(n, "decl");
+ SwigType *t = Copy(ty);
+ {
+ /* If the typename is qualified, make sure the scopename is fully qualified when making a typedef */
+ if (Swig_scopename_check(t) && strncmp(Char(t), "::", 2)) {
+ String *base, *prefix, *qprefix;
+ base = Swig_scopename_last(t);
+ prefix = Swig_scopename_prefix(t);
+ qprefix = SwigType_typedef_qualified(prefix);
+ Delete(t);
+ t = NewStringf("%s::%s", qprefix, base);
+ Delete(base);
+ Delete(prefix);
+ Delete(qprefix);
+ }
+ }
+ SwigType_push(t, decl);
+ if (CPlusPlus) {
+ Replaceall(t, "struct ", "");
+ Replaceall(t, "union ", "");
+ Replaceall(t, "class ", "");
+ }
+ SwigType_typedef(t, name);
+ }
+ /* If namespaces are active. We need to patch the name with a namespace prefix */
+ if (nsname && !inclass) {
+ String *name = Getattr(n, "name");
+ if (name) {
+ String *nname = NewStringf("%s::%s", nsname, name);
+ Setattr(n, "name", nname);
+ Delete(nname);
+ }
+ }
+ clean_overloaded(n);
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * constructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int constructorDeclaration(Node *n) {
+ if (NoExcept) {
+ Delattr(n, "throws");
+ }
+
+ normalize_parms(Getattr(n, "parms"));
+ normalize_parms(Getattr(n, "throws"));
+
+ clean_overloaded(n);
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * destructorDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int destructorDeclaration(Node *) {
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * constantDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int constantDirective(Node *n) {
+ SwigType *ty = Getattr(n, "type");
+ if (ty) {
+ Setattr(n, "type", SwigType_typedef_qualified(ty));
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * enumDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+
+ if (name) {
+ String *scope = 0;
+
+ // Add a typedef to the type table so that we can use 'enum Name' as well as just 'Name'
+ if (nsname || inclass) {
+
+ // But first correct the name and tdname to contain the fully qualified scopename
+ if (nsname && inclass) {
+ scope = NewStringf("%s::%s", nsname, Getattr(inclass, "name"));
+ } else if (nsname) {
+ scope = NewStringf("%s", nsname);
+ } else if (inclass) {
+ scope = NewStringf("%s", Getattr(inclass, "name"));
+ }
+
+ String *nname = NewStringf("%s::%s", scope, name);
+ Setattr(n, "name", nname);
+
+ String *tdname = Getattr(n, "tdname");
+ if (tdname) {
+ tdname = NewStringf("%s::%s", scope, tdname);
+ Setattr(n, "tdname", tdname);
+ }
+
+ SwigType *t = NewStringf("enum %s", nname);
+ SwigType_typedef(t, name);
+ } else {
+ SwigType *t = NewStringf("enum %s", name);
+ SwigType_typedef(t, name);
+ }
+ Delete(scope);
+ }
+
+ String *tdname = Getattr(n, "tdname");
+ String *unnamed = Getattr(n, "unnamed");
+ String *storage = Getattr(n, "storage");
+
+ // Construct enumtype - for declaring an enum of this type with SwigType_ltype() etc
+ String *enumtype = 0;
+ if (unnamed && tdname && (Cmp(storage, "typedef") == 0)) {
+ enumtype = Copy(Getattr(n, "tdname"));
+ } else if (name) {
+ enumtype = NewStringf("%s%s", CPlusPlus ? "" : "enum ", Getattr(n, "name"));
+ } else {
+ // anonymous enums
+ enumtype = Copy(Getattr(n, "type"));
+ }
+ Setattr(n, "enumtype", enumtype);
+
+ String *oldnssymname = nssymname;
+ Node *parent = parentNode(n);
+ nssymname = nspace_setting(n, parent && Equal(nodeType(parent), "class") ? parent : NULL);
+
+ // This block of code is for dealing with %ignore on an enum item where the target language
+ // attempts to use the C enum value in the target language itself and expects the previous enum value
+ // to be one more than the previous value... the previous enum item might not exist if it is ignored!
+ // - It sets the first non-ignored enum item with the "firstenumitem" attribute.
+ // - It adds an enumvalue attribute if the previous enum item is ignored
+ {
+ Node *c;
+ int count = 0;
+ String *previous = 0;
+ bool previous_ignored = false;
+ bool firstenumitem = false;
+ for (c = firstChild(n); c; c = nextSibling(c)) {
+ assert(strcmp(Char(nodeType(c)), "enumitem") == 0);
+
+ bool reset;
+ String *enumvalue = Getattr(c, "enumvalue");
+ if (GetFlag(c, "feature:ignore") || !Getattr(c, "sym:name")) {
+ reset = enumvalue ? true : false;
+ previous_ignored = true;
+ } else {
+ if (!enumvalue && previous_ignored) {
+ if (previous)
+ Setattr(c, "enumvalue", NewStringf("(%s) + %d", previous, count+1));
+ else
+ Setattr(c, "enumvalue", NewStringf("%d", count));
+ SetFlag(c, "virtenumvalue"); // identify enumvalue as virtual, ie not from the parsed source
+ }
+ if (!firstenumitem) {
+ SetFlag(c, "firstenumitem");
+ firstenumitem = true;
+ }
+ reset = true;
+ previous_ignored = false;
+ }
+ if (reset) {
+ previous = enumvalue ? enumvalue : Getattr(c, "name");
+ count = 0;
+ } else {
+ count++;
+ }
+ }
+ }
+
+ emit_children(n);
+
+ nssymname = oldnssymname;
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumvalueDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumvalueDeclaration(Node *n) {
+ String *name = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+ String *scopedenum = Getattr(parentNode(n), "scopedenum");
+ if (!value)
+ value = name;
+ if (Strcmp(value, name) == 0) {
+ String *new_value;
+ if ((nsname || inclass || scopedenum) && cparse_cplusplus) {
+ new_value = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
+ } else {
+ new_value = NewString(value);
+ }
+ if ((nsname || inclass || scopedenum) && !cparse_cplusplus) {
+ String *cppvalue = NewStringf("%s::%s", SwigType_namestr(Swig_symbol_qualified(n)), value);
+ Setattr(n, "cppvalue", cppvalue); /* for target languages that always generate C++ code even when wrapping C code */
+ }
+ Setattr(n, "value", new_value);
+ Delete(new_value);
+ }
+ Node *next = nextSibling(n);
+
+ // Make up an enumvalue if one was not specified in the parsed code (not designed to be used on enum items and %ignore - enumvalue will be set instead)
+ if (!GetFlag(n, "feature:ignore")) {
+ if (Getattr(n, "_last") && !Getattr(n, "enumvalue")) { // Only the first enum item has _last set (Note: first non-ignored enum item has firstenumitem set)
+ Setattr(n, "enumvalueex", "0");
+ }
+ if (next && !Getattr(next, "enumvalue")) {
+ Setattr(next, "enumvalueex", NewStringf("%s + 1", Getattr(n, "sym:name")));
+ }
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * enumforwardDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int enumforwardDeclaration(Node *n) {
+
+ // Use enumDeclaration() to do all the hard work.
+ // Note that no children can be emitted in a forward declaration as there aren't any.
+ int result = enumDeclaration(n);
+ if (result == SWIG_OK) {
+ // Detect when the real enum matching the forward enum declaration has not been parsed/declared
+ SwigType *ty = SwigType_typedef_resolve_all(Getattr(n, "type"));
+ Replaceall(ty, "enum ", "");
+ Node *nn = Swig_symbol_clookup(ty, 0);
+
+ String *nodetype = nn ? nodeType(nn) : 0;
+ if (nodetype) {
+ if (Equal(nodetype, "enumforward")) {
+ SetFlag(nn, "enumMissing");
+ } // if a real enum was declared this would be an "enum" node type
+ }
+ Delete(ty);
+ }
+ return result;
+ }
+
+#ifdef DEBUG_OVERLOADED
+ static void show_overloaded(Node *n) {
+ Node *c = Getattr(n, "sym:overloaded");
+ Node *checkoverloaded = c;
+ Printf(stdout, "-------------------- overloaded start %s sym:overloaded():%p -------------------------------\n", Getattr(n, "name"), c);
+ while (c) {
+ if (Getattr(c, "error")) {
+ c = Getattr(c, "sym:nextSibling");
+ continue;
+ }
+ if (Getattr(c, "sym:overloaded") != checkoverloaded) {
+ Printf(stdout, "sym:overloaded error c:%p checkoverloaded:%p\n", c, checkoverloaded);
+ Swig_print_node(c);
+ Exit(EXIT_FAILURE);
+ }
+
+ String *decl = Strcmp(nodeType(c), "using") == 0 ? NewString("------") : Getattr(c, "decl");
+ Printf(stdout, " show_overloaded %s::%s(%s) [%s] nodeType:%s\n", parentNode(c) ? Getattr(parentNode(c), "name") : "NOPARENT", Getattr(c, "name"), decl, Getattr(c, "sym:overname"), nodeType(c));
+ if (!Getattr(c, "sym:overloaded")) {
+ Printf(stdout, "sym:overloaded error.....%p\n", c);
+ Swig_print_node(c);
+ Exit(EXIT_FAILURE);
+ }
+ c = Getattr(c, "sym:nextSibling");
+ }
+ Printf(stdout, "-------------------- overloaded end %s -------------------------------\n", Getattr(n, "name"));
+ }
+#endif
+
+ /* ------------------------------------------------------------
+ * usingDeclaration()
+ * ------------------------------------------------------------ */
+
+ virtual int usingDeclaration(Node *n) {
+ if (Getattr(n, "namespace")) {
+ /* using namespace id */
+
+ /* For a namespace import. We set up inheritance in the type system */
+ Node *ns = Getattr(n, "node");
+ if (ns) {
+ Typetab *ts = Getattr(ns, "typescope");
+ if (ts) {
+ SwigType_using_scope(ts);
+ }
+ }
+ return SWIG_OK;
+ } else {
+ Node *ns;
+ /* using id */
+ Symtab *stab = Getattr(n, "sym:symtab");
+ if (stab) {
+ String *uname = Getattr(n, "uname");
+ ns = Swig_symbol_clookup(uname, stab);
+ if (!ns && SwigType_istemplate(uname)) {
+ String *tmp = Swig_symbol_template_deftype(uname, 0);
+ if (!Equal(tmp, uname)) {
+ ns = Swig_symbol_clookup(tmp, stab);
+ }
+ Delete(tmp);
+ }
+ } else {
+ ns = 0;
+ }
+ // Note that Allocate::usingDeclaration will warn when using member is not found (when ns is zero)
+ if (ns) {
+ /* Only a single symbol is being used. There are only a few symbols that
+ we actually care about. These are typedef, class declarations, and enum */
+ String *ntype = nodeType(ns);
+ if (Equal(ntype, "cdecl") || Equal(ntype, "constructor")) {
+ if (checkAttribute(ns, "storage", "typedef")) {
+ /* A typedef declaration */
+ String *uname = Getattr(n, "uname");
+ SwigType_typedef_using(uname);
+ }
+ } else if ((Strcmp(ntype, "class") == 0) || ((Strcmp(ntype, "classforward") == 0))) {
+ /* We install the using class name as kind of a typedef back to the original class */
+ String *uname = Getattr(n, "uname");
+ /* Import into current type scope */
+ SwigType_typedef_using(uname);
+ } else if (Strcmp(ntype, "enum") == 0) {
+ SwigType_typedef_using(Getattr(n, "uname"));
+ } else if (Strcmp(ntype, "template") == 0) {
+ SwigType_typedef_using(Getattr(n, "uname"));
+ }
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * typemapDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int typemapDirective(Node *n) {
+ if (inclass || nsname) {
+ Node *items = firstChild(n);
+ while (items) {
+ Parm *pattern = Getattr(items, "pattern");
+ Parm *parms = Getattr(items, "parms");
+ normalize_later(pattern);
+ normalize_later(parms);
+ items = nextSibling(items);
+ }
+ }
+ return SWIG_OK;
+ }
+
+
+ /* ------------------------------------------------------------
+ * typemapcopyDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int typemapcopyDirective(Node *n) {
+ if (inclass || nsname) {
+ Node *items = firstChild(n);
+ ParmList *pattern = Getattr(n, "pattern");
+ normalize_later(pattern);
+ while (items) {
+ ParmList *npattern = Getattr(items, "pattern");
+ normalize_later(npattern);
+ items = nextSibling(items);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * applyDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int applyDirective(Node *n) {
+ if (inclass || nsname) {
+ ParmList *pattern = Getattr(n, "pattern");
+ normalize_later(pattern);
+ Node *items = firstChild(n);
+ while (items) {
+ Parm *apattern = Getattr(items, "pattern");
+ normalize_later(apattern);
+ items = nextSibling(items);
+ }
+ }
+ return SWIG_OK;
+ }
+
+ /* ------------------------------------------------------------
+ * clearDirective()
+ * ------------------------------------------------------------ */
+
+ virtual int clearDirective(Node *n) {
+ if (inclass || nsname) {
+ Node *p;
+ for (p = firstChild(n); p; p = nextSibling(p)) {
+ ParmList *pattern = Getattr(p, "pattern");
+ normalize_later(pattern);
+ }
+ }
+ return SWIG_OK;
+ }
+
+public:
+ static void pass(Node *n) {
+ TypePass t;
+ t.top(n);
+ }
+};
+
+void Swig_process_types(Node *n) {
+ if (!n)
+ return;
+ TypePass::pass(n);
+}
+
diff --git a/contrib/tools/swig/Source/Modules/utils.cxx b/contrib/tools/swig/Source/Modules/utils.cxx
new file mode 100644
index 00000000000..2d956c4c86e
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/utils.cxx
@@ -0,0 +1,226 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * utils.cxx
+ *
+ * Various utility functions.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+int is_public(Node *n) {
+ String *access = Getattr(n, "access");
+ return !access || !Cmp(access, "public");
+}
+
+int is_private(Node *n) {
+ String *access = Getattr(n, "access");
+ return access && !Cmp(access, "private");
+}
+
+int is_protected(Node *n) {
+ String *access = Getattr(n, "access");
+ return access && !Cmp(access, "protected");
+}
+
+static int is_member_director_helper(Node *parentnode, Node *member) {
+ int parent_nodirector = GetFlag(parentnode, "feature:nodirector");
+ if (parent_nodirector)
+ return 0;
+ int parent_director = Swig_director_mode() && GetFlag(parentnode, "feature:director");
+ int cdecl_director = parent_director || GetFlag(member, "feature:director");
+ int cdecl_nodirector = GetFlag(member, "feature:nodirector");
+ return cdecl_director && !cdecl_nodirector && !GetFlag(member, "feature:extend");
+}
+
+int is_member_director(Node *parentnode, Node *member) {
+ if (parentnode && checkAttribute(member, "storage", "virtual")) {
+ return is_member_director_helper(parentnode, member);
+ } else {
+ return 0;
+ }
+}
+
+int is_member_director(Node *member) {
+ return is_member_director(Getattr(member, "parentNode"), member);
+}
+
+// Identifies the additional 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.
+int is_non_virtual_protected_access(Node *n) {
+ int result = 0;
+ if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode() && is_protected(n) && !checkAttribute(n, "storage", "virtual")) {
+ Node *parentNode = Getattr(n, "parentNode");
+ // When vtable is empty, the director class does not get emitted, so a check for an empty vtable should be done.
+ // However, vtable is set in Language and so is not yet set when methods in Typepass call clean_overloaded()
+ // which calls is_non_virtual_protected_access. So commented out below.
+ // Moving the director vtable creation into Typepass should solve this problem.
+ if (is_member_director_helper(parentNode, n) /* && Getattr(parentNode, "vtable")*/)
+ result = 1;
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * clean_overloaded()
+ *
+ * Clean overloaded list. Removes templates, ignored, and errors.
+ * ----------------------------------------------------------------------------- */
+
+void clean_overloaded(Node *n) {
+ Node *nn = Getattr(n, "sym:overloaded");
+ Node *first = 0;
+ while (nn) {
+ String *ntype = nodeType(nn);
+ if ((GetFlag(nn, "feature:ignore")) ||
+ (Getattr(nn, "error")) ||
+ (Strcmp(ntype, "template") == 0) ||
+ ((Strcmp(ntype, "cdecl") == 0) && is_protected(nn) && !is_member_director(nn) && !is_non_virtual_protected_access(n))) {
+ /* Remove from overloaded list */
+ Node *ps = Getattr(nn, "sym:previousSibling");
+ Node *ns = Getattr(nn, "sym:nextSibling");
+ if (ps) {
+ Setattr(ps, "sym:nextSibling", ns);
+ }
+ if (ns) {
+ Setattr(ns, "sym:previousSibling", ps);
+ }
+ Delattr(nn, "sym:previousSibling");
+ Delattr(nn, "sym:nextSibling");
+ Delattr(nn, "sym:overloaded");
+ Delattr(nn, "sym:overname");
+ nn = ns;
+ continue;
+ } else {
+ if (!first)
+ first = nn;
+ Setattr(nn, "sym:overloaded", first);
+ }
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ if (!first || (first && !Getattr(first, "sym:nextSibling"))) {
+ if (Getattr(n, "sym:overloaded"))
+ Delattr(n, "sym:overloaded");
+ }
+
+ Swig_symbol_fix_overname(Getattr(n, "sym:overloaded"));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_set_max_hash_expand()
+ *
+ * Controls how many Hash objects are displayed when displaying nested Hash objects.
+ * Makes DohSetMaxHashExpand an externally callable function (for debugger).
+ * ----------------------------------------------------------------------------- */
+
+void Swig_set_max_hash_expand(int count) {
+ SetMaxHashExpand(count);
+}
+
+
+extern "C" {
+
+/* -----------------------------------------------------------------------------
+ * Swig_get_max_hash_expand()
+ *
+ * Returns how many Hash objects are displayed when displaying nested Hash objects.
+ * Makes DohGetMaxHashExpand an externally callable function (for debugger).
+ * ----------------------------------------------------------------------------- */
+
+int Swig_get_max_hash_expand() {
+ return GetMaxHashExpand();
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_doh_string()
+ *
+ * DOH version of Swig_to_string()
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_to_doh_string(DOH *object, int count) {
+ int old_count = Swig_get_max_hash_expand();
+ if (count >= 0)
+ Swig_set_max_hash_expand(count);
+
+ String *debug_string = object ? NewStringf("%s", object) : NewString("NULL");
+
+ Swig_set_max_hash_expand(old_count);
+ return debug_string;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_doh_string_with_location()
+ *
+ * DOH version of Swig_to_string_with_location()
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_to_doh_string_with_location(DOH *object, int count) {
+ int old_count = Swig_get_max_hash_expand();
+ if (count >= 0)
+ Swig_set_max_hash_expand(count);
+
+ String *debug_string = Swig_stringify_with_location(object);
+
+ Swig_set_max_hash_expand(old_count);
+ return debug_string;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string()
+ *
+ * Swig debug - return C string representation of any DOH type.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * Note: leaks memory.
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_to_string(DOH *object, int count) {
+ return Char(Swig_to_doh_string(object, count));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string_with_location()
+ *
+ * Swig debug - return C string representation of any DOH type, within [] brackets
+ * for Hash and List types, prefixed by line and file information.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * Note: leaks memory.
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_to_string_with_location(DOH *object, int count) {
+ return Char(Swig_to_doh_string_with_location(object, count));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print()
+ *
+ * Swig debug - display string representation of any DOH type.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print(DOH *object, int count) {
+ String *output = Swig_to_doh_string(object, count);
+ Printf(stdout, "%s\n", output);
+ Delete(output);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string_with_location()
+ *
+ * Swig debug - display string representation of any DOH type, within [] brackets
+ * for Hash and List types, prefixed by line and file information.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_with_location(DOH *object, int count) {
+ String *output = Swig_to_doh_string_with_location(object, count);
+ Printf(stdout, "%s\n", output);
+ Delete(output);
+}
+
+} // extern "C"
+
diff --git a/contrib/tools/swig/Source/Modules/xml.cxx b/contrib/tools/swig/Source/Modules/xml.cxx
new file mode 100644
index 00000000000..159b1e24dec
--- /dev/null
+++ b/contrib/tools/swig/Source/Modules/xml.cxx
@@ -0,0 +1,297 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * xml.cxx
+ *
+ * An Xml parse tree generator.
+ * ----------------------------------------------------------------------------- */
+
+#include "swigmod.h"
+
+static const char *usage = "\
+XML Options (available with -xml)\n\
+ -xmllite - More lightweight version of XML\n";
+
+static File *out = 0;
+static int xmllite = 0;
+
+
+class XML:public Language {
+public:
+
+ int indent_level;
+ long id;
+
+ XML() :indent_level(0) , id(0) {
+ }
+
+ ~XML() {
+ }
+
+ virtual void main(int argc, char *argv[]) {
+ for (int iX = 0; iX < argc; iX++) {
+ if (strcmp(argv[iX], "-help") == 0) {
+ fputs(usage, stdout);
+ }
+ if (strcmp(argv[iX], "-xmllite") == 0) {
+ Swig_mark_arg(iX);
+ xmllite = 1;
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGXML 1", 0);
+ }
+
+ /* Top of the parse tree */
+
+ virtual int top(Node *n) {
+ if (out == 0) {
+ String *outfile = Getattr(n, "outfile");
+ String *ext = Swig_file_extension(outfile);
+ // If there's an extension, ext will include the ".".
+ Delslice(outfile, Len(outfile) - Len(ext), DOH_END);
+ Delete(ext);
+ Append(outfile, ".xml");
+ out = NewFile(outfile, "w", SWIG_output_files());
+ if (!out) {
+ FileErrorDisplay(outfile);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ Printf(out, "<?xml version=\"1.0\" ?> \n");
+ Xml_print_tree(n);
+ return SWIG_OK;
+ }
+
+ void print_indent(int l) {
+ int i;
+ for (i = 0; i < indent_level; i++) {
+ Printf(out, " ");
+ }
+ if (l) {
+ Printf(out, " ");
+ }
+ }
+
+ void Xml_print_tree(DOH *obj) {
+ while (obj) {
+ Xml_print_node(obj);
+ obj = nextSibling(obj);
+ }
+ }
+
+ void Xml_print_attributes(Node *obj) {
+ String *k;
+ indent_level += 4;
+ print_indent(0);
+ Printf(out, "<attributelist id=\"%ld\" addr=\"%p\">\n", ++id, obj);
+ indent_level += 4;
+ Iterator ki;
+ ki = First(obj);
+ while (ki.key) {
+ k = ki.key;
+ if ((Cmp(k, "nodeType") == 0)
+ || (Cmp(k, "firstChild") == 0)
+ || (Cmp(k, "lastChild") == 0)
+ || (Cmp(k, "parentNode") == 0)
+ || (Cmp(k, "nextSibling") == 0)
+ || (Cmp(k, "previousSibling") == 0)
+ || (*(Char(k)) == '$')) {
+ /* Do nothing */
+ } else if (Cmp(k, "module") == 0) {
+ Xml_print_module(Getattr(obj, k));
+ } else if (Cmp(k, "baselist") == 0) {
+ Xml_print_baselist(Getattr(obj, k));
+ } else if (!xmllite && Cmp(k, "typescope") == 0) {
+ Xml_print_typescope(Getattr(obj, k));
+ } else if (!xmllite && Cmp(k, "typetab") == 0) {
+ Xml_print_typetab(Getattr(obj, k));
+ } else if (Cmp(k, "kwargs") == 0) {
+ Xml_print_kwargs(Getattr(obj, k));
+ } else if (Cmp(k, "parms") == 0 || Cmp(k, "pattern") == 0) {
+ Xml_print_parmlist(Getattr(obj, k));
+ } else if (Cmp(k, "catchlist") == 0 || Cmp(k, "templateparms") == 0) {
+ Xml_print_parmlist(Getattr(obj, k), Char(k));
+ } else {
+ DOH *o;
+ print_indent(0);
+ if (DohIsString(Getattr(obj, k))) {
+ String *ck = NewString(k);
+ o = Str(Getattr(obj, k));
+ Replaceall(ck, ":", "_");
+ Replaceall(ck, "<", "&lt;");
+ /* Do first to avoid aliasing errors. */
+ Replaceall(o, "&", "&amp;");
+ Replaceall(o, "<", "&lt;");
+ Replaceall(o, "\"", "&quot;");
+ Replaceall(o, "\\", "\\\\");
+ Replaceall(o, "\n", "&#10;");
+ Printf(out, "<attribute name=\"%s\" value=\"%s\" id=\"%ld\" addr=\"%p\" />\n", ck, o, ++id, o);
+ Delete(o);
+ Delete(ck);
+ } else {
+ o = Getattr(obj, k);
+ String *ck = NewString(k);
+ Replaceall(ck, ":", "_");
+ Printf(out, "<attribute name=\"%s\" value=\"%p\" id=\"%ld\" addr=\"%p\" />\n", ck, o, ++id, o);
+ Delete(ck);
+ }
+ }
+ ki = Next(ki);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</attributelist>\n");
+ indent_level -= 4;
+ }
+
+ void Xml_print_node(Node *obj) {
+ Node *cobj;
+
+ print_indent(0);
+ Printf(out, "<%s id=\"%ld\" addr=\"%p\">\n", nodeType(obj), ++id, obj);
+ Xml_print_attributes(obj);
+ cobj = firstChild(obj);
+ if (cobj) {
+ indent_level += 4;
+ Printf(out, "\n");
+ Xml_print_tree(cobj);
+ indent_level -= 4;
+ } else {
+ print_indent(1);
+ Printf(out, "\n");
+ }
+ print_indent(0);
+ Printf(out, "</%s>\n", nodeType(obj));
+ }
+
+
+ void Xml_print_parmlist(ParmList *p, const char* markup = "parmlist") {
+
+ print_indent(0);
+ Printf(out, "<%s id=\"%ld\" addr=\"%p\">\n", markup, ++id, p);
+ indent_level += 4;
+ while (p) {
+ print_indent(0);
+ Printf(out, "<parm id=\"%ld\">\n", ++id);
+ Xml_print_attributes(p);
+ print_indent(0);
+ Printf(out, "</parm>\n");
+ p = nextSibling(p);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</%s>\n", markup);
+ }
+
+ void Xml_print_baselist(List *p) {
+
+ print_indent(0);
+ Printf(out, "<baselist id=\"%ld\" addr=\"%p\">\n", ++id, p);
+ indent_level += 4;
+ Iterator s;
+ for (s = First(p); s.item; s = Next(s)) {
+ print_indent(0);
+ String *item_name = Xml_escape_string(s.item);
+ Printf(out, "<base name=\"%s\" id=\"%ld\" addr=\"%p\" />\n", item_name, ++id, s.item);
+ Delete(item_name);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</baselist>\n");
+ }
+
+ String *Xml_escape_string(String *str) {
+ String *escaped_str = 0;
+ if (str) {
+ escaped_str = NewString(str);
+ Replaceall(escaped_str, "&", "&amp;");
+ Replaceall(escaped_str, "<", "&lt;");
+ Replaceall(escaped_str, "\"", "&quot;");
+ Replaceall(escaped_str, "\\", "\\\\");
+ Replaceall(escaped_str, "\n", "&#10;");
+ }
+ return escaped_str;
+ }
+
+ void Xml_print_module(Node *p) {
+
+ print_indent(0);
+ Printf(out, "<attribute name=\"module\" value=\"%s\" id=\"%ld\" addr=\"%p\" />\n", Getattr(p, "name"), ++id, p);
+ }
+
+ void Xml_print_kwargs(Hash *p) {
+ Xml_print_hash(p, "kwargs");
+ }
+
+ void Xml_print_typescope(Hash *p) {
+
+ Xml_print_hash(p, "typescope");
+ }
+
+ void Xml_print_typetab(Hash *p) {
+
+ Xml_print_hash(p, "typetab");
+ }
+
+
+ void Xml_print_hash(Hash *p, const char *markup) {
+
+ print_indent(0);
+ Printf(out, "<%s id=\"%ld\" addr=\"%p\">\n", markup, ++id, p);
+ Xml_print_attributes(p);
+ indent_level += 4;
+ Iterator n = First(p);
+ while (n.key) {
+ print_indent(0);
+ Printf(out, "<%ssitem id=\"%ld\" addr=\"%p\">\n", markup, ++id, n.item);
+ Xml_print_attributes(n.item);
+ print_indent(0);
+ Printf(out, "</%ssitem>\n", markup);
+ n = Next(n);
+ }
+ indent_level -= 4;
+ print_indent(0);
+ Printf(out, "</%s>\n", markup);
+ }
+
+ NestedClassSupport nestedClassesSupport() const {
+ return NCS_Full;
+ }
+};
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_xml
+ *
+ * Dump an XML version of the parse tree. This is different from using the -xml
+ * language module normally as it allows the real language module to process the
+ * tree first, possibly stuffing in new attributes, so the XML that is output ends
+ * up being a post-processing version of the tree.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_xml(Node *obj, String *filename) {
+ XML xml;
+ xmllite = 1;
+
+ out = NewFile(filename, "w", SWIG_output_files());
+ if (!out) {
+ FileErrorDisplay(filename);
+ Exit(EXIT_FAILURE);
+ }
+
+ Printf(out, "<?xml version=\"1.0\" ?> \n");
+ xml.Xml_print_tree(obj);
+}
+
+static Language *new_swig_xml() {
+ return new XML();
+}
+extern "C" Language *swig_xml(void) {
+ return new_swig_xml();
+}
diff --git a/contrib/tools/swig/Source/Preprocessor/cpp.c b/contrib/tools/swig/Source/Preprocessor/cpp.c
new file mode 100644
index 00000000000..407ccd51546
--- /dev/null
+++ b/contrib/tools/swig/Source/Preprocessor/cpp.c
@@ -0,0 +1,2198 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * cpp.c
+ *
+ * An implementation of a C preprocessor plus some support for additional
+ * SWIG directives.
+ *
+ * - SWIG directives such as %include and %import are handled
+ * - A new macro %define ... %enddef can be used for multiline macros
+ * - No preprocessing is performed in %{ ... %} blocks
+ * - Lines beginning with %# are stripped down to #... and passed through.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "preprocessor.h"
+#include <ctype.h>
+
+static Hash *cpp = 0; /* C preprocessor data */
+static int include_all = 0; /* Follow all includes */
+static int ignore_missing = 0;
+static int import_all = 0; /* Follow all includes, but as %import statements */
+static int imported_depth = 0; /* Depth of %imported files */
+static int single_include = 1; /* Only include each file once */
+static Hash *included_files = 0;
+static List *dependencies = 0;
+static Scanner *id_scan = 0;
+static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */
+static int expand_defined_operator = 0;
+static int macro_level = 0;
+static int macro_start_line = 0;
+static const String * macro_start_file = 0;
+
+/* Test a character to see if it starts an identifier */
+#define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$'))
+
+/* Test a character to see if it valid in an identifier (after the first letter) */
+#define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$'))
+
+static DOH *Preprocessor_replace(DOH *, DOH *);
+
+/* Skip whitespace */
+static void skip_whitespace(String *s, String *out) {
+ int c;
+ while ((c = Getc(s)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, s);
+ break;
+ } else if (out)
+ Putc(c, out);
+ }
+}
+
+/* Skip to a specified character taking line breaks into account */
+static int skip_tochar(String *s, int ch, String *out) {
+ int c;
+ while ((c = Getc(s)) != EOF) {
+ if (out)
+ Putc(c, out);
+ if (c == ch)
+ break;
+ if (c == '\\') {
+ c = Getc(s);
+ if ((c != EOF) && (out))
+ Putc(c, out);
+ }
+ }
+ if (c == EOF)
+ return -1;
+ return 0;
+}
+
+/* Skip to a specified character or the end of the line */
+static int skip_tochar_or_eol(String *s, int ch, String *out) {
+ int c;
+ while ((c = Getc(s)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, s);
+ break;
+ }
+ if (out)
+ Putc(c, out);
+ if (c == ch)
+ break;
+ if (c == '\\') {
+ c = Getc(s);
+ if ((c != EOF) && (out))
+ Putc(c, out);
+ }
+ }
+ if (c == EOF)
+ return -1;
+ return 0;
+}
+
+static void copy_location(const DOH *s1, DOH *s2) {
+ Setfile(s2, Getfile((DOH *) s1));
+ Setline(s2, Getline((DOH *) s1));
+}
+
+static String *cpp_include(const_String_or_char_ptr fn, int sysfile) {
+ String *s = sysfile ? Swig_include_sys(fn) : Swig_include(fn);
+ if (s && single_include) {
+ String *file = Getfile(s);
+ if (Getattr(included_files, file)) {
+ Delete(s);
+ return 0;
+ }
+ Setattr(included_files, file, file);
+ }
+ if (!s) {
+ if (ignore_missing) {
+ Swig_warning(WARN_PP_MISSING_FILE, Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
+ } else {
+ Swig_error(Getfile(fn), Getline(fn), "Unable to find '%s'\n", fn);
+ }
+ } else {
+ String *lf;
+ Seek(s, 0, SEEK_SET);
+ if (!dependencies) {
+ dependencies = NewList();
+ }
+ lf = Copy(Swig_last_file());
+ Append(dependencies, lf);
+ Delete(lf);
+ }
+ return s;
+}
+
+static int is_digits(const String *str) {
+ const char *s = Char(str);
+ int isdigits = (*s != 0);
+ while (*s) {
+ if (!isdigit((int)*s)) {
+ isdigits = 0;
+ break;
+ }
+ s++;
+ }
+ return isdigits;
+}
+
+List *Preprocessor_depend(void) {
+ return dependencies;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Preprocessor_cpp_init() - Initialize the preprocessor
+ * ----------------------------------------------------------------------------- */
+static String *kpp_args = 0;
+static String *kpp_define = 0;
+static String *kpp_defined = 0;
+static String *kpp_elif = 0;
+static String *kpp_else = 0;
+static String *kpp_endif = 0;
+static String *kpp_expanded = 0;
+static String *kpp_if = 0;
+static String *kpp_ifdef = 0;
+static String *kpp_ifndef = 0;
+static String *kpp_name = 0;
+static String *kpp_swigmacro = 0;
+static String *kpp_symbols = 0;
+static String *kpp_undef = 0;
+static String *kpp_value = 0;
+static String *kpp_varargs = 0;
+static String *kpp_error = 0;
+static String *kpp_warning = 0;
+static String *kpp_line = 0;
+static String *kpp_include = 0;
+static String *kpp_pragma = 0;
+static String *kpp_level = 0;
+
+static String *kpp_dline = 0;
+static String *kpp_ddefine = 0;
+static String *kpp_dinclude = 0;
+static String *kpp_dimport = 0;
+static String *kpp_dbeginfile = 0;
+
+static String *kpp_LINE = 0;
+static String *kpp_FILE = 0;
+
+static String *kpp_hash_if = 0;
+static String *kpp_hash_elif = 0;
+
+void Preprocessor_init(void) {
+ Hash *s;
+
+ kpp_args = NewString("args");
+ kpp_define = NewString("define");
+ kpp_defined = NewString("defined");
+ kpp_else = NewString("else");
+ kpp_elif = NewString("elif");
+ kpp_endif = NewString("endif");
+ kpp_expanded = NewString("*expanded*");
+ kpp_if = NewString("if");
+ kpp_ifdef = NewString("ifdef");
+ kpp_ifndef = NewString("ifndef");
+ kpp_name = NewString("name");
+ kpp_swigmacro = NewString("swigmacro");
+ kpp_symbols = NewString("symbols");
+ kpp_undef = NewString("undef");
+ kpp_value = NewString("value");
+ kpp_error = NewString("error");
+ kpp_warning = NewString("warning");
+ kpp_pragma = NewString("pragma");
+ kpp_level = NewString("level");
+ kpp_line = NewString("line");
+ kpp_include = NewString("include");
+ kpp_varargs = NewString("varargs");
+
+ kpp_dinclude = NewString("%include");
+ kpp_dimport = NewString("%import");
+ kpp_dbeginfile = NewString("%beginfile");
+ kpp_ddefine = NewString("%define");
+ kpp_dline = NewString("%line");
+
+
+ kpp_LINE = NewString("__LINE__");
+ kpp_FILE = NewString("__FILE__");
+
+ kpp_hash_if = NewString("#if");
+ kpp_hash_elif = NewString("#elif");
+
+ cpp = NewHash();
+ s = NewHash();
+ Setattr(cpp, kpp_symbols, s);
+ Delete(s);
+ Preprocessor_expr_init(); /* Initialize the expression evaluator */
+ included_files = NewHash();
+
+ id_scan = NewScanner();
+
+}
+
+void Preprocessor_delete(void) {
+ Delete(kpp_args);
+ Delete(kpp_define);
+ Delete(kpp_defined);
+ Delete(kpp_else);
+ Delete(kpp_elif);
+ Delete(kpp_endif);
+ Delete(kpp_expanded);
+ Delete(kpp_if);
+ Delete(kpp_ifdef);
+ Delete(kpp_ifndef);
+ Delete(kpp_name);
+ Delete(kpp_swigmacro);
+ Delete(kpp_symbols);
+ Delete(kpp_undef);
+ Delete(kpp_value);
+ Delete(kpp_error);
+ Delete(kpp_warning);
+ Delete(kpp_pragma);
+ Delete(kpp_level);
+ Delete(kpp_line);
+ Delete(kpp_include);
+ Delete(kpp_varargs);
+
+ Delete(kpp_dinclude);
+ Delete(kpp_dimport);
+ Delete(kpp_dbeginfile);
+ Delete(kpp_ddefine);
+ Delete(kpp_dline);
+
+ Delete(kpp_LINE);
+ Delete(kpp_FILE);
+
+ Delete(kpp_hash_if);
+ Delete(kpp_hash_elif);
+
+ Delete(cpp);
+ Delete(included_files);
+ Preprocessor_expr_delete();
+ DelScanner(id_scan);
+
+ Delete(dependencies);
+
+ Delete(Swig_add_directory(0));
+}
+
+/* -----------------------------------------------------------------------------
+ * void Preprocessor_include_all() - Instruct preprocessor to include all files
+ * ----------------------------------------------------------------------------- */
+void Preprocessor_include_all(int a) {
+ include_all = a;
+}
+
+void Preprocessor_import_all(int a) {
+ import_all = a;
+}
+
+void Preprocessor_ignore_missing(int a) {
+ ignore_missing = a;
+}
+
+void Preprocessor_error_as_warning(int a) {
+ error_as_warning = a;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_define()
+ *
+ * Defines a new C preprocessor symbol. swigmacro specifies whether or not the macro has
+ * SWIG macro semantics.
+ * ----------------------------------------------------------------------------- */
+
+
+static String *Macro_vararg_name(const_String_or_char_ptr str, const_String_or_char_ptr line) {
+ String *varargname;
+ char *s, *dots;
+
+ s = Char(str);
+ dots = strchr(s, '.');
+ if (!dots) {
+ return NULL;
+ }
+
+ if (strcmp(dots, "...") != 0) {
+ Swig_error(Getfile(line), Getline(line), "Illegal macro argument name '%s'\n", str);
+ return NULL;
+ }
+ if (dots == s) {
+ varargname = NewString("__VA_ARGS__");
+ } else {
+ varargname = NewStringWithSize(s, (int)(dots - s));
+ }
+ return varargname;
+}
+
+Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
+ String *macroname = 0, *argstr = 0, *macrovalue = 0, *file = 0, *s = 0;
+ Hash *macro = 0, *symbols = 0, *m1;
+ List *arglist = 0;
+ int c, line;
+ int varargs = 0;
+ String *str;
+
+ assert(cpp);
+ assert(_str);
+
+ /* First make sure that string is actually a string */
+ if (DohCheck(_str)) {
+ s = Copy(_str);
+ copy_location(_str, s);
+ str = s;
+ } else {
+ str = NewString((char *) _str);
+ }
+ Seek(str, 0, SEEK_SET);
+ line = Getline(str);
+ file = Getfile(str);
+
+ /* Skip over any leading whitespace */
+ skip_whitespace(str, 0);
+
+ /* Now look for a macro name */
+ macroname = NewStringEmpty();
+ copy_location(str, macroname);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '(') {
+ argstr = NewStringEmpty();
+ copy_location(str, argstr);
+ /* It is a macro. Go extract its argument string */
+ while ((c = Getc(str)) != EOF) {
+ if (c == ')')
+ break;
+ else
+ Putc(c, argstr);
+ }
+ if (c != ')') {
+ Swig_error(Getfile(argstr), Getline(argstr), "Missing \')\' in macro parameters\n");
+ goto macro_error;
+ }
+ break;
+ } else if (isidchar(c) || (c == '%')) {
+ Putc(c, macroname);
+ } else if (isspace(c)) {
+ break;
+ } else if (c == '\\') {
+ c = Getc(str);
+ if (c != '\n') {
+ Ungetc(c, str);
+ Ungetc('\\', str);
+ break;
+ }
+ } else {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ if (!swigmacro)
+ skip_whitespace(str, 0);
+ macrovalue = NewStringEmpty();
+ copy_location(str, macrovalue);
+ while ((c = Getc(str)) != EOF) {
+ Putc(c, macrovalue);
+ }
+
+ /* If there are any macro arguments, convert into a list */
+ if (argstr) {
+ String *argname, *varargname;
+ arglist = NewList();
+ Seek(argstr, 0, SEEK_SET);
+ argname = NewStringEmpty();
+ while ((c = Getc(argstr)) != EOF) {
+ if (c == ',') {
+ varargname = Macro_vararg_name(argname, argstr);
+ if (varargname) {
+ Delete(varargname);
+ Swig_error(Getfile(argstr), Getline(argstr), "Variable length macro argument must be last parameter\n");
+ } else {
+ Append(arglist, argname);
+ }
+ Delete(argname);
+ argname = NewStringEmpty();
+ } else if (isidchar(c) || (c == '.')) {
+ Putc(c, argname);
+ } else if (!(isspace(c) || (c == '\\'))) {
+ Delete(argname);
+ Swig_error(Getfile(argstr), Getline(argstr), "Illegal character in macro argument name\n");
+ goto macro_error;
+ }
+ }
+ if (Len(argname)) {
+ /* Check for varargs */
+ varargname = Macro_vararg_name(argname, argstr);
+ if (varargname) {
+ Append(arglist, varargname);
+ Delete(varargname);
+ varargs = 1;
+ } else {
+ Append(arglist, argname);
+ }
+ }
+ Delete(argname);
+ }
+
+ if (!swigmacro) {
+ Replace(macrovalue, "\\\n", " ", DOH_REPLACE_NOQUOTE);
+ }
+
+ /* Look for special # substitutions. We only consider # that appears
+ outside of quotes and comments */
+
+ {
+ int state = 0;
+ char *cc = Char(macrovalue);
+ while (*cc) {
+ switch (state) {
+ case 0:
+ if (*cc == '#')
+ *cc = '\001';
+ else if (*cc == '/')
+ state = 10;
+ else if (*cc == '\'')
+ state = 20;
+ else if (*cc == '\"')
+ state = 30;
+ break;
+ case 10:
+ if (*cc == '*')
+ state = 11;
+ else if (*cc == '/')
+ state = 15;
+ else {
+ state = 0;
+ cc--;
+ }
+ break;
+ case 11:
+ if (*cc == '*')
+ state = 12;
+ break;
+ case 12:
+ if (*cc == '/')
+ state = 0;
+ else if (*cc != '*')
+ state = 11;
+ break;
+ case 15:
+ if (*cc == '\n')
+ state = 0;
+ break;
+ case 20:
+ if (*cc == '\'')
+ state = 0;
+ if (*cc == '\\')
+ state = 21;
+ break;
+ case 21:
+ state = 20;
+ break;
+ case 30:
+ if (*cc == '\"')
+ state = 0;
+ if (*cc == '\\')
+ state = 31;
+ break;
+ case 31:
+ state = 30;
+ break;
+ default:
+ break;
+ }
+ cc++;
+ }
+ }
+
+ /* Get rid of whitespace surrounding # */
+ /* Replace(macrovalue,"#","\001",DOH_REPLACE_NOQUOTE); */
+ while (Replace(macrovalue, "\001 ", "\001", DOH_REPLACE_ANY) > 0) { }
+ while (Replace(macrovalue, " \001", "\001", DOH_REPLACE_ANY) > 0) { }
+ /* Replace '##' with a special token */
+ Replace(macrovalue, "\001\001", "\002", DOH_REPLACE_ANY);
+ /* Replace '#@' with a special token */
+ Replace(macrovalue, "\001@", "\004", DOH_REPLACE_ANY);
+ /* Replace '##@' with a special token */
+ Replace(macrovalue, "\002@", "\005", DOH_REPLACE_ANY);
+ if (varargs) {
+ /* Replace '__VA_OPT__' with a special token */
+ Replace(macrovalue, "__VA_OPT__", "\006", DOH_REPLACE_ID|DOH_REPLACE_ANY);
+ }
+
+ /* Go create the macro */
+ macro = NewHash();
+ Setattr(macro, kpp_name, macroname);
+
+ if (arglist) {
+ Setattr(macro, kpp_args, arglist);
+ Delete(arglist);
+ if (varargs) {
+ Setattr(macro, kpp_varargs, "1");
+ }
+ }
+ Setattr(macro, kpp_value, macrovalue);
+ Setline(macro, line);
+ Setfile(macro, file);
+ if (swigmacro) {
+ Setattr(macro, kpp_swigmacro, "1");
+ }
+ symbols = Getattr(cpp, kpp_symbols);
+ if ((m1 = Getattr(symbols, macroname))) {
+ if (!Checkattr(m1, kpp_value, macrovalue)) {
+ Swig_error(Getfile(macroname), Getline(macroname), "Macro '%s' redefined,\n", macroname);
+ Swig_error(Getfile(m1), Getline(m1), "previous definition of '%s'.\n", macroname);
+ goto macro_error;
+ }
+ } else {
+ Setattr(symbols, macroname, macro);
+ Delete(macro);
+ }
+
+ Delete(macroname);
+ Delete(macrovalue);
+
+ Delete(str);
+ Delete(argstr);
+ return macro;
+
+macro_error:
+ Delete(str);
+ Delete(argstr);
+ Delete(arglist);
+ Delete(macroname);
+ Delete(macrovalue);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_undef()
+ *
+ * Undefines a macro.
+ * ----------------------------------------------------------------------------- */
+void Preprocessor_undef(const_String_or_char_ptr str) {
+ Hash *symbols;
+ assert(cpp);
+ symbols = Getattr(cpp, kpp_symbols);
+ Delattr(symbols, str);
+}
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_defined()
+ *
+ * Check if a macro is defined.
+ * ----------------------------------------------------------------------------- */
+int Preprocessor_defined(const_String_or_char_ptr str) {
+ Hash *symbols;
+ assert(cpp);
+ symbols = Getattr(cpp, kpp_symbols);
+ return Getattr(symbols, str) != NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * find_args()
+ *
+ * Isolates macro arguments and returns them in a list. For each argument,
+ * leading and trailing whitespace is stripped (ala K&R, pg. 230).
+ * ----------------------------------------------------------------------------- */
+static List *find_args(String *s, int ismacro, String *macro_name) {
+ List *args;
+ String *str;
+ int c, level;
+ long pos;
+
+ /* Create a new list */
+ args = NewList();
+ copy_location(s, args);
+
+ /* First look for a '(' */
+ pos = Tell(s);
+ skip_whitespace(s, 0);
+
+ /* Now see if the next character is a '(' */
+ c = Getc(s);
+ if (c != '(') {
+ /* Not a macro, bail out now! */
+ assert(pos != -1);
+ (void)Seek(s, pos, SEEK_SET);
+ Delete(args);
+ return 0;
+ }
+ c = Getc(s);
+ /* Okay. This appears to be a macro so we will start isolating arguments */
+ while (c != EOF) {
+ if (isspace(c)) {
+ skip_whitespace(s, 0); /* Skip leading whitespace */
+ c = Getc(s);
+ }
+ str = NewStringEmpty();
+ copy_location(s, str);
+ level = 0;
+ while (c != EOF) {
+ if (c == '\"') {
+ Putc(c, str);
+ skip_tochar(s, '\"', str);
+ c = Getc(s);
+ continue;
+ } else if (c == '\'') {
+ Putc(c, str);
+ skip_tochar(s, '\'', str);
+ c = Getc(s);
+ continue;
+ } else if (c == '/') {
+ /* Ensure comments are ignored by eating up the characters */
+ c = Getc(s);
+ /* Handle / * ... * / type comments (multi-line) */
+ if (c == '*') {
+ while ((c = Getc(s)) != EOF) {
+ if (c == '*') {
+another_star:
+ c = Getc(s);
+ if (c == '/' || c == EOF)
+ break;
+ if (c == '*') goto another_star;
+ }
+ }
+ c = Getc(s);
+ continue;
+ }
+ /* Handle // ... type comments (single-line) */
+ if (c == '/') {
+ while ((c = Getc(s)) != EOF) {
+ if (c == '\n') {
+ break;
+ }
+ }
+ c = Getc(s);
+ continue;
+ }
+ /* ensure char is available in the stream as this was not a comment*/
+ Ungetc(c, s);
+ c = '/';
+ }
+ if ((c == ',') && (level == 0))
+ break;
+ if ((c == ')') && (level == 0))
+ break;
+ Putc(c, str);
+ if (c == '(')
+ level++;
+ if (c == ')')
+ level--;
+ c = Getc(s);
+ }
+ if (level > 0) {
+ goto unterm;
+ }
+ Chop(str);
+ Append(args, str);
+ Delete(str);
+ if (c == ')')
+ return args;
+ c = Getc(s);
+ }
+unterm:
+ if (ismacro)
+ Swig_error(Getfile(args), Getline(args), "Unterminated call invoking macro '%s'\n", macro_name);
+ else
+ Swig_error(Getfile(args), Getline(args), "Unterminated call to '%s'\n", macro_name);
+ return args;
+}
+
+/* -----------------------------------------------------------------------------
+ * DOH *get_filename()
+ *
+ * Read a filename from str. A filename can be enclosed in quotes, angle brackets,
+ * or bare.
+ * ----------------------------------------------------------------------------- */
+
+static String *get_filename(String *str, int *sysfile) {
+ String *fn;
+ int c;
+
+ fn = NewStringEmpty();
+ copy_location(str, fn);
+ c = Getc(str);
+ *sysfile = 0;
+ if (c == '\"') {
+ while (((c = Getc(str)) != EOF) && (c != '\"'))
+ Putc(c, fn);
+ } else if (c == '<') {
+ *sysfile = 1;
+ while (((c = Getc(str)) != EOF) && (c != '>'))
+ Putc(c, fn);
+ } else {
+ String *preprocessed_str;
+ Putc(c, fn);
+ while (((c = Getc(str)) != EOF) && (!isspace(c)))
+ Putc(c, fn);
+ if (isspace(c))
+ Ungetc(c, str);
+ preprocessed_str = Preprocessor_replace(fn, NULL);
+ Seek(preprocessed_str, 0, SEEK_SET);
+ Delete(fn);
+
+ fn = NewStringEmpty();
+ copy_location(preprocessed_str, fn);
+ c = Getc(preprocessed_str);
+ if (c == '\"') {
+ while (((c = Getc(preprocessed_str)) != EOF) && (c != '\"'))
+ Putc(c, fn);
+ } else if (c == '<') {
+ *sysfile = 1;
+ while (((c = Getc(preprocessed_str)) != EOF) && (c != '>'))
+ Putc(c, fn);
+ } else {
+ fn = Copy(preprocessed_str);
+ }
+ Delete(preprocessed_str);
+ }
+ Swig_filename_unescape(fn);
+ Swig_filename_correct(fn);
+ Seek(fn, 0, SEEK_SET);
+ return fn;
+}
+
+static String *get_options(String *str) {
+ int c;
+ c = Getc(str);
+ if (c == '(') {
+ String *opt;
+ int level = 1;
+ opt = NewString("(");
+ while (((c = Getc(str)) != EOF)) {
+ Putc(c, opt);
+ switch (c) {
+ case ')':
+ level--;
+ if (!level)
+ return opt;
+ break;
+ case '(':
+ level++;
+ break;
+ case '"':
+ /* Skip over quoted strings */
+ while (1) {
+ c = Getc(str);
+ if (c == EOF)
+ goto bad;
+ Putc(c, opt);
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ c = Getc(str);
+ if (c == EOF)
+ goto bad;
+ Putc(c, opt);
+ }
+ }
+ break;
+ }
+ }
+bad:
+ Delete(opt);
+ return 0;
+ } else {
+ Ungetc(c, str);
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * expand_macro()
+ *
+ * Perform macro expansion and return a new string. Returns NULL if some sort
+ * of error occurred.
+ * name - name of the macro
+ * args - arguments passed to the macro
+ * line_file - global context, used for line/file name when reporting errors
+ * ----------------------------------------------------------------------------- */
+
+static String *expand_macro(String *name, List *args, String *line_file) {
+ String *ns;
+ DOH *symbols, *macro, *margs, *mvalue, *temp, *tempa, *e;
+ int i, l;
+ int isvarargs = 0;
+
+ symbols = Getattr(cpp, kpp_symbols);
+ if (!symbols)
+ return 0;
+
+ /* See if the name is actually defined */
+ macro = Getattr(symbols, name);
+ if (!macro)
+ return 0;
+
+ if (macro_level == 0) {
+ /* Store the start of the macro should the macro contain __LINE__ and __FILE__ for expansion */
+ macro_start_line = Getline(args ? args : line_file);
+ macro_start_file = Getfile(args ? args : line_file);
+ }
+ macro_level++;
+
+ if (Getattr(macro, kpp_expanded)) {
+ ns = NewStringEmpty();
+ Append(ns, name);
+ if (args) {
+ int lenargs = Len(args);
+ if (lenargs)
+ Putc('(', ns);
+ for (i = 0; i < lenargs; i++) {
+ Append(ns, Getitem(args, i));
+ if (i < (lenargs - 1))
+ Putc(',', ns);
+ }
+ if (i)
+ Putc(')', ns);
+ }
+ macro_level--;
+ return ns;
+ }
+
+ /* Get macro arguments and value */
+ mvalue = Getattr(macro, kpp_value);
+ assert(mvalue);
+ margs = Getattr(macro, kpp_args);
+
+ if (args && Getattr(macro, kpp_varargs)) {
+ isvarargs = 1;
+ /* Variable length argument macro. We need to collect all of the extra arguments into a single argument */
+ if (Len(args) >= (Len(margs) - 1)) {
+ int i;
+ int vi, na;
+ String *vararg = NewStringEmpty();
+ vi = Len(margs) - 1;
+ na = Len(args);
+ for (i = vi; i < na; i++) {
+ Append(vararg, Getitem(args, i));
+ if ((i + 1) < na) {
+ Append(vararg, ",");
+ }
+ }
+ /* Remove arguments */
+ for (i = vi; i < na; i++) {
+ Delitem(args, vi);
+ }
+ Append(args, vararg);
+ Delete(vararg);
+ }
+ }
+
+ if (args && margs && Len(margs) == 0 && Len(args) == 1 && Len(Getitem(args, 0)) == 0) {
+ /* FOO() can invoke a macro defined as FOO(X) as well as one defined FOO().
+ *
+ * Handle this by removing the only argument if it's empty and the macro
+ * expects no arguments.
+ *
+ * We don't need to worry about varargs here - a varargs macro will always have
+ * Len(margs) >= 1, since the varargs are put in the final macro argument.
+ */
+ Delitem(args, 0);
+ }
+
+ /* If there are arguments, see if they match what we were given */
+ if (args && (!margs || Len(margs) != Len(args))) {
+ if (margs && Len(margs) > (1 + isvarargs))
+ Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
+ else if (margs && Len(margs) == (1 + isvarargs))
+ Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects 1 argument\n", name);
+ else
+ Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects no arguments\n", name);
+ macro_level--;
+ return 0;
+ }
+
+ /* If the macro expects arguments, but none were supplied, we leave it in place */
+ if (!args && margs) {
+ macro_level--;
+ return NewString(name);
+ }
+
+ /* Copy the macro value */
+ ns = Copy(mvalue);
+ copy_location(mvalue, ns);
+
+ /* Tag the macro as being expanded. This is to avoid recursion in
+ macro expansion */
+
+ temp = NewStringEmpty();
+ tempa = NewStringEmpty();
+ if (args && margs) {
+ l = Len(margs);
+ for (i = 0; i < l; i++) {
+ DOH *arg, *aname;
+ String *reparg;
+ arg = Getitem(args, i); /* Get an argument value */
+ reparg = Preprocessor_replace(arg, NULL);
+ aname = Getitem(margs, i); /* Get macro argument name */
+ if (strchr(Char(ns), '\001')) {
+ /* Try to replace a quoted version of the argument */
+ Clear(temp);
+ Clear(tempa);
+ Printf(temp, "\001%s", aname);
+ Printf(tempa, "\"%s\"", arg);
+ Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
+ }
+ if (isvarargs && i == l - 1) {
+ char *s = Char(ns);
+ char *a = s;
+ while ((a = strchr(a, '\006')) != NULL) {
+ *a = ' ';
+ while (isspace((unsigned char)*++a)) { }
+ if (*a == '(') {
+ char *e = a;
+ int depth = 1;
+ while (*++e) {
+ if (*e == ')') {
+ if (--depth == 0) break;
+ } else if (*e == '(') {
+ ++depth;
+ }
+ }
+ if (*e) {
+ if (Len(arg) == 0) {
+ // Empty varargs so replace ( and ) and everything between with
+ // spaces.
+ memset(a, ' ', e - a + 1);
+ } else {
+ // Non-empty varargs so replace ( and ) with spaces.
+ *a = ' ';
+ *e = ' ';
+ }
+ }
+ a = e + 1;
+ }
+ }
+ }
+
+ if (strchr(Char(ns), '\002')) {
+ /* Look for concatenation tokens */
+ Clear(temp);
+ Clear(tempa);
+ Printf(temp, "\002%s", aname);
+ Append(tempa, "\002\003");
+ Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
+ if (isvarargs && i == l - 1 && Len(arg) == 0) {
+ // ## followed by a zero length varargs macro argument - if preceded
+ // by a comma (possibly with whitespace in between) we nuke the
+ // comma.
+ char *s = Char(ns);
+ char *a = s + 1;
+ while ((a = strstr(a, "\002\003")) != NULL) {
+ char *t = a;
+ while (--t >= s) {
+ if (!isspace((unsigned char)*t)) {
+ if (*t == ',') *t = ' ';
+ break;
+ }
+ }
+ // Advance 3 since we're only interested in \002\003 when it could
+ // be preceded by a comma.
+ a += 3;
+ }
+ }
+
+ Clear(temp);
+ Clear(tempa);
+ Printf(temp, "%s\002", aname);
+ Append(tempa, "\003\002");
+ Replace(ns, temp, tempa, DOH_REPLACE_ID_BEGIN);
+ }
+
+ /* Non-standard macro expansion. The value `x` is replaced by a quoted
+ version of the argument except that if the argument is already quoted
+ nothing happens */
+
+ if (strchr(Char(ns), '`')) {
+ String *rep;
+ char *c;
+ Clear(temp);
+ Printf(temp, "`%s`", aname);
+ c = Char(arg);
+ if (*c == '"') {
+ rep = arg;
+ } else {
+ Clear(tempa);
+ Printf(tempa, "\"%s\"", arg);
+ rep = tempa;
+ }
+ Replace(ns, temp, rep, DOH_REPLACE_ANY);
+ }
+
+ /* Non-standard mangle expansions.
+ The #@Name is replaced by mangle_arg(Name). */
+ if (strchr(Char(ns), '\004')) {
+ String *marg = Swig_name_mangle_string(arg);
+ Clear(temp);
+ Printf(temp, "\004%s", aname);
+ Replace(ns, temp, marg, DOH_REPLACE_ID_END);
+ Delete(marg);
+ }
+ if (strchr(Char(ns), '\005')) {
+ String *marg = Swig_name_mangle_string(arg);
+ Clear(temp);
+ Clear(tempa);
+ Printf(temp, "\005%s", aname);
+ Printf(tempa, "\"%s\"", marg);
+ Replace(ns, temp, tempa, DOH_REPLACE_ID_END);
+ Delete(marg);
+ }
+
+ /* Replace(ns, aname, arg, DOH_REPLACE_ID); */
+ Replace(ns, aname, reparg, DOH_REPLACE_ID); /* Replace expanded args */
+ Replace(ns, "\003", arg, DOH_REPLACE_ANY); /* Replace unexpanded arg */
+ Delete(reparg);
+ }
+ }
+ Replace(ns, "\002", "", DOH_REPLACE_ANY); /* Get rid of concatenation tokens */
+ Replace(ns, "\001", "#", DOH_REPLACE_ANY); /* Put # back (non-standard C) */
+ Replace(ns, "\004", "#@", DOH_REPLACE_ANY); /* Put # back (non-standard C) */
+
+ /* Expand this macro even further */
+ Setattr(macro, kpp_expanded, "1");
+
+ e = Preprocessor_replace(ns, line_file);
+
+ Delattr(macro, kpp_expanded);
+ Delete(ns);
+
+ if (Getattr(macro, kpp_swigmacro)) {
+ String *g;
+ String *f = NewStringEmpty();
+ Seek(e, 0, SEEK_SET);
+ copy_location(macro, e);
+ g = Preprocessor_parse(e);
+
+#if 0
+ /* Drop the macro in place, but with a marker around it */
+ Printf(f, "/*@%s,%d,%s@*/%s/*@@*/", Getfile(macro), Getline(macro), name, g);
+#else
+ /* Use simplified around markers to properly count lines in cscanner.c */
+ if (strchr(Char(g), '\n')) {
+ Printf(f, "/*@SWIG:%s,%d,%s@*/%s/*@SWIG@*/", Getfile(macro), Getline(macro), name, g);
+#if 0
+ Printf(f, "/*@SWIG:%s@*/%s/*@SWIG@*/", name, g);
+#endif
+ } else {
+ Append(f, g);
+ }
+#endif
+
+ Delete(g);
+ Delete(e);
+ e = f;
+ }
+ macro_level--;
+ Delete(temp);
+ Delete(tempa);
+ return e;
+}
+
+/* -----------------------------------------------------------------------------
+ * DOH *Preprocessor_replace(DOH *s, DOH *line_file)
+ *
+ * Performs a macro substitution on a string s. Returns a new string with
+ * substitutions applied. This function works by walking down s and looking
+ * for identifiers. When found, a check is made to see if they are macros
+ * which are then expanded.
+ * ----------------------------------------------------------------------------- */
+
+/* #define SWIG_PUT_BUFF */
+
+static DOH *Preprocessor_replace(DOH *s, DOH *line_file) {
+ DOH *ns, *symbols, *m;
+ int c, i, state = 0;
+ String *id = NewStringEmpty();
+
+ assert(cpp);
+ symbols = Getattr(cpp, kpp_symbols);
+
+ ns = NewStringEmpty();
+ copy_location(s, ns);
+ Seek(s, 0, SEEK_SET);
+
+ /* Try to locate identifiers in s and replace them with macro replacements */
+ while ((c = Getc(s)) != EOF) {
+ switch (state) {
+ case 0:
+ if (isidentifier(c)) {
+ Clear(id);
+ Putc(c, id);
+ state = 4;
+ } else if (c == '%') {
+ Clear(id);
+ Putc(c, id);
+ state = 2;
+ } else if (c == '#') {
+ Clear(id);
+ Putc(c, id);
+ state = 4;
+ } else if (c == '\"') {
+ Putc(c, ns);
+ skip_tochar(s, '\"', ns);
+ } else if (c == '\'') {
+ Putc(c, ns);
+ skip_tochar(s, '\'', ns);
+ } else if (c == '/') {
+ Putc(c, ns);
+ state = 10;
+ } else if (c == '\\') {
+ Putc(c, ns);
+ c = Getc(s);
+ if (c == '\n') {
+ Putc(c, ns);
+ } else {
+ Ungetc(c, s);
+ }
+ } else if (c == '\n') {
+ Putc(c, ns);
+ expand_defined_operator = 0;
+ } else {
+ Putc(c, ns);
+ }
+ break;
+ case 2:
+ /* Found '%#' */
+ if (c == '#') {
+ Putc(c, id);
+ state = 4;
+ } else {
+ Ungetc(c, s);
+ state = 4;
+ }
+ break;
+ case 4: /* An identifier */
+ if (isidchar(c)) {
+ Putc(c, id);
+ state = 4;
+ } else {
+ /* We found the end of a valid identifier */
+ Ungetc(c, s);
+ /* See if this is the special "defined" operator */
+ if (Equal(kpp_defined, id)) {
+ if (expand_defined_operator) {
+ int lenargs = 0;
+ DOH *args = 0;
+ /* See whether or not a parenthesis has been used */
+ skip_whitespace(s, 0);
+ c = Getc(s);
+ if (c == '(') {
+ Ungetc(c, s);
+ args = find_args(s, 0, kpp_defined);
+ } else if (isidchar(c)) {
+ DOH *arg = NewStringEmpty();
+ args = NewList();
+ Putc(c, arg);
+ while (((c = Getc(s)) != EOF)) {
+ if (!isidchar(c)) {
+ Ungetc(c, s);
+ break;
+ }
+ Putc(c, arg);
+ }
+ if (Len(arg))
+ Append(args, arg);
+ Delete(arg);
+ } else {
+ Seek(s, -1, SEEK_CUR);
+ }
+ lenargs = Len(args);
+ if ((!args) || (!lenargs)) {
+ /* This is not a defined() operator. */
+ Append(ns, id);
+ state = 0;
+ break;
+ }
+ for (i = 0; i < lenargs; i++) {
+ DOH *o = Getitem(args, i);
+ if (!Getattr(symbols, o)) {
+ break;
+ }
+ }
+ if (i < lenargs)
+ Putc('0', ns);
+ else
+ Putc('1', ns);
+ Delete(args);
+ } else {
+ Append(ns, id);
+ }
+ state = 0;
+ break;
+ } else if (Equal(kpp_LINE, id)) {
+ Printf(ns, "%d", macro_level > 0 ? macro_start_line : Getline(s));
+ state = 0;
+ break;
+ } else if (Equal(kpp_FILE, id)) {
+ String *fn = Copy(macro_level > 0 ? macro_start_file : Getfile(s));
+ Replaceall(fn, "\\", "\\\\");
+ Printf(ns, "\"%s\"", fn);
+ Delete(fn);
+ state = 0;
+ break;
+ } else if (Equal(kpp_hash_if, id) || Equal(kpp_hash_elif, id)) {
+ expand_defined_operator = 1;
+ Append(ns, id);
+ } else if (Equal("#ifdef", id) || Equal("#ifndef", id)) {
+ /* Evaluate the defined-ness check and substitute `#if 0` or `#if 1`. */
+ int allow = 0;
+ skip_whitespace(s, 0);
+ c = Getc(s);
+ if (isidchar(c)) {
+ DOH *arg = NewStringEmpty();
+ Putc(c, arg);
+ while (((c = Getc(s)) != EOF)) {
+ if (!isidchar(c)) {
+ Ungetc(c, s);
+ break;
+ }
+ Putc(c, arg);
+ }
+ if (Equal("#ifdef", id)) {
+ if (Getattr(symbols, arg)) allow = 1;
+ } else {
+ if (!Getattr(symbols, arg)) allow = 1;
+ }
+ Delete(arg);
+ } else {
+ Ungetc(c, s);
+ Swig_error(Getfile(s), Getline(s), "Missing identifier for %s.\n", id);
+ }
+ if (allow) {
+ Append(ns, "#if 1");
+ } else {
+ Append(ns, "#if 0");
+ }
+ } else if ((m = Getattr(symbols, id))) {
+ /* See if the macro is defined in the preprocessor symbol table */
+ DOH *args = 0;
+ DOH *e;
+ int macro_additional_lines = 0;
+ /* See if the macro expects arguments */
+ if (Getattr(m, kpp_args)) {
+ /* Yep. We need to go find the arguments and do a substitution */
+ int line = Getline(s);
+ args = find_args(s, 1, id);
+ macro_additional_lines = Getline(s) - line;
+ assert(macro_additional_lines >= 0);
+ } else {
+ args = 0;
+ }
+ e = expand_macro(id, args, s);
+ if (e) {
+ Append(ns, e);
+ }
+ while (macro_additional_lines--) {
+ Putc('\n', ns);
+ }
+ Delete(e);
+ Delete(args);
+ } else {
+ Append(ns, id);
+ }
+ state = 0;
+ }
+ break;
+ case 10:
+ if (c == '/')
+ state = 11;
+ else if (c == '*')
+ state = 12;
+ else {
+ Ungetc(c, s);
+ state = 0;
+ break;
+ }
+ Putc(c, ns);
+ break;
+ case 11:
+ /* in C++ comment */
+ Putc(c, ns);
+ if (c == '\n') {
+ expand_defined_operator = 0;
+ state = 0;
+ }
+ break;
+ case 12:
+ /* in C comment */
+ Putc(c, ns);
+ if (c == '*')
+ state = 13;
+ break;
+ case 13:
+ Putc(c, ns);
+ if (c == '/')
+ state = 0;
+ else if (c != '*')
+ state = 12;
+ break;
+ default:
+ state = 0;
+ break;
+ }
+ }
+
+ /* Identifier at the end */
+ if (state == 2 || state == 4) {
+ /* See if this is the special "defined" operator */
+ if (Equal(kpp_defined, id)) {
+ Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n");
+ } else if (Equal(kpp_LINE, id)) {
+ Printf(ns, "%d", macro_level > 0 ? macro_start_line : Getline(s));
+ } else if (Equal(kpp_FILE, id)) {
+ String *fn = Copy(macro_level > 0 ? macro_start_file : Getfile(s));
+ Replaceall(fn, "\\", "\\\\");
+ Printf(ns, "\"%s\"", fn);
+ Delete(fn);
+ } else if ((m = Getattr(symbols, id))) {
+ /* Yes. There is a macro here */
+ /* If it expects arguments, they must come from `line_file` */
+ DOH *args = 0;
+ DOH *e;
+ int macro_additional_lines = 0;
+ /* See if the macro expects arguments */
+ if (Getattr(m, kpp_args) && line_file) {
+ /* Yep. We need to go find the arguments and do a substitution */
+ int line = Getline(line_file);
+ args = find_args(line_file, 1, id);
+ macro_additional_lines = Getline(line_file) - line;
+ assert(macro_additional_lines >= 0);
+ } else {
+ args = 0;
+ }
+ e = expand_macro(id, args, s);
+ if (e) {
+ Append(ns, e);
+ }
+ while (macro_additional_lines--) {
+ Putc('\n', ns);
+ }
+ Delete(e);
+ Delete(args);
+ } else {
+ Append(ns, id);
+ }
+ }
+ Delete(id);
+ return ns;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * int checkpp_id(DOH *s)
+ *
+ * Checks the string s to see if it contains any unresolved identifiers. This
+ * function contains the heuristic that determines whether or not a macro
+ * definition passes through the preprocessor as a constant declaration.
+ * ----------------------------------------------------------------------------- */
+static int checkpp_id(DOH *s) {
+ int c;
+ int hastok = 0;
+ Scanner *scan = id_scan;
+
+ Seek(s, 0, SEEK_SET);
+
+ Scanner_clear(scan);
+ s = Copy(s);
+ Seek(s, SEEK_SET, 0);
+ Scanner_push(scan, s);
+ while ((c = Scanner_token(scan))) {
+ hastok = 1;
+ if ((c == SWIG_TOKEN_ID) || (c == SWIG_TOKEN_LBRACE) || (c == SWIG_TOKEN_RBRACE))
+ return 1;
+ }
+ if (!hastok)
+ return 1;
+ return 0;
+}
+
+/* addline(). Utility function for adding lines to a chunk */
+static void addline(DOH *s1, DOH *s2, int allow) {
+ if (allow) {
+ Append(s1, s2);
+ } else {
+ int len = Len(s2);
+ for (int i = 0; i < len; ++i) {
+ if (Char(s2)[i] == '\n')
+ Putc('\n', s1);
+ }
+ }
+}
+
+static void add_chunk(DOH *ns, DOH *chunk, int allow) {
+ DOH *echunk;
+ Seek(chunk, 0, SEEK_SET);
+ if (allow) {
+ echunk = Preprocessor_replace(chunk, NULL);
+ addline(ns, echunk, allow);
+ Delete(echunk);
+ } else {
+ addline(ns, chunk, 0);
+ }
+ Clear(chunk);
+}
+
+/*
+ push/pop_imported(): helper functions for defining and undefining
+ SWIGIMPORTED (when %importing a file).
+ */
+static void push_imported(void) {
+ if (imported_depth == 0) {
+ Preprocessor_define("SWIGIMPORTED 1", 0);
+ }
+ ++imported_depth;
+}
+
+static void pop_imported(void) {
+ --imported_depth;
+ if (imported_depth == 0) {
+ Preprocessor_undef("SWIGIMPORTED");
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_parse()
+ *
+ * Parses the string s. Returns a new string containing the preprocessed version.
+ *
+ * Parsing rules :
+ * 1. Lines starting with # are C preprocessor directives
+ * 2. Macro expansion inside strings is not allowed
+ * 3. All code inside false conditionals is changed to blank lines
+ * 4. Code in %{, %} is not parsed because it may need to be
+ * included inline (with all preprocessor directives included).
+ * ----------------------------------------------------------------------------- */
+
+String *Preprocessor_parse(String *s) {
+ String *ns; /* New string containing the preprocessed text */
+ String *chunk, *decl;
+ Hash *symbols;
+ String *id = 0, *value = 0, *comment = 0;
+ int i, state, e, c;
+ int start_line = 0;
+ int allow = 1;
+ int level = 0;
+ int dlevel = 0;
+ int filelevel = 0;
+ int mask = 0;
+ int start_level = 0;
+ int cpp_lines = 0;
+ int cond_lines[256];
+
+ /* Blow away all carriage returns */
+ Replace(s, "\015", "", DOH_REPLACE_ANY);
+
+ ns = NewStringEmpty(); /* Return result */
+
+ decl = NewStringEmpty();
+ id = NewStringEmpty();
+ value = NewStringEmpty();
+ comment = NewStringEmpty();
+ chunk = NewStringEmpty();
+ copy_location(s, chunk);
+ copy_location(s, ns);
+ symbols = Getattr(cpp, kpp_symbols);
+
+ state = 0;
+ while ((c = Getc(s)) != EOF) {
+ switch (state) {
+ case 0: /* Initial state - in first column */
+ /* Look for C preprocessor directives. Otherwise, go directly to state 1 */
+ if (c == '#') {
+ copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
+ cpp_lines = 1;
+ state = 40;
+ } else if (isspace(c)) {
+ Putc(c, chunk);
+ skip_whitespace(s, chunk);
+ } else {
+ state = 1;
+ Ungetc(c, s);
+ }
+ break;
+ case 1: { /* Non-preprocessor directive */
+ /* Look for SWIG directives */
+state1:
+ if (c == '%') {
+ state = 100;
+ break;
+ }
+ Putc(c, chunk);
+ if (c == '\n')
+ state = 0;
+ else if (c == '\"') {
+ start_line = Getline(s);
+ if (skip_tochar(s, '\"', chunk) < 0) {
+ Swig_error(Getfile(s), start_line, "Unterminated string constant\n");
+ }
+ } else if (c == '\'') {
+ start_line = Getline(s);
+ if (skip_tochar(s, '\'', chunk) < 0) {
+ Swig_error(Getfile(s), start_line, "Unterminated character constant\n");
+ }
+ } else if (c == '/')
+ state = 30; /* Comment */
+ break;
+ }
+
+ case 30: /* Possibly a comment string of some sort */
+ start_line = Getline(s);
+ if (c == '/')
+ state = 31;
+ else if (c == '*')
+ state = 32;
+ else {
+ state = 1;
+ goto state1; /* Process this character the same as if it wasn't preceded by a `/`. */
+ }
+ Putc(c, chunk);
+ break;
+ case 31:
+ Putc(c, chunk);
+ if (c == '\n')
+ state = 0;
+ break;
+ case 32:
+ Putc(c, chunk);
+ if (c == '*')
+ state = 33;
+ break;
+ case 33:
+ Putc(c, chunk);
+ if (c == '/')
+ state = 1;
+ else if (c != '*')
+ state = 32;
+ break;
+
+ case 40: /* Start of a C preprocessor directive */
+ if (c == '\n') {
+ Putc('\n', chunk);
+ state = 0;
+ } else if (isspace(c)) {
+ state = 40;
+ } else {
+ /* Got the start of a preprocessor directive */
+ Ungetc(c, s);
+ Clear(id);
+ copy_location(s, id);
+ state = 41;
+ }
+ break;
+
+ case 41: /* Build up the name of the preprocessor directive */
+ if ((isspace(c) || (!isidchar(c)))) {
+ Clear(value);
+ Clear(comment);
+ if (c == '\n') {
+ Ungetc(c, s);
+ state = 50;
+ } else {
+ state = 42;
+ if (!isspace(c)) {
+ Ungetc(c, s);
+ }
+ }
+
+ copy_location(s, value);
+ break;
+ }
+ Putc(c, id);
+ break;
+
+ case 42: /* Strip any leading space after the preprocessor directive (before preprocessor value) */
+ if (isspace(c)) {
+ if (c == '\n') {
+ Ungetc(c, s);
+ state = 50;
+ }
+ break;
+ }
+ state = 43;
+ /* FALL THRU */
+
+ case 43:
+ /* Get preprocessor value */
+ if (c == '\n') {
+ Ungetc(c, s);
+ state = 50;
+ } else if (c == '/') {
+ state = 45;
+ } else if (c == '\"') {
+ Putc(c, value);
+ skip_tochar_or_eol(s, '\"', value);
+ } else if (c == '\'') {
+ Putc(c, value);
+ skip_tochar_or_eol(s, '\'', value);
+ } else {
+ Putc(c, value);
+ if (c == '\\')
+ state = 44;
+ }
+ break;
+
+ case 44:
+ if (c == '\n') {
+ Putc(c, value);
+ cpp_lines++;
+ } else {
+ Ungetc(c, s);
+ }
+ state = 43;
+ break;
+
+ /* States 45-48 are used to remove, but retain comments from macro values. The comments
+ will be placed in the output in an alternative form */
+
+ case 45:
+ if (c == '/')
+ state = 46;
+ else if (c == '*')
+ state = 47;
+ else if (c == '\n') {
+ Putc('/', value);
+ Ungetc(c, s);
+ state = 50;
+ } else {
+ Putc('/', value);
+ Putc(c, value);
+ state = 43;
+ }
+ break;
+ case 46: /* in C++ comment */
+ if (c == '\n') {
+ Ungetc(c, s);
+ state = 50;
+ } else
+ Putc(c, comment);
+ break;
+ case 47: /* in C comment */
+ if (c == '*')
+ state = 48;
+ else
+ Putc(c, comment);
+ break;
+ case 48:
+ if (c == '/')
+ state = 43;
+ else if (c == '*')
+ Putc(c, comment);
+ else {
+ Putc('*', comment);
+ Putc(c, comment);
+ state = 47;
+ }
+ break;
+ case 50:
+ /* Check for various preprocessor directives */
+ Chop(value);
+ if (Equal(id, kpp_define)) {
+ if (allow) {
+ DOH *m, *v, *v1;
+ Seek(value, 0, SEEK_SET);
+ m = Preprocessor_define(value, 0);
+ if ((m) && !(Getattr(m, kpp_args))) {
+ v = Copy(Getattr(m, kpp_value));
+ copy_location(m, v);
+ if (Len(v)) {
+ Swig_error_silent(1);
+ v1 = Preprocessor_replace(v, NULL);
+ Swig_error_silent(0);
+ /* Printf(stdout,"checking '%s'\n", v1); */
+ if (!checkpp_id(v1)) {
+ if (Len(comment) == 0)
+ Printf(ns, "%%constant %s = %s;\n", Getattr(m, kpp_name), v1);
+ else
+ Printf(ns, "%%constant %s = %s; /*%s*/\n", Getattr(m, kpp_name), v1, comment);
+ cpp_lines--;
+ }
+ Delete(v1);
+ }
+ Delete(v);
+ }
+ }
+ } else if (Equal(id, kpp_undef)) {
+ if (allow)
+ Preprocessor_undef(value);
+ } else if (Equal(id, kpp_ifdef)) {
+ cond_lines[level] = Getline(id);
+ level++;
+ if (allow) {
+ start_level = level;
+ if (Len(value) > 0) {
+ /* See if the identifier is in the hash table */
+ if (!Getattr(symbols, value))
+ allow = 0;
+ } else {
+ Swig_error(Getfile(s), Getline(id), "Missing identifier for #ifdef.\n");
+ allow = 0;
+ }
+ mask = 1;
+ }
+ } else if (Equal(id, kpp_ifndef)) {
+ cond_lines[level] = Getline(id);
+ level++;
+ if (allow) {
+ start_level = level;
+ if (Len(value) > 0) {
+ /* See if the identifier is in the hash table */
+ if (Getattr(symbols, value))
+ allow = 0;
+ } else {
+ Swig_error(Getfile(s), Getline(id), "Missing identifier for #ifndef.\n");
+ allow = 0;
+ }
+ mask = 1;
+ }
+ } else if (Equal(id, kpp_else)) {
+ if (level <= 0) {
+ Swig_error(Getfile(s), Getline(id), "Misplaced #else.\n");
+ } else {
+ cond_lines[level - 1] = Getline(id);
+ if (Len(value) != 0)
+ Swig_warning(WARN_PP_UNEXPECTED_TOKENS, Getfile(s), Getline(id), "Unexpected tokens after #else directive.\n");
+ if (allow) {
+ allow = 0;
+ mask = 0;
+ } else if (level == start_level) {
+ allow = 1 * mask;
+ }
+ }
+ } else if (Equal(id, kpp_endif)) {
+ level--;
+ if (level < 0) {
+ Swig_error(Getfile(id), Getline(id), "Extraneous #endif.\n");
+ level = 0;
+ } else {
+ if (level < start_level) {
+ if (Len(value) != 0)
+ Swig_warning(WARN_PP_UNEXPECTED_TOKENS, Getfile(s), Getline(id), "Unexpected tokens after #endif directive.\n");
+ allow = 1;
+ start_level--;
+ }
+ }
+ } else if (Equal(id, kpp_if)) {
+ cond_lines[level] = Getline(id);
+ level++;
+ if (allow) {
+ int val;
+ String *sval;
+ expand_defined_operator = 1;
+ sval = Preprocessor_replace(value, NULL);
+ start_level = level;
+ Seek(sval, 0, SEEK_SET);
+ /* Printf(stdout,"Evaluating '%s'\n", sval); */
+ if (Len(sval) > 0) {
+ val = Preprocessor_expr(sval, &e);
+ if (e) {
+ const char *msg = Preprocessor_expr_error();
+ Seek(value, 0, SEEK_SET);
+ Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate expression '%s'\n", value);
+ if (msg)
+ Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "%s\n", msg);
+ allow = 0;
+ } else {
+ if (val == 0)
+ allow = 0;
+ }
+ } else {
+ Swig_error(Getfile(s), Getline(id), "Missing expression for #if.\n");
+ allow = 0;
+ }
+ expand_defined_operator = 0;
+ mask = 1;
+ }
+ } else if (Equal(id, kpp_elif)) {
+ if (level == 0) {
+ Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
+ } else {
+ cond_lines[level - 1] = Getline(id);
+ if (allow) {
+ allow = 0;
+ mask = 0;
+ } else if (level == start_level) {
+ int val;
+ String *sval;
+ expand_defined_operator = 1;
+ sval = Preprocessor_replace(value, NULL);
+ Seek(sval, 0, SEEK_SET);
+ if (Len(sval) > 0) {
+ val = Preprocessor_expr(sval, &e);
+ if (e) {
+ const char *msg = Preprocessor_expr_error();
+ Seek(value, 0, SEEK_SET);
+ Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "Could not evaluate expression '%s'\n", value);
+ if (msg)
+ Swig_warning(WARN_PP_EVALUATION, Getfile(value), Getline(value), "%s\n", msg);
+ allow = 0;
+ } else {
+ if (val)
+ allow = 1 * mask;
+ else
+ allow = 0;
+ }
+ } else {
+ Swig_error(Getfile(s), Getline(id), "Missing expression for #elif.\n");
+ allow = 0;
+ }
+ expand_defined_operator = 0;
+ }
+ }
+ } else if (Equal(id, kpp_warning)) {
+ if (allow) {
+ Swig_warning(WARN_PP_CPP_WARNING, Getfile(s), Getline(id), "CPP #warning, \"%s\".\n", value);
+ }
+ } else if (Equal(id, kpp_error)) {
+ if (allow) {
+ if (error_as_warning) {
+ Swig_warning(WARN_PP_CPP_ERROR, Getfile(s), Getline(id), "CPP #error \"%s\".\n", value);
+ } else {
+ Swig_error(Getfile(s), Getline(id), "CPP #error \"%s\". Use the -cpperraswarn option to continue swig processing.\n", value);
+ }
+ }
+ } else if (Equal(id, kpp_line)) {
+ } else if (Equal(id, kpp_include)) {
+ if (((include_all) || (import_all)) && (allow)) {
+ String *s1, *s2, *fn;
+ String *dirname;
+ int sysfile = 0;
+ if (include_all && import_all) {
+ Swig_warning(WARN_PP_INCLUDEALL_IMPORTALL, Getfile(s), Getline(id), "Both includeall and importall are defined: using includeall.\n");
+ import_all = 0;
+ }
+ Seek(value, 0, SEEK_SET);
+ fn = get_filename(value, &sysfile);
+ s1 = cpp_include(fn, sysfile);
+ if (s1) {
+ if (include_all)
+ Printf(ns, "%%includefile \"%s\" %%beginfile\n", Swig_filename_escape(Swig_last_file()));
+ else if (import_all) {
+ Printf(ns, "%%importfile \"%s\" %%beginfile\n", Swig_filename_escape(Swig_last_file()));
+ push_imported();
+ }
+
+ /* See if the filename has a directory component */
+ dirname = Swig_file_dirname(Swig_last_file());
+ if (sysfile || !Len(dirname)) {
+ Delete(dirname);
+ dirname = 0;
+ }
+ if (dirname) {
+ int len = Len(dirname);
+ Delslice(dirname, len - 1, len); /* Kill trailing directory delimiter */
+ Swig_push_directory(dirname);
+ }
+ s2 = Preprocessor_parse(s1);
+ addline(ns, s2, allow);
+ Append(ns, "%endoffile");
+ if (dirname) {
+ Swig_pop_directory();
+ }
+ if (import_all) {
+ pop_imported();
+ }
+ Delete(s2);
+ Delete(dirname);
+ Delete(s1);
+ }
+ Delete(fn);
+ }
+ } else if (Equal(id, kpp_pragma)) {
+ if (Strncmp(value, "SWIG ", 5) == 0) {
+ char *c = Char(value) + 5;
+ while (*c && (isspace((int) *c)))
+ c++;
+ if (*c) {
+ if (strncmp(c, "nowarn=", 7) == 0) {
+ String *val = NewString(c + 7);
+ String *nowarn = Preprocessor_replace(val, NULL);
+ Swig_warnfilter(nowarn, 1);
+ Delete(nowarn);
+ Delete(val);
+ } else if (strncmp(c, "cpperraswarn=", 13) == 0) {
+ error_as_warning = atoi(c + 13);
+ } else {
+ Swig_error(Getfile(s), Getline(id), "Unknown SWIG pragma: %s\n", c);
+ }
+ }
+ }
+ } else if (Equal(id, kpp_level)) {
+ Swig_error(Getfile(s), Getline(id), "cpp debug: level = %d, startlevel = %d\n", level, start_level);
+ } else if (Equal(id, "")) {
+ /* Null directive */
+ } else if (is_digits(id)) {
+ /* A gcc linemarker of the form '# linenum filename flags' (resulting from running gcc -E) */
+ } else {
+ /* Ignore unknown preprocessor directives which are inside an inactive
+ * conditional (github issue #394). */
+ if (allow)
+ Swig_error(Getfile(s), Getline(id), "Unknown SWIG preprocessor directive: %s (if this is a block of target language code, delimit it with %%{ and %%})\n", id);
+ }
+ for (i = 0; i < cpp_lines; i++)
+ Putc('\n', ns);
+ state = 0;
+ break;
+
+ /* SWIG directives */
+ case 100:
+ /* %{,%} block */
+ if (c == '{') {
+ start_line = Getline(s);
+ copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
+ Putc('%', chunk);
+ Putc(c, chunk);
+ state = 105;
+ }
+ /* %#cpp - an embedded C preprocessor directive (we strip off the %) */
+ else if (c == '#') {
+ add_chunk(ns, chunk, allow);
+ Putc(c, chunk);
+ state = 107;
+ } else if (isidentifier(c)) {
+ Clear(decl);
+ Putc('%', decl);
+ Putc(c, decl);
+ state = 110;
+ } else {
+ Putc('%', chunk);
+ Putc(c, chunk);
+ state = 1;
+ }
+ break;
+
+ case 105:
+ Putc(c, chunk);
+ if (c == '%')
+ state = 106;
+ break;
+
+ case 106:
+ Putc(c, chunk);
+ if (c == '}') {
+ state = 1;
+ addline(ns, chunk, allow);
+ Clear(chunk);
+ copy_location(s, chunk);
+ } else {
+ state = 105;
+ }
+ break;
+
+ case 107:
+ Putc(c, chunk);
+ if (c == '\n') {
+ addline(ns, chunk, allow);
+ Clear(chunk);
+ state = 0;
+ } else if (c == '\\') {
+ state = 108;
+ }
+ break;
+
+ case 108:
+ Putc(c, chunk);
+ state = 107;
+ break;
+
+ case 110:
+ if (!isidchar(c)) {
+ Ungetc(c, s);
+ /* Look for common SWIG directives */
+ if (Equal(decl, kpp_dinclude) || Equal(decl, kpp_dimport)) {
+ /* Got some kind of file inclusion directive, eg: %import(option1="value1") "filename" */
+ if (allow) {
+ DOH *s1, *s2, *fn, *opt;
+ String *options_whitespace = NewStringEmpty();
+ String *filename_whitespace = NewStringEmpty();
+ int sysfile = 0;
+
+ skip_whitespace(s, options_whitespace);
+ opt = get_options(s);
+
+ skip_whitespace(s, filename_whitespace);
+ fn = get_filename(s, &sysfile);
+ s1 = cpp_include(fn, sysfile);
+ if (s1) {
+ String *dirname;
+ copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
+ Printf(ns, "%sfile%s%s%s\"%s\" %%beginfile\n", decl, options_whitespace, opt, filename_whitespace, Swig_filename_escape(Swig_last_file()));
+ if (Equal(decl, kpp_dimport)) {
+ push_imported();
+ }
+ dirname = Swig_file_dirname(Swig_last_file());
+ if (sysfile || !Len(dirname)) {
+ Delete(dirname);
+ dirname = 0;
+ }
+ if (dirname) {
+ int len = Len(dirname);
+ Delslice(dirname, len - 1, len); /* Kill trailing directory delimiter */
+ Swig_push_directory(dirname);
+ }
+ s2 = Preprocessor_parse(s1);
+ if (dirname) {
+ Swig_pop_directory();
+ }
+ if (Equal(decl, kpp_dimport)) {
+ pop_imported();
+ }
+ addline(ns, s2, allow);
+ Append(ns, "%endoffile");
+ Delete(s2);
+ Delete(dirname);
+ Delete(s1);
+ }
+ Delete(fn);
+ Delete(filename_whitespace);
+ Delete(options_whitespace);
+ }
+ state = 1;
+ } else if (Equal(decl, kpp_dbeginfile)) {
+ /* Got an internal directive marking the beginning of an included file: %beginfile ... %endoffile */
+ filelevel++;
+ start_line = Getline(s);
+ copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
+ Append(chunk, decl);
+ state = 120;
+ } else if (Equal(decl, kpp_dline)) {
+ /* Got a line directive */
+ state = 1;
+ } else if (Equal(decl, kpp_ddefine)) {
+ /* Got a define directive */
+ dlevel++;
+ copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
+ Clear(value);
+ copy_location(s, value);
+ state = 150;
+ } else {
+ Append(chunk, decl);
+ state = 1;
+ }
+ } else {
+ Putc(c, decl);
+ }
+ break;
+
+ /* Searching for the end of a %beginfile block */
+ case 120:
+ Putc(c, chunk);
+ if (c == '%') {
+ const char *bf = "beginfile";
+ const char *ef = "endoffile";
+ char statement[10];
+ int i = 0;
+ for (i = 0; i < 9;) {
+ c = Getc(s);
+ Putc(c, chunk);
+ statement[i++] = (char)c;
+ if (strncmp(statement, bf, i) && strncmp(statement, ef, i))
+ break;
+ }
+ c = Getc(s);
+ Ungetc(c, s);
+ if ((i == 9) && (isspace(c))) {
+ if (strncmp(statement, bf, i) == 0) {
+ ++filelevel;
+ } else if (strncmp(statement, ef, i) == 0) {
+ --filelevel;
+ if (!filelevel) {
+ /* Reached end of included file */
+ addline(ns, chunk, allow);
+ Clear(chunk);
+ copy_location(s, chunk);
+ state = 1;
+ }
+ }
+ }
+ }
+ break;
+
+ /* Searching for the end of a %define statement */
+ case 150:
+ Putc(c, value);
+ if (c == '%') {
+ const char *ed = "enddef";
+ const char *df = "define";
+ char statement[7];
+ int i = 0;
+ for (i = 0; i < 6;) {
+ c = Getc(s);
+ Putc(c, value);
+ statement[i++] = (char)c;
+ if (strncmp(statement, ed, i) && strncmp(statement, df, i))
+ break;
+ }
+ c = Getc(s);
+ Ungetc(c, s);
+ if ((i == 6) && (isspace(c))) {
+ if (strncmp(statement, df, i) == 0) {
+ ++dlevel;
+ } else {
+ if (strncmp(statement, ed, i) == 0) {
+ --dlevel;
+ if (!dlevel) {
+ /* Got the macro */
+ for (i = 0; i < 7; i++) {
+ Delitem(value, DOH_END);
+ }
+ if (allow) {
+ Seek(value, 0, SEEK_SET);
+ Preprocessor_define(value, 1);
+ }
+ addline(ns, value, 0);
+ state = 0;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ Printf(stderr, "cpp: Invalid parser state %d\n", state);
+ Exit(EXIT_FAILURE);
+ }
+ }
+ while (level > 0) {
+ Swig_error(Getfile(s), cond_lines[level - 1], "Missing #endif for conditional starting here\n");
+ level--;
+ }
+ if (state == 120) {
+ Swig_error(Getfile(s), start_line, "Missing %%endoffile for file inclusion block starting here\n");
+ }
+ if (state == 150) {
+ Seek(value, 0, SEEK_SET);
+ Swig_error(Getfile(s), Getline(value), "Missing %%enddef for macro starting here\n", Getline(value));
+ }
+ if ((state >= 105) && (state < 107)) {
+ Swig_error(Getfile(s), start_line, "Unterminated %%{ ... %%} block\n");
+ }
+ if ((state >= 30) && (state < 40)) {
+ Swig_error(Getfile(s), start_line, "Unterminated comment\n");
+ }
+
+ copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
+
+ /* DelScope(scp); */
+ Delete(decl);
+ Delete(id);
+ Delete(value);
+ Delete(comment);
+ Delete(chunk);
+
+ return ns;
+}
diff --git a/contrib/tools/swig/Source/Preprocessor/expr.c b/contrib/tools/swig/Source/Preprocessor/expr.c
new file mode 100644
index 00000000000..c14f7ed81bf
--- /dev/null
+++ b/contrib/tools/swig/Source/Preprocessor/expr.c
@@ -0,0 +1,515 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * expr.c
+ *
+ * Integer arithmetic expression evaluator used to handle expressions
+ * encountered during preprocessing.
+ *
+ * Note that this is used for expressions in `#if` and the like, but not
+ * for expressions in `#define` which SWIG wraps as constants - for those
+ * we inject a `%constant` directive which is handled by the parser in
+ * `Source/CParse/parser.y`.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "preprocessor.h"
+
+static Scanner *scan = 0;
+
+typedef struct {
+ /* One of the EXPR_xxx values defined below. */
+ int op;
+ /* op == EXPR_OP: value is the token specifying which operator.
+ *
+ * op == EXPR_VALUE && svalue == NULL: Numeric expression value.
+ *
+ * Otherwise unused.
+ */
+ long value;
+ /* op == EXPR_VALUE: If non-NULL, string expression value; if NULL see value.
+ *
+ * Otherwise unused.
+ */
+ String *svalue;
+} exprval;
+
+#define EXPR_TOP 1
+#define EXPR_VALUE 2
+#define EXPR_OP 3
+#define EXPR_GROUP 4
+
+/* Special token values used here to distinguish from SWIG_TOKEN_MINUS
+ * and SWIG_TOKEN_PLUS (which we use here for a two argument versions).
+ */
+#define OP_UMINUS 100
+#define OP_UPLUS 101
+
+static exprval stack[256]; /* Parsing stack */
+static int sp = 0; /* Stack pointer */
+static int prec[256]; /* Precedence rules */
+static int expr_init = 0; /* Initialization flag */
+static const char *errmsg = 0; /* Parsing error */
+
+/* Initialize the precedence table for various operators. Low values have higher precedence */
+static void init_precedence(void) {
+ prec[SWIG_TOKEN_NOT] = 10;
+ prec[SWIG_TOKEN_LNOT] = 10;
+ prec[OP_UMINUS] = 10;
+ prec[OP_UPLUS] = 10;
+ prec[SWIG_TOKEN_STAR] = 20;
+ prec[SWIG_TOKEN_SLASH] = 20;
+ prec[SWIG_TOKEN_PERCENT] = 20;
+ prec[SWIG_TOKEN_PLUS] = 30;
+ prec[SWIG_TOKEN_MINUS] = 30;
+ prec[SWIG_TOKEN_LSHIFT] = 40;
+ prec[SWIG_TOKEN_RSHIFT] = 40;
+ prec[SWIG_TOKEN_LESSTHAN] = 50;
+ prec[SWIG_TOKEN_GREATERTHAN] = 50;
+ prec[SWIG_TOKEN_LTEQUAL] = 50;
+ prec[SWIG_TOKEN_GTEQUAL] = 50;
+ prec[SWIG_TOKEN_EQUALTO] = 60;
+ prec[SWIG_TOKEN_NOTEQUAL] = 60;
+ prec[SWIG_TOKEN_AND] = 70;
+ prec[SWIG_TOKEN_XOR] = 80;
+ prec[SWIG_TOKEN_OR] = 90;
+ prec[SWIG_TOKEN_LAND] = 100;
+ prec[SWIG_TOKEN_LOR] = 110;
+ expr_init = 1;
+}
+
+#define UNARY_OP(token) (((token) == SWIG_TOKEN_NOT) || \
+ ((token) == SWIG_TOKEN_LNOT) || \
+ ((token) == OP_UMINUS) || \
+ ((token) == OP_UPLUS))
+
+/* Reduce a single operator on the stack */
+/* return 0 on failure, 1 on success */
+static int reduce_op(void) {
+ long op_token = stack[sp - 1].value;
+ assert(sp > 0);
+ assert(stack[sp - 1].op == EXPR_OP);
+ /* do some basic checking first: */
+ if (stack[sp].op != EXPR_VALUE) {
+ errmsg = "Right-hand side is not value";
+ return 0;
+ }
+ if (UNARY_OP(op_token)) {
+ if (stack[sp].svalue) {
+ errmsg = "Syntax error: attempt to apply unary operator to string";
+ return 0;
+ }
+ } else {
+ /* binary operator: */
+ if (sp == 1) {
+ /* top of stack: don't attempt to use sp-2! */
+ errmsg = "Missing left-hand side for binary operator";
+ return 0;
+ }
+ if (stack[sp].op != EXPR_VALUE) {
+ errmsg = "Left-hand side of binary operator is not a value";
+ return 0;
+ }
+ if ((!stack[sp - 2].svalue) != (!stack[sp].svalue)) {
+ errmsg = "Can't mix strings and integers in expression";
+ return 0;
+ }
+ }
+ if (stack[sp].svalue) {
+ /* A binary string expression */
+ switch (stack[sp - 1].value) {
+ case SWIG_TOKEN_EQUALTO:
+ stack[sp - 2].value = (Strcmp(stack[sp - 2].svalue, stack[sp].svalue) == 0);
+ Delete(stack[sp - 2].svalue);
+ Delete(stack[sp].svalue);
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_NOTEQUAL:
+ stack[sp - 2].value = (Strcmp(stack[sp - 2].svalue, stack[sp].svalue) != 0);
+ Delete(stack[sp - 2].svalue);
+ Delete(stack[sp].svalue);
+ sp -= 2;
+ break;
+ default:
+ errmsg = "Syntax error: bad binary operator for strings";
+ return 0;
+ }
+ } else {
+ switch (op_token) {
+ case SWIG_TOKEN_STAR:
+ stack[sp - 2].value = stack[sp - 2].value * stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_EQUALTO:
+ stack[sp - 2].value = stack[sp - 2].value == stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_NOTEQUAL:
+ stack[sp - 2].value = stack[sp - 2].value != stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_PLUS:
+ stack[sp - 2].value = stack[sp - 2].value + stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_MINUS:
+ stack[sp - 2].value = stack[sp - 2].value - stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_AND:
+ stack[sp - 2].value = stack[sp - 2].value & stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_LAND:
+ stack[sp - 2].value = stack[sp - 2].value && stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_OR:
+ stack[sp - 2].value = stack[sp - 2].value | stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_LOR:
+ stack[sp - 2].value = stack[sp - 2].value || stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_XOR:
+ stack[sp - 2].value = stack[sp - 2].value ^ stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_LESSTHAN:
+ stack[sp - 2].value = stack[sp - 2].value < stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_GREATERTHAN:
+ stack[sp - 2].value = stack[sp - 2].value > stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_LTEQUAL:
+ stack[sp - 2].value = stack[sp - 2].value <= stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_GTEQUAL:
+ stack[sp - 2].value = stack[sp - 2].value >= stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_NOT:
+ stack[sp - 1].value = ~stack[sp].value;
+ sp--;
+ break;
+ case SWIG_TOKEN_LNOT:
+ stack[sp - 1].value = !stack[sp].value;
+ sp--;
+ break;
+ case OP_UMINUS:
+ stack[sp - 1].value = -stack[sp].value;
+ sp--;
+ break;
+ case OP_UPLUS:
+ stack[sp - 1].value = stack[sp].value;
+ sp--;
+ break;
+ case SWIG_TOKEN_SLASH:
+ if (stack[sp].value != 0) {
+ stack[sp - 2].value = stack[sp - 2].value / stack[sp].value;
+ sp -= 2;
+ } else {
+ errmsg = "Division by zero in expression";
+ return 0;
+ }
+ break;
+ case SWIG_TOKEN_PERCENT:
+ if (stack[sp].value != 0) {
+ stack[sp - 2].value = stack[sp - 2].value % stack[sp].value;
+ sp -= 2;
+ } else {
+ errmsg = "Modulo by zero in expression";
+ return 0;
+ }
+ break;
+ case SWIG_TOKEN_LSHIFT:
+ stack[sp - 2].value = stack[sp - 2].value << stack[sp].value;
+ sp -= 2;
+ break;
+ case SWIG_TOKEN_RSHIFT:
+ stack[sp - 2].value = stack[sp - 2].value >> stack[sp].value;
+ sp -= 2;
+ break;
+ default:
+ errmsg = "Syntax error: bad operator";
+ return 0;
+ }
+ }
+ stack[sp].op = EXPR_VALUE;
+ stack[sp].svalue = 0; /* ensure it's not a string! */
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_expr_init()
+ *
+ * Initialize the expression evaluator
+ * ----------------------------------------------------------------------------- */
+
+void Preprocessor_expr_init(void) {
+ if (!expr_init)
+ init_precedence();
+ if (!scan)
+ scan = NewScanner();
+}
+
+void Preprocessor_expr_delete(void) {
+ DelScanner(scan);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Tokenizer
+ * ----------------------------------------------------------------------------- */
+
+static int expr_token(Scanner * s) {
+ int t;
+ while (1) {
+ t = Scanner_token(s);
+ if (!((t == SWIG_TOKEN_BACKSLASH) || (t == SWIG_TOKEN_ENDLINE) || (t == SWIG_TOKEN_COMMENT)))
+ break;
+ }
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_expr()
+ *
+ * Evaluates an arithmetic expression. Returns the result and sets an error code.
+ * ----------------------------------------------------------------------------- */
+
+int Preprocessor_expr(DOH *s, int *error) {
+ int token = 0;
+ int op = 0;
+
+ sp = 0;
+ assert(s);
+ assert(scan);
+
+ Seek(s, 0, SEEK_SET);
+ /* Printf(stdout,"evaluating : '%s'\n", s); */
+ *error = 0;
+ Scanner_clear(scan);
+ Scanner_push(scan, s);
+
+ /* Put initial state onto the stack */
+ stack[sp].op = EXPR_TOP;
+
+ while (1) {
+ /* Look at the top of the stack */
+ switch (stack[sp].op) {
+ case EXPR_TOP:
+ /* EXPR_TOP is a place-holder which can only appear on the top of the
+ * stack. We can reduce it to any expression - a number, a string, an
+ * unary operator, or another expression enclosed in parentheses.
+ */
+ token = expr_token(scan);
+ if (!token) {
+ errmsg = "Expected an expression";
+ *error = 1;
+ return 0;
+ }
+ if (token == SWIG_TOKEN_BOOL) {
+ /* A boolean value. Reduce EXPR_TOP to an EXPR_VALUE */
+ String *cc = Scanner_text(scan);
+ if (Strcmp(cc, "true") == 0) {
+ stack[sp].value = (long) 1;
+ } else {
+ stack[sp].value = (long) 0;
+ }
+ stack[sp].svalue = 0;
+ stack[sp].op = EXPR_VALUE;
+ } else if ((token == SWIG_TOKEN_INT) || (token == SWIG_TOKEN_UINT) || (token == SWIG_TOKEN_LONG) || (token == SWIG_TOKEN_ULONG)) {
+ /* A number. Reduce EXPR_TOP to an EXPR_VALUE */
+ char *c = Char(Scanner_text(scan));
+ if (c[0] == '0' && (c[1] == 'b' || c[1] == 'B')) {
+ /* strtol() doesn't handle binary constants */
+ stack[sp].value = (long) strtol(c + 2, 0, 2);
+ } else {
+ stack[sp].value = (long) strtol(c, 0, 0);
+ }
+ stack[sp].svalue = 0;
+ stack[sp].op = EXPR_VALUE;
+ } else if ((token == SWIG_TOKEN_MINUS) || (token == SWIG_TOKEN_PLUS) || (token == SWIG_TOKEN_LNOT) || (token == SWIG_TOKEN_NOT)) {
+ if (token == SWIG_TOKEN_MINUS)
+ token = OP_UMINUS;
+ else if (token == SWIG_TOKEN_PLUS)
+ token = OP_UPLUS;
+ stack[sp].value = token;
+ stack[sp].op = EXPR_OP;
+ sp++;
+ stack[sp].op = EXPR_TOP;
+ } else if (token == SWIG_TOKEN_LPAREN) {
+ stack[sp].op = EXPR_GROUP;
+ sp++;
+ stack[sp].op = EXPR_TOP;
+ } else if (token == SWIG_TOKEN_ENDLINE) {
+ } else if (token == SWIG_TOKEN_STRING) {
+ stack[sp].svalue = NewString(Scanner_text(scan));
+ stack[sp].op = EXPR_VALUE;
+ } else if (token == SWIG_TOKEN_ID) {
+ int next_token = expr_token(scan);
+ if (next_token == SWIG_TOKEN_LPAREN) {
+ /* This is a use of an unknown function-like macro so we emit a
+ * warning.
+ */
+ errmsg = "Use of undefined function-like macro";
+ *error = 1;
+ return 0;
+ }
+ Scanner_pushtoken(scan, next_token, Scanner_text(scan));
+
+ /* Defined macros have been expanded already so this is an unknown
+ * macro, which gets treated as zero.
+ */
+ stack[sp].value = 0;
+ stack[sp].svalue = 0;
+ stack[sp].op = EXPR_VALUE;
+ } else if (token == SWIG_TOKEN_FLOAT || token == SWIG_TOKEN_DOUBLE || token == SWIG_TOKEN_LONGDOUBLE) {
+ errmsg = "Floating point constant in preprocessor expression";
+ *error = 1;
+ return 0;
+ } else
+ goto syntax_error;
+ break;
+ case EXPR_VALUE:
+ /* A value is on top of the stack. We may reduce or evaluate depending
+ * on what the next token is.
+ */
+ token = expr_token(scan);
+ if (!token) {
+ /* End of input. Might have to reduce if an operator is on stack */
+ while (sp > 0) {
+ if (stack[sp - 1].op == EXPR_OP) {
+ if (!reduce_op())
+ goto reduce_error;
+ } else if (stack[sp - 1].op == EXPR_GROUP) {
+ errmsg = "Missing \')\'";
+ *error = 1;
+ return 0;
+ } else
+ goto syntax_error;
+ }
+ return stack[sp].value;
+ }
+ /* Token must be an operator */
+ switch (token) {
+ case SWIG_TOKEN_STAR:
+ case SWIG_TOKEN_EQUALTO:
+ case SWIG_TOKEN_NOTEQUAL:
+ case SWIG_TOKEN_PLUS:
+ case SWIG_TOKEN_MINUS:
+ case SWIG_TOKEN_AND:
+ case SWIG_TOKEN_LAND:
+ case SWIG_TOKEN_OR:
+ case SWIG_TOKEN_LOR:
+ case SWIG_TOKEN_XOR:
+ case SWIG_TOKEN_LESSTHAN:
+ case SWIG_TOKEN_GREATERTHAN:
+ case SWIG_TOKEN_LTEQUAL:
+ case SWIG_TOKEN_GTEQUAL:
+ case SWIG_TOKEN_SLASH:
+ case SWIG_TOKEN_PERCENT:
+ case SWIG_TOKEN_LSHIFT:
+ case SWIG_TOKEN_RSHIFT:
+ if ((sp == 0) || (stack[sp - 1].op == EXPR_GROUP)) {
+ /* No possibility of reduce. Push operator and expression */
+ sp++;
+ stack[sp].op = EXPR_OP;
+ stack[sp].value = token;
+ sp++;
+ stack[sp].op = EXPR_TOP;
+ } else {
+ if (stack[sp - 1].op != EXPR_OP)
+ goto syntax_error_expected_operator;
+ op = stack[sp - 1].value; /* Previous operator */
+
+ /* Now, depending on the precedence relationship between the last operator and the current
+ we will reduce or push */
+
+ if (prec[op] <= prec[token]) {
+ /* Reduce the previous operator */
+ if (!reduce_op())
+ goto reduce_error;
+ }
+ sp++;
+ stack[sp].op = EXPR_OP;
+ stack[sp].value = token;
+ sp++;
+ stack[sp].op = EXPR_TOP;
+ }
+ break;
+ case SWIG_TOKEN_RPAREN:
+ if (sp == 0)
+ goto extra_rparen;
+
+ /* Might have to reduce operators first */
+ while ((sp > 0) && (stack[sp - 1].op == EXPR_OP)) {
+ if (!reduce_op())
+ goto reduce_error;
+ }
+ if ((sp == 0) || (stack[sp - 1].op != EXPR_GROUP))
+ goto extra_rparen;
+ stack[sp - 1].op = EXPR_VALUE;
+ stack[sp - 1].value = stack[sp].value;
+ stack[sp - 1].svalue = stack[sp].svalue;
+ sp--;
+ break;
+ case SWIG_TOKEN_LTEQUALGT:
+ goto spaceship_not_allowed;
+ default:
+ goto syntax_error_expected_operator;
+ break;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Internal error in expression evaluator.\n");
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+syntax_error:
+ errmsg = "Syntax error";
+ *error = 1;
+ return 0;
+
+syntax_error_expected_operator:
+ errmsg = "Syntax error: expected operator";
+ *error = 1;
+ return 0;
+
+reduce_error:
+ /* errmsg has been set by reduce_op */
+ *error = 1;
+ return 0;
+
+extra_rparen:
+ errmsg = "Extra \')\'";
+ *error = 1;
+ return 0;
+
+spaceship_not_allowed:
+ errmsg = "Spaceship operator (<=>) not allowed in preprocessor expression";
+ *error = 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Preprocessor_expr_error()
+ *
+ * Return error message set by the evaluator (if any)
+ * ----------------------------------------------------------------------------- */
+
+const char *Preprocessor_expr_error(void) {
+ return errmsg;
+}
diff --git a/contrib/tools/swig/Source/Preprocessor/preprocessor.h b/contrib/tools/swig/Source/Preprocessor/preprocessor.h
new file mode 100644
index 00000000000..9f9537bbbcc
--- /dev/null
+++ b/contrib/tools/swig/Source/Preprocessor/preprocessor.h
@@ -0,0 +1,41 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * preprocessor.h
+ *
+ * SWIG preprocessor module.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_PREPROCESSOR_H
+#define SWIG_PREPROCESSOR_H
+
+#include "swigwarn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern int Preprocessor_expr(String *s, int *error);
+ extern const char *Preprocessor_expr_error(void);
+ extern Hash *Preprocessor_define(const_String_or_char_ptr str, int swigmacro);
+ extern void Preprocessor_undef(const_String_or_char_ptr name);
+ extern int Preprocessor_defined(const_String_or_char_ptr str);
+ extern void Preprocessor_init(void);
+ extern void Preprocessor_delete(void);
+ extern String *Preprocessor_parse(String *s);
+ extern void Preprocessor_include_all(int);
+ extern void Preprocessor_import_all(int);
+ extern void Preprocessor_ignore_missing(int);
+ extern void Preprocessor_error_as_warning(int);
+ extern List *Preprocessor_depend(void);
+ extern void Preprocessor_expr_init(void);
+ extern void Preprocessor_expr_delete(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/contrib/tools/swig/Source/README b/contrib/tools/swig/Source/README
new file mode 100644
index 00000000000..08893330889
--- /dev/null
+++ b/contrib/tools/swig/Source/README
@@ -0,0 +1,15 @@
+SWIG Source directory
+
+ Source/DOH - A core set of basic datatypes including
+ strings, lists, hashes, and files. Used
+ extensively by the rest of SWIG.
+
+ Source/Swig - Swig core. Type-system, utility functions.
+
+ Source/Preprocessor - SWIG C Preprocessor
+
+ Source/CParse - SWIG C Parser (still messy)
+
+ Source/Modules - Language modules.
+
+ Source/Include - Include files.
diff --git a/contrib/tools/swig/Source/Swig/cwrap.c b/contrib/tools/swig/Source/Swig/cwrap.c
new file mode 100644
index 00000000000..356ede9cc51
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/cwrap.c
@@ -0,0 +1,1664 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * cwrap.c
+ *
+ * This file defines a variety of wrapping rules for C/C++ handling including
+ * the naming of local variables, calling conventions, and so forth.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+extern int UseWrapperSuffix;
+
+static const char *cresult_variable_name = "result";
+
+static Parm *nonvoid_parms(Parm *p) {
+ if (p) {
+ SwigType *t = Getattr(p, "type");
+ if (SwigType_type(t) == T_VOID)
+ return 0;
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cresult_name_set()
+ *
+ * Change the name of the variable used to hold the return value from C/C++ wrapper functions
+ * from the default "result".
+ * ----------------------------------------------------------------------------- */
+
+void Swig_cresult_name_set(const char *new_name) {
+ cresult_variable_name = new_name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cresult_name()
+ *
+ * Get the name of the variable used to hold the return value from C/C++ wrapper functions
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_cresult_name(void) {
+ return cresult_variable_name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cparm_name()
+ *
+ * Generates a name for the ith argument in an argument list
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cparm_name(Parm *p, int i) {
+ String *name = NewStringf("arg%d", i + 1);
+ if (p) {
+ Setattr(p, "lname", name);
+ }
+
+ return name;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_clocal()
+ *
+ * Creates a string that declares a C local variable type. Converts references
+ * and user defined types to pointers.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_clocal(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr value) {
+ String *decl;
+
+ decl = NewStringEmpty();
+
+ switch (SwigType_type(t)) {
+ case T_REFERENCE:
+ if (value) {
+ String *lstrname = SwigType_lstr(t, name);
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(decl, "%s = (%s) &%s_defvalue", lstrname, lstr, name);
+ Delete(lstrname);
+ Delete(lstr);
+ } else {
+ String *lstrname = SwigType_lstr(t, name);
+ Printf(decl, "%s = 0", lstrname);
+ Delete(lstrname);
+ }
+ break;
+ case T_RVALUE_REFERENCE:
+ if (value) {
+ String *lstrname = SwigType_lstr(t, name);
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(decl, "%s = (%s) &%s_defrvalue", lstrname, lstr, name);
+ Delete(lstrname);
+ Delete(lstr);
+ } else {
+ String *lstrname = SwigType_lstr(t, name);
+ Printf(decl, "%s = 0", lstrname);
+ Delete(lstrname);
+ }
+ break;
+ case T_VOID:
+ break;
+ case T_VARARGS:
+ Printf(decl, "void *%s = 0", name);
+ break;
+
+ default:
+ if (value) {
+ String *lcaststr = SwigType_lcaststr(t, value);
+ String *lstr = SwigType_lstr(t, 0);
+ String *lstrn = SwigType_lstr(t, name);
+ Printf(decl, "%s = (%s) %s", lstrn, lstr, lcaststr);
+ Delete(lcaststr);
+ Delete(lstr);
+ Delete(lstrn);
+ } else {
+ String *lstrname = SwigType_lstr(t, name);
+ Append(decl, lstrname);
+ Delete(lstrname);
+ }
+ }
+ return decl;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_wrapped_var_convert()
+ *
+ * Converts a member variable for use in the get and set wrapper methods.
+ * This function only converts user defined types to pointers.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_wrapped_var_type(SwigType *t, int varcref) {
+ SwigType *ty;
+
+ if (!Strstr(t, "enum $unnamed")) {
+ ty = Copy(t);
+ } else {
+ /* Change the type for unnamed enum instance variables */
+ ty = NewString("int");
+ }
+
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ if (cparse_cplusplus) {
+ if (!SwigType_isconst(ty))
+ SwigType_add_qualifier(ty, "const");
+ SwigType_add_reference(ty);
+ } else {
+ return Copy(ty);
+ }
+ } else {
+ SwigType_add_pointer(ty);
+ }
+ }
+ return ty;
+}
+
+static String *Swig_wrapped_member_var_type(SwigType *t, int varcref) {
+ SwigType *ty;
+
+ if (!Strstr(t, "enum $unnamed")) {
+ ty = Copy(t);
+ } else {
+ /* Change the type for unnamed enum instance variables */
+ ty = NewString("int");
+ }
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ if (cparse_cplusplus) {
+ if (!SwigType_isconst(ty))
+ SwigType_add_qualifier(ty, "const");
+ SwigType_add_reference(ty);
+ } else {
+ return Copy(ty);
+ }
+ } else {
+ SwigType_add_pointer(ty);
+ }
+ }
+ return ty;
+}
+
+
+static String *Swig_wrapped_var_deref(SwigType *t, const_String_or_char_ptr name, int varcref) {
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ if (cparse_cplusplus) {
+ return NewStringf("*%s", name);
+ } else {
+ return NewStringf("%s", name);
+ }
+ } else {
+ return NewStringf("*%s", name);
+ }
+ } else {
+ return SwigType_rcaststr(t, name);
+ }
+}
+
+static String *Swig_wrapped_var_assign(SwigType *t, const_String_or_char_ptr name, int varcref) {
+ if (SwigType_isclass(t)) {
+ if (varcref) {
+ return NewStringf("%s", name);
+ } else {
+ return NewStringf("&%s", name);
+ }
+ } else {
+ return SwigType_lcaststr(t, name);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cargs()
+ *
+ * Emit all of the local variables for a list of parameters. Returns the
+ * number of parameters.
+ * Default values for the local variables are only emitted if the compact default
+ * argument behaviour is required.
+ * ----------------------------------------------------------------------------- */
+int Swig_cargs(Wrapper *w, ParmList *p) {
+ int i = 0;
+ int compactdefargs = ParmList_is_compactdefargs(p);
+
+ while (p != 0) {
+ String *lname = Swig_cparm_name(p, i);
+ SwigType *pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *local = 0;
+ String *type = Getattr(p, "type");
+ /* default values only emitted if in compact default args mode */
+ String *pvalue = (compactdefargs) ? Getattr(p, "value") : 0;
+
+ /* When using compactdefaultargs, the code generated initialises a variable via a constructor call that accepts the
+ * default value as a parameter. The default constructor is not called and therefore SwigValueWrapper is not needed. */
+ SwigType *altty = pvalue ? 0 : SwigType_alttype(type, 0);
+
+ int tycode = SwigType_type(type);
+ if (tycode == T_REFERENCE) {
+ if (pvalue) {
+ SwigType *tvalue;
+ String *defname, *defvalue, *rvalue, *qvalue;
+ rvalue = SwigType_typedef_resolve_all(pvalue);
+ qvalue = SwigType_typedef_qualified(rvalue);
+ defname = NewStringf("%s_defvalue", lname);
+ tvalue = Copy(type);
+ SwigType_del_reference(tvalue);
+ tycode = SwigType_type(tvalue);
+ if (tycode != T_USER) {
+ /* plain primitive type, we copy the def value */
+ String *lstr = SwigType_lstr(tvalue, defname);
+ defvalue = NewStringf("%s = %s", lstr, qvalue);
+ Delete(lstr);
+ } else {
+ /* user type, we copy the reference value */
+ String *str = SwigType_str(type, defname);
+ defvalue = NewStringf("%s = %s", str, qvalue);
+ Delete(str);
+ }
+ Wrapper_add_localv(w, defname, defvalue, NIL);
+ Delete(tvalue);
+ Delete(rvalue);
+ Delete(qvalue);
+ Delete(defname);
+ Delete(defvalue);
+ }
+ } else if (tycode == T_RVALUE_REFERENCE) {
+ if (pvalue) {
+ SwigType *tvalue;
+ String *defname, *defvalue, *rvalue, *qvalue;
+ rvalue = SwigType_typedef_resolve_all(pvalue);
+ qvalue = SwigType_typedef_qualified(rvalue);
+ defname = NewStringf("%s_defrvalue", lname);
+ tvalue = Copy(type);
+ SwigType_del_rvalue_reference(tvalue);
+ tycode = SwigType_type(tvalue);
+ if (tycode != T_USER) {
+ /* plain primitive type, we copy the def value */
+ String *lstr = SwigType_lstr(tvalue, defname);
+ defvalue = NewStringf("%s = %s", lstr, qvalue);
+ Delete(lstr);
+ } else {
+ /* user type, we copy the reference value */
+ String *str = SwigType_str(type, defname);
+ defvalue = NewStringf("%s = %s", str, qvalue);
+ Delete(str);
+ }
+ Wrapper_add_localv(w, defname, defvalue, NIL);
+ Delete(tvalue);
+ Delete(rvalue);
+ Delete(qvalue);
+ Delete(defname);
+ Delete(defvalue);
+ }
+ } else if (!pvalue && ((tycode == T_POINTER) || (tycode == T_STRING) || (tycode == T_WSTRING) || (tycode == T_ARRAY))) {
+ pvalue = (String *) "0";
+ }
+ if (!altty) {
+ local = Swig_clocal(pt, lname, pvalue);
+ } else {
+ local = Swig_clocal(altty, lname, pvalue);
+ Delete(altty);
+ }
+ Wrapper_add_localv(w, lname, local, NIL);
+ Delete(local);
+ i++;
+ }
+ Delete(lname);
+ p = nextSibling(p);
+ }
+ return (i);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cresult()
+ *
+ * This function generates the C code needed to set the result of a C
+ * function call.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cresult(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ String *fcall;
+
+ fcall = NewStringEmpty();
+ switch (SwigType_type(t)) {
+ case T_VOID:
+ break;
+ case T_REFERENCE:
+ {
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(fcall, "%s = (%s) &", name, lstr);
+ Delete(lstr);
+ }
+ break;
+ case T_RVALUE_REFERENCE:
+ {
+ String *const_lvalue_str;
+ String *lstr = SwigType_lstr(t, 0);
+ SwigType *tt = Copy(t);
+ SwigType_del_rvalue_reference(tt);
+ SwigType_add_qualifier(tt, "const");
+ SwigType_add_reference(tt);
+ const_lvalue_str = SwigType_rcaststr(tt, 0);
+
+ Printf(fcall, "%s = (%s) &%s", name, lstr, const_lvalue_str);
+
+ Delete(const_lvalue_str);
+ Delete(tt);
+ Delete(lstr);
+ }
+ break;
+ case T_USER:
+ Printf(fcall, "%s = ", name);
+ break;
+
+ default:
+ /* Normal return value */
+ {
+ String *lstr = SwigType_lstr(t, 0);
+ Printf(fcall, "%s = (%s)", name, lstr);
+ Delete(lstr);
+ }
+ break;
+ }
+
+ /* Now print out function call */
+ Append(fcall, decl);
+
+ /* A sick hack */
+ {
+ char *c = Char(decl) + Len(decl) - 1;
+ if (!((*c == ';') || (*c == '}')))
+ Append(fcall, ";");
+ }
+
+ return fcall;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cfunction_call()
+ *
+ * Creates a string that calls a C function using the local variable rules
+ * defined above.
+ *
+ * name(arg0, arg1, arg2, ... argn)
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cfunction_call(const_String_or_char_ptr name, ParmList *parms) {
+ String *func;
+ int i = 0;
+ int comma = 0;
+ Parm *p = parms;
+ String *nname;
+
+ func = NewStringEmpty();
+ nname = SwigType_namestr(name);
+
+ /*
+ SWIGTEMPLATEDISAMBIGUATOR is compiler dependent (swiglabels.swg),
+ - SUN Studio 9 requires 'template',
+ - gcc-3.4 forbids the use of 'template'.
+ the rest seems not caring very much,
+ */
+ if (SwigType_istemplate(name)) {
+ String *prefix = Swig_scopename_prefix(nname);
+ if (!prefix || Len(prefix) == 0) {
+ Printf(func, "%s(", nname);
+ } else {
+ String *last = Swig_scopename_last(nname);
+ Printf(func, "%s::SWIGTEMPLATEDISAMBIGUATOR %s(", prefix, last);
+ Delete(last);
+ }
+ Delete(prefix);
+ } else {
+ Printf(func, "%s(", nname);
+ }
+ Delete(nname);
+
+ while (p) {
+ SwigType *pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ SwigType *rpt = SwigType_typedef_resolve_all(pt);
+ String *pname = Swig_cparm_name(p, i);
+ String *rcaststr = SwigType_rcaststr(rpt, pname);
+
+ if (comma) {
+ Append(func, ",");
+ }
+
+ if (cparse_cplusplus && SwigType_type(rpt) == T_USER)
+ Printv(func, "SWIG_STD_MOVE(", rcaststr, ")", NIL);
+ else
+ Printv(func, rcaststr, NIL);
+
+ Delete(rpt);
+ Delete(pname);
+ Delete(rcaststr);
+ comma = 1;
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Append(func, ")");
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cmethod_call()
+ *
+ * Generates a string that calls a C++ method from a list of parameters.
+ *
+ * arg0->name(arg1, arg2, arg3, ..., argn)
+ *
+ * self is an argument that defines how to handle the first argument. Normally,
+ * it should be set to "this->". With C++ proxy classes enabled, it could be
+ * set to "(*this)->" or some similar sequence.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_cmethod_call(const_String_or_char_ptr name, ParmList *parms, const_String_or_char_ptr self, String *explicit_qualifier, SwigType *director_type) {
+ String *func, *nname;
+ int i = 0;
+ Parm *p = parms;
+ SwigType *pt;
+ int comma = 0;
+
+ func = NewStringEmpty();
+ if (!p)
+ return func;
+
+ if (!self)
+ self = "(this)->";
+ Append(func, self);
+
+ if (SwigType_istemplate(name) && (strncmp(Char(name), "operator ", 9) == 0)) {
+ /* fix for template + operators and compilers like gcc 3.3.5 */
+ String *tprefix = SwigType_templateprefix(name);
+ nname = tprefix;
+ } else {
+ nname = SwigType_namestr(name);
+ }
+
+ if (director_type) {
+ const char *pname = "darg";
+ String *rcaststr = SwigType_rcaststr(director_type, pname);
+ Replaceall(func, "this", rcaststr);
+ Delete(rcaststr);
+ } else {
+ pt = Getattr(p, "type");
+
+ /* If the method is invoked through a dereferenced pointer, we don't add any casts
+ (needed for smart pointers). Otherwise, we cast to the appropriate type */
+
+ if (Strstr(func, "*this")) {
+ String *pname = Swig_cparm_name(p, 0);
+ Replaceall(func, "this", pname);
+ Delete(pname);
+ } else {
+ String *pname = Swig_cparm_name(p, 0);
+ String *rcaststr = SwigType_rcaststr(pt, pname);
+ Replaceall(func, "this", rcaststr);
+ Delete(rcaststr);
+ Delete(pname);
+ }
+
+ /*
+ SWIGTEMPLATEDESIMBUAGATOR is compiler dependent (swiglabels.swg),
+ - SUN Studio 9 requires 'template',
+ - gcc-3.4 forbids the use of 'template' (correctly implementing the ISO C++ standard)
+ the others don't seem to care,
+ */
+ if (SwigType_istemplate(name))
+ Printf(func, "SWIGTEMPLATEDISAMBIGUATOR ");
+
+ if (explicit_qualifier) {
+ Printv(func, explicit_qualifier, "::", NIL);
+ }
+ }
+
+ Printf(func, "%s(", nname);
+
+ i++;
+ p = nextSibling(p);
+ while (p) {
+ pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *pname = Swig_cparm_name(p, i);
+ String *rcaststr = SwigType_rcaststr(pt, pname);
+ if (comma)
+ Append(func, ",");
+ if (cparse_cplusplus && SwigType_type(pt) == T_USER)
+ Printv(func, "SWIG_STD_MOVE(", rcaststr, ")", NIL);
+ else
+ Printv(func, rcaststr, NIL);
+ Delete(rcaststr);
+ Delete(pname);
+ comma = 1;
+ i++;
+ }
+ p = nextSibling(p);
+ }
+ Append(func, ")");
+ Delete(nname);
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cconstructor_call()
+ *
+ * Creates a string that calls a C constructor function.
+ *
+ * calloc(1,sizeof(name));
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cconstructor_call(const_String_or_char_ptr name) {
+ DOH *func;
+
+ func = NewStringEmpty();
+ Printf(func, "calloc(1, sizeof(%s))", name);
+ return func;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cppconstructor_call()
+ *
+ * Creates a string that calls a C function using the local variable rules
+ * defined above.
+ *
+ * name(arg0, arg1, arg2, ... argn)
+ *
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_cppconstructor_base_call(const_String_or_char_ptr name, ParmList *parms, int skip_self) {
+ String *func;
+ String *nname;
+ int i = 0;
+ int comma = 0;
+ Parm *p = parms;
+ SwigType *pt;
+ if (skip_self) {
+ if (p)
+ p = nextSibling(p);
+ i++;
+ }
+ nname = SwigType_namestr(name);
+ func = NewStringEmpty();
+ Printf(func, "new %s(", nname);
+ while (p) {
+ pt = Getattr(p, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *rcaststr = 0;
+ String *pname = 0;
+ if (comma)
+ Append(func, ",");
+ if (!Getattr(p, "arg:byname")) {
+ pname = Swig_cparm_name(p, i);
+ i++;
+ } else {
+ pname = Getattr(p, "value");
+ if (pname)
+ pname = Copy(pname);
+ else
+ pname = Copy(Getattr(p, "name"));
+ }
+ rcaststr = SwigType_rcaststr(pt, pname);
+ if (cparse_cplusplus && SwigType_type(pt) == T_USER)
+ Printv(func, "SWIG_STD_MOVE(", rcaststr, ")", NIL);
+ else
+ Printv(func, rcaststr, NIL);
+ Delete(rcaststr);
+ comma = 1;
+ Delete(pname);
+ }
+ p = nextSibling(p);
+ }
+ Append(func, ")");
+ Delete(nname);
+ return func;
+}
+
+String *Swig_cppconstructor_call(const_String_or_char_ptr name, ParmList *parms) {
+ return Swig_cppconstructor_base_call(name, parms, 0);
+}
+
+static String *Swig_cppconstructor_nodirector_call(const_String_or_char_ptr name, ParmList *parms) {
+ return Swig_cppconstructor_base_call(name, parms, 1);
+}
+
+static String *Swig_cppconstructor_director_call(const_String_or_char_ptr name, ParmList *parms) {
+ return Swig_cppconstructor_base_call(name, parms, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * recursive_flag_search()
+ *
+ * This function searches for the class attribute 'attr' in the class
+ * 'n' or recursively in its bases.
+ *
+ * If you define SWIG_FAST_REC_SEARCH, the method will set the found
+ * 'attr' in the target class 'n'. If not, the method will set the
+ * 'noattr' one. This prevents of having to navigate the entire
+ * hierarchy tree every time, so, it is an O(1) method... or something
+ * like that. However, it populates all the parsed classes with the
+ * 'attr' and/or 'noattr' attributes.
+ *
+ * If you undefine the SWIG_FAST_REC_SEARCH no attribute will be set
+ * while searching. This could be slower for large projects with very
+ * large hierarchy trees... or maybe not. But it will be cleaner.
+ *
+ * Maybe later a swig option can be added to switch at runtime.
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* #define SWIG_FAST_REC_SEARCH 1 */
+static String *recursive_flag_search(Node *n, const String *attr, const String *noattr) {
+ String *f = 0;
+ n = Swig_methodclass(n);
+ if (GetFlag(n, noattr)) {
+ return 0;
+ }
+ f = GetFlagAttr(n, attr);
+ if (f) {
+ return f;
+ } else {
+ List *bl = Getattr(n, "bases");
+ if (bl) {
+ Iterator bi;
+ for (bi = First(bl); bi.item; bi = Next(bi)) {
+ f = recursive_flag_search(bi.item, attr, noattr);
+ if (f) {
+#ifdef SWIG_FAST_REC_SEARCH
+ SetFlagAttr(n, attr, f);
+#endif
+ return f;
+ }
+ }
+ }
+ }
+#ifdef SWIG_FAST_REC_SEARCH
+ SetFlag(n, noattr);
+#endif
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_unref_call()
+ *
+ * Find the "feature:unref" call, if any.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_unref_call(Node *n) {
+ String *unref = recursive_flag_search(n, "feature:unref", "feature:nounref");
+ if (unref) {
+ String *pname = Swig_cparm_name(0, 0);
+ unref = NewString(unref);
+ Replaceall(unref, "$this", pname);
+ Replaceall(unref, "$self", pname);
+ Delete(pname);
+ }
+ return unref;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_ref_call()
+ *
+ * Find the "feature:ref" call, if any.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_ref_call(Node *n, const String *lname) {
+ String *ref = recursive_flag_search(n, "feature:ref", "feature:noref");
+ if (ref) {
+ ref = NewString(ref);
+ Replaceall(ref, "$this", lname);
+ Replaceall(ref, "$self", lname);
+ }
+ return ref;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cdestructor_call()
+ *
+ * Creates a string that calls a C destructor function.
+ *
+ * free((char *) arg0);
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cdestructor_call(Node *n) {
+ Node *cn = Swig_methodclass(n);
+ String *unref = Swig_unref_call(cn);
+
+ if (unref) {
+ return unref;
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ String *call = NewStringf("free((char *) %s);", pname);
+ Delete(pname);
+ return call;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cppdestructor_call()
+ *
+ * Creates a string that calls a C destructor function.
+ *
+ * delete arg1;
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cppdestructor_call(Node *n) {
+ Node *cn = Swig_methodclass(n);
+ String *unref = Swig_unref_call(cn);
+ if (unref) {
+ return unref;
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ String *call = NewStringf("delete %s;", pname);
+ Delete(pname);
+ return call;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_cmemberset_call()
+ *
+ * Generates a string that sets the name of a member in a C++ class or C struct.
+ *
+ * arg0->name = arg1
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, String *self, int varcref) {
+ String *func;
+ String *pname0 = Swig_cparm_name(0, 0);
+ String *pname1 = Swig_cparm_name(0, 1);
+ func = NewStringEmpty();
+ if (!self)
+ self = NewString("(this)->");
+ else
+ self = NewString(self);
+ Replaceall(self, "this", pname0);
+ if (SwigType_type(type) != T_ARRAY) {
+ if (!Strstr(type, "enum $unnamed")) {
+ String *dref = Swig_wrapped_var_deref(type, pname1, varcref);
+ 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);
+ }
+ }
+ Delete(self);
+ Delete(pname0);
+ Delete(pname1);
+ return (func);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_cmemberget_call()
+ *
+ * Generates a string that sets the name of a member in a C++ class or C struct.
+ *
+ * arg0->name
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String *self, int varcref) {
+ String *func;
+ String *call;
+ String *pname0 = Swig_cparm_name(0, 0);
+ if (!self)
+ self = NewString("(this)->");
+ else
+ self = NewString(self);
+ Replaceall(self, "this", pname0);
+ func = NewStringEmpty();
+ call = Swig_wrapped_var_assign(t, "", varcref);
+ Printf(func, "%s (%s%s)", call, self, name);
+ Delete(self);
+ Delete(call);
+ Delete(pname0);
+ return func;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_replace_special_variables()
+ *
+ * Replaces special variables with a value from the supplied node
+ * ----------------------------------------------------------------------------- */
+void Swig_replace_special_variables(Node *n, Node *parentnode, String *code) {
+ Node *parentclass = parentnode;
+ String *overloaded = Getattr(n, "sym:overloaded");
+ Replaceall(code, "$name", Getattr(n, "name"));
+ Replaceall(code, "$symname", Getattr(n, "sym:name"));
+ Replaceall(code, "$wrapname", Getattr(n, "wrap:name"));
+ Replaceall(code, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : "");
+
+ if (Strstr(code, "$decl")) {
+ String *decl = Swig_name_decl(n);
+ Replaceall(code, "$decl", decl);
+ Delete(decl);
+ }
+ if (Strstr(code, "$fulldecl")) {
+ String *fulldecl = Swig_name_fulldecl(n);
+ Replaceall(code, "$fulldecl", fulldecl);
+ Delete(fulldecl);
+ }
+
+ if (parentclass && !Equal(nodeType(parentclass), "class"))
+ parentclass = 0;
+ if (Strstr(code, "$parentclasssymname")) {
+ String *parentclasssymname = 0;
+ if (parentclass)
+ parentclasssymname = Getattr(parentclass, "sym:name");
+ Replaceall(code, "$parentclasssymname", parentclasssymname ? parentclasssymname : "");
+ }
+ if (Strstr(code, "$parentclassname")) {
+ String *parentclassname = 0;
+ if (parentclass)
+ parentclassname = Getattr(parentclass, "name");
+ Replaceall(code, "$parentclassname", parentclassname ? SwigType_str(parentclassname, NULL) : "");
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * extension_code()
+ *
+ * Generates an extension function (a function defined in %extend)
+ *
+ * return_type function_name(parms) code
+ *
+ * ----------------------------------------------------------------------------- */
+static String *extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
+ String *parms_str = cplusplus ? ParmList_str_defaultargs(parms) : ParmList_str(parms);
+ String *sig = NewStringf("%s(%s)", function_name, (cplusplus || Len(parms_str)) ? parms_str : "void");
+ String *rt_sig = SwigType_str(return_type, sig);
+ String *body = NewStringf("SWIGINTERN %s", rt_sig);
+ Printv(body, code, "\n", NIL);
+ if (Strchr(body, '$')) {
+ Swig_replace_special_variables(n, parentNode(parentNode(n)), body);
+ if (self)
+ Replaceall(body, "$self", self);
+ }
+ Delete(parms_str);
+ Delete(sig);
+ Delete(rt_sig);
+ return body;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_add_extension_code()
+ *
+ * Generates an extension function (a function defined in %extend) and
+ * adds it to the "wrap:code" attribute of a node
+ *
+ * See also extension_code()
+ *
+ * ----------------------------------------------------------------------------- */
+int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
+ String *body = extension_code(n, function_name, parms, return_type, code, cplusplus, self);
+ Setattr(n, "wrap:code", body);
+ Delete(body);
+ return SWIG_OK;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_MethodToFunction(Node *n)
+ *
+ * Converts a C++ method node to a function accessor function.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director) {
+ String *name;
+ ParmList *parms;
+ SwigType *type;
+ Parm *p;
+ String *self = 0;
+ int is_smart_pointer_overload = 0;
+ String *qualifier = Getattr(n, "qualifier");
+ String *directorScope = NewString(nspace);
+
+ Replace(directorScope, NSPACE_SEPARATOR, "_", DOH_REPLACE_ANY);
+
+ /* If smart pointer without const overload or mutable method, change self dereferencing */
+ if (flags & CWRAP_SMART_POINTER) {
+ if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
+ if (qualifier && strncmp(Char(qualifier), "q(const)", 8) == 0) {
+ self = NewString("(*(this))->");
+ is_smart_pointer_overload = 1;
+ }
+ else if (Swig_storage_isstatic(n)) {
+ String *cname = Getattr(n, "extendsmartclassname") ? Getattr(n, "extendsmartclassname") : classname;
+ String *ctname = SwigType_namestr(cname);
+ self = NewStringf("(*(%s const *)this)->", ctname);
+ is_smart_pointer_overload = 1;
+ Delete(ctname);
+ }
+ else {
+ self = NewString("(*this)->");
+ }
+ } else {
+ self = NewString("(*this)->");
+ }
+ }
+
+ /* If node is a member template expansion, we don't allow added code */
+ if (Getattr(n, "templatetype"))
+ flags &= ~(CWRAP_EXTEND);
+
+ name = Getattr(n, "name");
+ parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
+
+ type = NewString(classname);
+ if (qualifier) {
+ SwigType_push(type, qualifier);
+ }
+ SwigType_add_pointer(type);
+ p = NewParm(type, "self", n);
+ Setattr(p, "self", "1");
+ Setattr(p, "hidden","1");
+ /*
+ Disable the 'this' ownership in 'self' to manage inplace
+ operations like:
+
+ A& A::operator+=(int i) { ...; return *this;}
+
+ Here the 'self' parameter ownership needs to be disabled since
+ there could be two objects sharing the same 'this' pointer: the
+ input and the result one. And worse, the pointer could be deleted
+ in one of the objects (input), leaving the other (output) with
+ just a seg. fault to happen.
+
+ To avoid the previous problem, use
+
+ %feature("self:disown") *::operator+=;
+ %feature("new") *::operator+=;
+
+ These two lines just transfer the ownership of the 'this' pointer
+ from the input to the output wrapping object.
+
+ This happens in python, but may also happen in other target
+ languages.
+ */
+ if (GetFlag(n, "feature:self:disown")) {
+ Setattr(p, "wrap:disown", "1");
+ }
+ set_nextSibling(p, parms);
+ Delete(type);
+
+ /* Generate action code for the access */
+ if (!(flags & CWRAP_EXTEND)) {
+ String *explicit_qualifier = 0;
+ String *call = 0;
+ String *cres = 0;
+ String *explicitcall_name = 0;
+ int pure_virtual = !(Cmp(Getattr(n, "storage"), "virtual")) && !(Cmp(Getattr(n, "value"), "0"));
+
+ /* Call the explicit method rather than allow for a polymorphic call */
+ if ((flags & CWRAP_DIRECTOR_TWO_CALLS) || (flags & CWRAP_DIRECTOR_ONE_CALL)) {
+ String *access = Getattr(n, "access");
+ if (access && (Cmp(access, "protected") == 0)) {
+ /* If protected access (can only be if a director method) then call the extra public accessor method (language module must provide this) */
+ String *explicit_qualifier_tmp = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
+ explicitcall_name = NewStringf("%sSwigPublic", name);
+ if (Len(directorScope) > 0)
+ explicit_qualifier = NewStringf("SwigDirector_%s_%s", directorScope, explicit_qualifier_tmp);
+ else
+ explicit_qualifier = NewStringf("SwigDirector_%s", explicit_qualifier_tmp);
+ Delete(explicit_qualifier_tmp);
+ } else {
+ explicit_qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
+ }
+ }
+
+ if (!self && SwigType_isrvalue_reference(Getattr(n, "refqualifier"))) {
+ String *memory_header = NewString("<memory>");
+ Setfile(memory_header, Getfile(n));
+ Setline(memory_header, Getline(n));
+ Swig_fragment_emit(memory_header);
+ self = NewString("std::move(*this).");
+ Delete(memory_header);
+ }
+
+ call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type);
+ cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);
+
+ if (pure_virtual && is_director && (flags & CWRAP_DIRECTOR_TWO_CALLS)) {
+ String *qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), "qname"));
+ Delete(cres);
+ cres = NewStringf("Swig::DirectorPureVirtualException::raise(\"%s::%s\");", qualifier, name);
+ Delete(qualifier);
+ }
+
+ if (flags & CWRAP_DIRECTOR_TWO_CALLS) {
+ /* Create two method calls, one to call the explicit method, the other a normal polymorphic function call */
+ String *cres_both_calls = NewStringf("");
+ String *call_extra = Swig_cmethod_call(name, p, self, 0, director_type);
+ String *cres_extra = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call_extra);
+ Printv(cres_both_calls, "if (upcall) {\n", cres, "\n", "} else {", cres_extra, "\n}", NIL);
+ Setattr(n, "wrap:action", cres_both_calls);
+ Delete(cres_extra);
+ Delete(call_extra);
+ Delete(cres_both_calls);
+ } else {
+ Setattr(n, "wrap:action", cres);
+ }
+
+ Delete(explicitcall_name);
+ Delete(call);
+ Delete(cres);
+ Delete(explicit_qualifier);
+ } else {
+ /* Methods with default arguments are wrapped with additional methods for each default argument,
+ * however, only one extra %extend method is generated. */
+
+ String *defaultargs = Getattr(n, "defaultargs");
+ String *code = Getattr(n, "code");
+ String *cname = Getattr(n, "extendsmartclassname") ? Getattr(n, "extendsmartclassname") : classname;
+ String *membername = Swig_name_member(nspace, cname, name);
+ String *mangled = Swig_name_mangle_string(membername);
+ int is_smart_pointer = flags & CWRAP_SMART_POINTER;
+
+ type = Getattr(n, "type");
+
+ /* Check if the method is overloaded. If so, and it has code attached, we append an extra suffix
+ to avoid a name-clash in the generated wrappers. This allows overloaded methods to be defined
+ in C.
+
+ But when not using the suffix used for overloaded functions, we still need to ensure that the
+ wrapper name doesn't conflict with any wrapper functions for some languages, so optionally make
+ it sufficiently unique by appending a suffix similar to the one used for overloaded functions to it.
+ */
+ if (code) {
+ if (Getattr(n, "sym:overloaded")) {
+ Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ } else if (UseWrapperSuffix) {
+ Append(mangled, "__SWIG");
+ }
+ }
+
+ /* See if there is any code that we need to emit */
+ if (!defaultargs && code && !is_smart_pointer) {
+ Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self");
+ }
+ if (is_smart_pointer) {
+ int i = 0;
+ Parm *pp = p;
+ String *func = NewStringf("%s(", mangled);
+ String *cres;
+
+ if (!Swig_storage_isstatic(n)) {
+ String *pname = Swig_cparm_name(pp, i);
+ String *ctname = SwigType_namestr(cname);
+ String *fadd = 0;
+ if (is_smart_pointer_overload) {
+ String *nclassname = SwigType_namestr(classname);
+ fadd = NewStringf("(%s const *)((%s const *)%s)->operator ->()", ctname, nclassname, pname);
+ Delete(nclassname);
+ }
+ else {
+ fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
+ }
+ Append(func, fadd);
+ Delete(ctname);
+ Delete(fadd);
+ Delete(pname);
+ pp = nextSibling(pp);
+ if (pp)
+ Append(func, ",");
+ } else {
+ pp = nextSibling(pp);
+ }
+ ++i;
+ while (pp) {
+ SwigType *pt = Getattr(pp, "type");
+ if ((SwigType_type(pt) != T_VOID)) {
+ String *pname = Swig_cparm_name(pp, i++);
+ String *rcaststr = SwigType_rcaststr(pt, pname);
+ Append(func, rcaststr);
+ Delete(rcaststr);
+ Delete(pname);
+ pp = nextSibling(pp);
+ if (pp)
+ Append(func, ",");
+ }
+ }
+ Append(func, ")");
+ cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), func);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ } else {
+ String *call = Swig_cfunction_call(mangled, p);
+ String *cres = Swig_cresult(Getattr(n, "type"), Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+
+ Delete(membername);
+ Delete(mangled);
+ }
+ Setattr(n, "parms", p);
+ Delete(p);
+ Delete(self);
+ Delete(parms);
+ Delete(directorScope);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_methodclass()
+ *
+ * This function returns the class node for a given method or class.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_methodclass(Node *n) {
+ if (Equal(nodeType(n), "class"))
+ return n;
+ return GetFlag(n, "feature:extend") ? parentNode(parentNode(n)) : parentNode(n);
+}
+
+int Swig_directorclass(Node *n) {
+ Node *classNode = Swig_methodclass(n);
+ assert(classNode != 0);
+ return (Getattr(classNode, "vtable") != 0);
+}
+
+Node *Swig_directormap(Node *module, String *type) {
+ int is_void = !Cmp(type, "void");
+ if (!is_void && module) {
+ /* ?? follow the inheritance hierarchy? */
+
+ String *base = SwigType_base(type);
+
+ Node *directormap = Getattr(module, "wrap:directormap");
+ if (directormap)
+ return Getattr(directormap, base);
+ }
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_ConstructorToFunction()
+ *
+ * This function creates a C wrapper for a C constructor function.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_ConstructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, String *none_comparison, String *director_ctor, int cplus, int flags, String *directorname) {
+ Parm *p;
+ ParmList *directorparms;
+ SwigType *type;
+ int use_director = Swig_directorclass(n);
+ ParmList *parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
+ /* Prepend the list of prefix_args (if any) */
+ Parm *prefix_args = Getattr(n, "director:prefix_args");
+ if (prefix_args != NIL) {
+ Parm *p2, *p3;
+
+ directorparms = CopyParmList(prefix_args);
+ for (p = directorparms; nextSibling(p); p = nextSibling(p));
+ for (p2 = parms; p2; p2 = nextSibling(p2)) {
+ p3 = CopyParm(p2);
+ set_nextSibling(p, p3);
+ Delete(p3);
+ p = p3;
+ }
+ } else
+ directorparms = parms;
+
+ type = NewString(classname);
+ SwigType_add_pointer(type);
+
+ if (flags & CWRAP_EXTEND) {
+ /* Constructors with default arguments are wrapped with additional constructor methods for each default argument,
+ * however, only one extra %extend method is generated. */
+ String *call;
+ String *cres;
+ String *defaultargs = Getattr(n, "defaultargs");
+ String *code = Getattr(n, "code");
+ String *membername = Swig_name_construct(nspace, classname);
+ String *mangled = Swig_name_mangle_string(membername);
+
+ /* Check if the constructor is overloaded. If so, and it has code attached, we append an extra suffix
+ to avoid a name-clash in the generated wrappers. This allows overloaded constructors to be defined
+ in C. */
+ if (Getattr(n, "sym:overloaded") && code) {
+ Append(mangled, Getattr(defaultargs ? defaultargs : n, "sym:overname"));
+ }
+
+ /* See if there is any code that we need to emit */
+ if (!defaultargs && code) {
+ Swig_add_extension_code(n, mangled, parms, type, code, cparse_cplusplus, "self");
+ }
+
+ call = Swig_cfunction_call(mangled, parms);
+ cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ Delete(membername);
+ Delete(mangled);
+ } else {
+ if (cplus) {
+ /* if a C++ director class exists, create it rather than the original class */
+ if (use_director) {
+ Node *parent = Swig_methodclass(n);
+ int abstract = Getattr(parent, "abstracts") != 0;
+ String *action = NewStringEmpty();
+ String *tmp_none_comparison = Copy(none_comparison);
+ String *director_call;
+ String *nodirector_call;
+
+ Replaceall(tmp_none_comparison, "$arg", "arg1");
+
+ director_call = Swig_cppconstructor_director_call(directorname, directorparms);
+ nodirector_call = Swig_cppconstructor_nodirector_call(classname, parms);
+
+ if (abstract) {
+ /* whether or not the abstract class has been subclassed in python,
+ * create a director instance (there's no way to create a normal
+ * instance). if any of the pure virtual methods haven't been
+ * implemented in the target language, calls to those methods will
+ * generate Swig::DirectorPureVirtualException exceptions.
+ */
+ String *cres = Swig_cresult(type, Swig_cresult_name(), director_call);
+ Append(action, cres);
+ Delete(cres);
+ } else {
+ /* (scottm): The code for creating a new director is now a string
+ template that gets passed in via the director_ctor argument.
+
+ $comparison : an 'if' comparison from none_comparison
+ $director_new: Call new for director class
+ $nondirector_new: Call new for non-director class
+ */
+ String *cres;
+ Append(action, director_ctor);
+ Replaceall(action, "$comparison", tmp_none_comparison);
+
+ cres = Swig_cresult(type, Swig_cresult_name(), director_call);
+ Replaceall(action, "$director_new", cres);
+ Delete(cres);
+
+ cres = Swig_cresult(type, Swig_cresult_name(), nodirector_call);
+ Replaceall(action, "$nondirector_new", cres);
+ Delete(cres);
+ }
+ Setattr(n, "wrap:action", action);
+ Delete(tmp_none_comparison);
+ Delete(action);
+ } else {
+ String *call = Swig_cppconstructor_call(classname, parms);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ }
+ } else {
+ String *call = Swig_cconstructor_call(classname);
+ String *cres = Swig_cresult(type, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ }
+ }
+ Setattr(n, "type", type);
+ Setattr(n, "parms", parms);
+ Delete(type);
+ if (directorparms != parms)
+ Delete(directorparms);
+ Delete(parms);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_DestructorToFunction()
+ *
+ * This function creates a C wrapper for a destructor function.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_DestructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int cplus, int flags) {
+ SwigType *type;
+ Parm *p;
+
+ type = NewString(classname);
+ SwigType_add_pointer(type);
+ p = NewParm(type, "self", n);
+ Setattr(p, "self", "1");
+ Setattr(p, "hidden", "1");
+ Setattr(p, "wrap:disown", "1");
+ Delete(type);
+ type = NewString("void");
+
+ if (flags & CWRAP_EXTEND) {
+ String *cres;
+ String *call;
+ String *membername, *mangled, *code;
+ membername = Swig_name_destroy(nspace, classname);
+ mangled = Swig_name_mangle_string(membername);
+ code = Getattr(n, "code");
+ if (code) {
+ Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, "self");
+ }
+ call = Swig_cfunction_call(mangled, p);
+ cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(membername);
+ Delete(mangled);
+ Delete(call);
+ Delete(cres);
+ } else {
+ if (cplus) {
+ String *call = Swig_cppdestructor_call(n);
+ String *cres = NewStringf("%s", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ } else {
+ String *call = Swig_cdestructor_call(n);
+ String *cres = NewStringf("%s", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+ }
+ Setattr(n, "type", type);
+ Setattr(n, "parms", p);
+ Delete(type);
+ Delete(p);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_MembersetToFunction()
+ *
+ * This function creates a C wrapper for setting a structure member.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_MembersetToFunction(Node *n, String *classname, int flags) {
+ String *name;
+ ParmList *parms;
+ Parm *p;
+ SwigType *t;
+ SwigType *ty;
+ SwigType *type;
+ SwigType *void_type = NewString("void");
+ String *self = 0;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ if (flags & CWRAP_SMART_POINTER) {
+ self = NewString("(*this)->");
+ }
+ if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
+ self = NewStringf("darg->");
+ }
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+
+ t = NewString(classname);
+ SwigType_add_pointer(t);
+ parms = NewParm(t, "self", n);
+ Setattr(parms, "self", "1");
+ Setattr(parms, "hidden","1");
+ Delete(t);
+
+ ty = Swig_wrapped_member_var_type(type, varcref);
+ p = NewParm(ty, name, n);
+ Setattr(parms, "hidden", "1");
+ set_nextSibling(parms, p);
+
+ /* If the type is a pointer or reference. We mark it with a special wrap:disown attribute */
+ if (SwigType_check_decl(type, "p.")) {
+ Setattr(p, "wrap:disown", "1");
+ }
+ Delete(p);
+
+ if (flags & CWRAP_EXTEND) {
+ String *call;
+ String *cres;
+ String *code = Getattr(n, "code");
+
+ String *sname = Swig_name_set(0, name);
+ String *membername = Swig_name_member(0, classname, sname);
+ String *mangled = Swig_name_mangle_string(membername);
+
+ if (code) {
+ /* I don't think this ever gets run - WSF */
+ Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, "self");
+ }
+ call = Swig_cfunction_call(mangled, parms);
+ cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+
+ Delete(cres);
+ Delete(call);
+ Delete(mangled);
+ Delete(membername);
+ Delete(sname);
+ } else {
+ String *call = Swig_cmemberset_call(name, type, self, varcref);
+ String *cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+ Setattr(n, "type", void_type);
+ Setattr(n, "parms", parms);
+ Delete(parms);
+ Delete(ty);
+ Delete(void_type);
+ Delete(self);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_MembergetToFunction()
+ *
+ * This function creates a C wrapper for getting a structure member.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
+ String *name;
+ ParmList *parms;
+ SwigType *t;
+ SwigType *ty;
+ SwigType *type;
+ String *self = 0;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ if (flags & CWRAP_SMART_POINTER) {
+ if (Swig_storage_isstatic(n)) {
+ Node *sn = Getattr(n, "cplus:staticbase");
+ String *base = Getattr(sn, "name");
+ self = NewStringf("%s::", base);
+ } else if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
+ String *nclassname = SwigType_namestr(classname);
+ self = NewStringf("(*(%s const *)this)->", nclassname);
+ Delete(nclassname);
+ } else {
+ self = NewString("(*this)->");
+ }
+ }
+ if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
+ self = NewStringf("darg->");
+ }
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+
+ t = NewString(classname);
+ SwigType_add_pointer(t);
+ parms = NewParm(t, "self", n);
+ Setattr(parms, "self", "1");
+ Setattr(parms, "hidden","1");
+ Delete(t);
+
+ ty = Swig_wrapped_member_var_type(type, varcref);
+ if (flags & CWRAP_EXTEND) {
+ String *call;
+ String *cres;
+ String *code = Getattr(n, "code");
+
+ String *gname = Swig_name_get(0, name);
+ String *membername = Swig_name_member(0, classname, gname);
+ String *mangled = Swig_name_mangle_string(membername);
+
+ if (code) {
+ /* I don't think this ever gets run - WSF */
+ Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus, "self");
+ }
+ call = Swig_cfunction_call(mangled, parms);
+ cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+
+ Delete(cres);
+ Delete(call);
+ Delete(mangled);
+ Delete(membername);
+ Delete(gname);
+ } else {
+ String *call = Swig_cmemberget_call(name, type, self, varcref);
+ String *cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(call);
+ Delete(cres);
+ }
+ Setattr(n, "type", ty);
+ Setattr(n, "parms", parms);
+ Delete(parms);
+ Delete(ty);
+
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_VarsetToFunction()
+ *
+ * This function creates a C wrapper for setting a global variable or static member
+ * variable.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_VarsetToFunction(Node *n, int flags) {
+ String *name, *nname;
+ ParmList *parms;
+ SwigType *type, *ty;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+ nname = SwigType_namestr(name);
+ ty = Swig_wrapped_var_type(type, varcref);
+ parms = NewParm(ty, name, n);
+
+ if (flags & CWRAP_EXTEND) {
+ String *sname = Swig_name_set(0, name);
+ String *mangled = Swig_name_mangle_string(sname);
+ String *call = Swig_cfunction_call(mangled, parms);
+ String *cres = NewStringf("%s;", call);
+ Setattr(n, "wrap:action", cres);
+ Delete(cres);
+ Delete(call);
+ Delete(mangled);
+ Delete(sname);
+ } else {
+ if (!Strstr(type, "enum $unnamed")) {
+ String *pname = Swig_cparm_name(0, 0);
+ String *dref = Swig_wrapped_var_deref(type, pname, varcref);
+ String *call = NewStringf("%s = %s;", nname, dref);
+ Setattr(n, "wrap:action", call);
+ Delete(call);
+ Delete(dref);
+ Delete(pname);
+ } else {
+ String *pname = Swig_cparm_name(0, 0);
+ String *call = NewStringf("if (sizeof(int) == sizeof(%s)) *(int*)(void*)&(%s) = %s;", nname, nname, pname);
+ Setattr(n, "wrap:action", call);
+ Delete(pname);
+ Delete(call);
+ }
+ }
+ Setattr(n, "type", "void");
+ Setattr(n, "parms", parms);
+ Delete(parms);
+ Delete(ty);
+ Delete(nname);
+ return SWIG_OK;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_VargetToFunction()
+ *
+ * This function creates a C wrapper for getting a global variable or static member
+ * variable.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_VargetToFunction(Node *n, int flags) {
+ String *cres, *call;
+ String *name;
+ SwigType *type;
+ SwigType *ty = 0;
+
+ int varcref = flags & CWRAP_NATURAL_VAR;
+
+ name = Getattr(n, "name");
+ type = Getattr(n, "type");
+ ty = Swig_wrapped_var_type(type, varcref);
+
+ if (flags & CWRAP_EXTEND) {
+ String *sname = Swig_name_get(0, name);
+ String *mangled = Swig_name_mangle_string(sname);
+ call = Swig_cfunction_call(mangled, 0);
+ cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(mangled);
+ Delete(sname);
+ } else {
+ String *nname = 0;
+ if (Equal(nodeType(n), "constant")) {
+ nname = NewStringf("(%s)", Getattr(n, "value"));
+ } else {
+ nname = SwigType_namestr(name);
+ }
+ call = Swig_wrapped_var_assign(type, nname, varcref);
+ cres = Swig_cresult(ty, Swig_cresult_name(), call);
+ Setattr(n, "wrap:action", cres);
+ Delete(nname);
+ }
+
+ Setattr(n, "type", ty);
+ Delattr(n, "parms");
+ Delete(cres);
+ Delete(call);
+ Delete(ty);
+ return SWIG_OK;
+}
diff --git a/contrib/tools/swig/Source/Swig/deprecate.c b/contrib/tools/swig/Source/Swig/deprecate.c
new file mode 100644
index 00000000000..5783455e599
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/deprecate.c
@@ -0,0 +1,107 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * deprecate.c
+ *
+ * The functions in this file are SWIG core functions that are deprecated
+ * or which do not fit in nicely with everything else. Generally this means
+ * that the function and/or API needs to be changed in some future release.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+/* ---------------------------------------------------------------------
+ * ParmList_is_compactdefargs()
+ *
+ * Returns 1 if the parameter list passed in is marked for compact argument
+ * handling (by the "compactdefargs" attribute). Otherwise returns 0.
+ * ---------------------------------------------------------------------- */
+
+/* Discussion:
+
+ "compactdefargs" is a property set by the Parser to indicate special
+ handling of default arguments. This property seems to be something that
+ is associated with functions and methods rather than low-level ParmList
+ objects. Therefore, I don't like the fact that this special purpose
+ feature is bolted onto the side of ParmList objects.
+
+ Proposed solution:
+
+ 1. "compactdefargs" should be a feature set on function/method nodes
+ instead of ParmList objects. For example, if you have a function,
+ you would check the function node to see if the parameters are
+ to be handled in this way.
+
+
+ Difficulties:
+
+ 1. This is used by functions in cwrap.c and emit.cxx, none of which
+ are passed information about the function/method node. We might
+ have to change the API of those functions to make this work correctly.
+ For example:
+
+ int emit_num_required(ParmList *parms)
+
+ might become
+
+ int emit_num_required(ParmList *parms, int compactargs)
+
+*/
+
+int ParmList_is_compactdefargs(ParmList *p) {
+ int compactdefargs = 0;
+
+ if (p) {
+ compactdefargs = Getattr(p, "compactdefargs") ? 1 : 0;
+
+ /* The "compactdefargs" attribute should only be set on the first parameter in the list.
+ * However, sometimes an extra parameter is inserted at the beginning of the parameter list,
+ * so we check the 2nd parameter too. */
+ if (!compactdefargs) {
+ Parm *nextparm = nextSibling(p);
+ compactdefargs = (nextparm && Getattr(nextparm, "compactdefargs")) ? 1 : 0;
+ }
+ }
+
+ return compactdefargs;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_errorstr()
+ *
+ * Generate a prototype string suitable for use in error/warning messages.
+ * Similar to ParmList_protostr() but is also aware of hidden parameters.
+ * ---------------------------------------------------------------------- */
+
+/* Discussion. This function is used to generate error messages, but take
+ into account that there might be a hidden parameter. Although this involves
+ parameter lists, it really isn't a core feature of swigparm.h or parms.c.
+ This is because the "hidden" attribute of parameters is added elsewhere (cwrap.c).
+
+ For now, this function is placed here because it doesn't really seem to fit in
+ with the parms.c interface.
+
+*/
+
+String *ParmList_errorstr(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ if (Getattr(p,"hidden")) {
+ p = nextSibling(p);
+ } else {
+ String *pstr = SwigType_str(Getattr(p, "type"), 0);
+ Append(out, pstr);
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ }
+ return out;
+}
diff --git a/contrib/tools/swig/Source/Swig/error.c b/contrib/tools/swig/Source/Swig/error.c
new file mode 100644
index 00000000000..c85f16df29d
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/error.c
@@ -0,0 +1,350 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * error.c
+ *
+ * Error handling functions. These are used to issue warnings and
+ * error messages.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <stdarg.h>
+#include <ctype.h>
+
+/* -----------------------------------------------------------------------------
+ * Commentary on the warning filter.
+ *
+ * The warning filter is a string of numbers prefaced by (-) or (+) to
+ * indicate whether or not a warning message is displayed. For example:
+ *
+ * "-304-201-140+210+201"
+ *
+ * The filter string is scanned left to right and the first occurrence
+ * of a warning number is used to determine printing behavior.
+ *
+ * The same number may appear more than once in the string. For example, in the
+ * above string, "201" appears twice. This simply means that warning 201
+ * was disabled after it was previously enabled. This may only be temporary
+ * setting--the first number may be removed later in which case the warning
+ * is reenabled.
+ * ----------------------------------------------------------------------------- */
+
+#if defined(_WIN32)
+# define DEFAULT_ERROR_MSG_FORMAT EMF_MICROSOFT
+#else
+# define DEFAULT_ERROR_MSG_FORMAT EMF_STANDARD
+#endif
+static ErrorMessageFormat msg_format = DEFAULT_ERROR_MSG_FORMAT;
+static int silence = 0; /* Silent operation */
+static String *filter = 0; /* Warning filter */
+static int warnall = 0;
+static int nwarning = 0;
+static int nerrors = 0;
+
+static int init_fmt = 0;
+static char wrn_wnum_fmt[64];
+static char wrn_nnum_fmt[64];
+static char err_line_fmt[64];
+static char err_eof_fmt[64];
+static char diag_line_fmt[64];
+static char diag_eof_fmt[64];
+
+static String *format_filename(const_String_or_char_ptr filename);
+
+/* -----------------------------------------------------------------------------
+ * Swig_warning()
+ *
+ * Issue a warning message on stderr.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const char *fmt, ...) {
+ String *out;
+ char *msg;
+ int wrn = 1;
+ va_list ap;
+ if (silence)
+ return;
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ va_start(ap, fmt);
+
+ out = NewStringEmpty();
+ vPrintf(out, fmt, ap);
+
+ msg = Char(out);
+ if (isdigit((unsigned char) *msg)) {
+ unsigned long result = strtoul(msg, &msg, 10);
+ if (msg != Char(out)) {
+ msg++;
+ wnum = result;
+ }
+ }
+
+ /* Check in the warning filter */
+ if (filter) {
+ char temp[32];
+ char *c;
+ char *f = Char(filter);
+ sprintf(temp, "%d", wnum);
+ while (*f != '\0' && (c = strstr(f, temp))) {
+ if (*(c - 1) == '-') {
+ wrn = 0; /* Warning disabled */
+ break;
+ }
+ if (*(c - 1) == '+') {
+ wrn = 1; /* Warning enabled */
+ break;
+ }
+ f += strlen(temp);
+ }
+ }
+ if (warnall || wrn) {
+ String *formatted_filename = format_filename(filename);
+ String *full_message = NewString("");
+ if (wnum) {
+ Printf(full_message, wrn_wnum_fmt, formatted_filename, line, wnum);
+ } else {
+ Printf(full_message, wrn_nnum_fmt, formatted_filename, line);
+ }
+ Printf(full_message, "%s", msg);
+ Printv(stderr, full_message, NIL);
+ nwarning++;
+ Delete(full_message);
+ Delete(formatted_filename);
+ }
+ Delete(out);
+ va_end(ap);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error()
+ *
+ * Issue an error message on stderr.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
+ va_list ap;
+ String *formatted_filename = NULL;
+ String *full_message = NULL;
+
+ if (silence)
+ return;
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ va_start(ap, fmt);
+ formatted_filename = format_filename(filename);
+ full_message = NewString("");
+ if (line > 0) {
+ Printf(full_message, err_line_fmt, formatted_filename, line);
+ } else {
+ Printf(full_message, err_eof_fmt, formatted_filename);
+ }
+ vPrintf(full_message, fmt, ap);
+ Printv(stderr, full_message, NIL);
+ va_end(ap);
+ nerrors++;
+ Delete(full_message);
+ Delete(formatted_filename);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error_count()
+ *
+ * Returns number of errors received.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_error_count(void) {
+ return nerrors;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error_silent()
+ *
+ * Set silent flag
+ * ----------------------------------------------------------------------------- */
+
+void Swig_error_silent(int s) {
+ silence = s;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_warnfilter()
+ *
+ * Takes a comma separate list of warning numbers and puts in the filter.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_warnfilter(const_String_or_char_ptr wlist, int add) {
+ char *c;
+ char *cw;
+ String *s;
+ if (!filter)
+ filter = NewStringEmpty();
+
+ s = NewString("");
+ cw = Char(wlist);
+ while (*cw != '\0') {
+ if (*cw != ' ') {
+ Putc(*cw, s);
+ }
+ ++cw;
+ }
+ c = Char(s);
+ c = strtok(c, ", ");
+ while (c) {
+ if (isdigit((int) *c) || (*c == '+') || (*c == '-')) {
+ /* Even if c is a digit, the rest of the string might not be, eg in the case of typemap
+ * warnings (a bit odd really), eg: %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG) */
+ if (add) {
+ Insert(filter, 0, c);
+ if (isdigit((int) *c)) {
+ Insert(filter, 0, "-");
+ }
+ } else {
+ char *temp = (char *)Malloc(sizeof(char)*strlen(c) + 2);
+ if (isdigit((int) *c)) {
+ sprintf(temp, "-%s", c);
+ } else {
+ strcpy(temp, c);
+ }
+ Replace(filter, temp, "", DOH_REPLACE_FIRST);
+ Free(temp);
+ }
+ }
+ c = strtok(NULL, ", ");
+ }
+ Delete(s);
+}
+
+void Swig_warnall(void) {
+ warnall = 1;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_warn_count()
+ *
+ * Return the number of warnings
+ * ----------------------------------------------------------------------------- */
+
+int Swig_warn_count(void) {
+ return nwarning;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_error_msg_format()
+ *
+ * Set the type of error/warning message display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_error_msg_format(ErrorMessageFormat format) {
+ const char *error = "Error";
+ const char *warning = "Warning";
+
+ const char *fmt_eof = 0;
+ const char *fmt_line = 0;
+
+ /* here 'format' could be directly a string instead of an enum, but
+ by now a switch is used to translated into one. */
+ switch (format) {
+ case EMF_MICROSOFT:
+ fmt_line = "%s(%d) ";
+ fmt_eof = "%s(999999) "; /* Is there a special character for EOF? Just use a large number. */
+ break;
+ case EMF_STANDARD:
+ default:
+ fmt_line = "%s:%d";
+ fmt_eof = "%s:EOF";
+ }
+
+ sprintf(wrn_wnum_fmt, "%s: %s %%d: ", fmt_line, warning);
+ sprintf(wrn_nnum_fmt, "%s: %s: ", fmt_line, warning);
+ sprintf(err_line_fmt, "%s: %s: ", fmt_line, error);
+ sprintf(err_eof_fmt, "%s: %s: ", fmt_eof, error);
+ sprintf(diag_line_fmt, "%s: ", fmt_line);
+ sprintf(diag_eof_fmt, "%s: ", fmt_eof);
+
+ msg_format = format;
+ init_fmt = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * format_filename()
+ *
+ * Remove double backslashes in Windows filename paths for display
+ * ----------------------------------------------------------------------------- */
+static String *format_filename(const_String_or_char_ptr filename) {
+ String *formatted_filename = NewString(filename);
+#if defined(_WIN32)
+ Replaceall(formatted_filename, "\\\\", "\\");
+#endif
+ return formatted_filename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_stringify_with_location()
+ *
+ * Return a string representation of any DOH object with line and file location
+ * information in the appropriate error message format. The string representation
+ * is enclosed within [] brackets after the line and file information.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_stringify_with_location(DOH *object) {
+ String *str = NewStringEmpty();
+
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ if (object) {
+ int line = Getline(object);
+ String *formatted_filename = format_filename(Getfile(object));
+ if (line > 0) {
+ Printf(str, diag_line_fmt, formatted_filename, line);
+ } else {
+ Printf(str, diag_eof_fmt, formatted_filename);
+ }
+ if (Len(object) == 0) {
+ Printf(str, "[EMPTY]");
+ } else {
+ Printf(str, "[%s]", object);
+ }
+ Delete(formatted_filename);
+ } else {
+ Printf(str, "[NULL]");
+ }
+
+ return str;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_diagnostic()
+ *
+ * Issue a diagnostic message on stdout.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
+ va_list ap;
+ String *formatted_filename = NULL;
+
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ va_start(ap, fmt);
+ formatted_filename = format_filename(filename);
+ if (line > 0) {
+ Printf(stdout, diag_line_fmt, formatted_filename, line);
+ } else {
+ Printf(stdout, diag_eof_fmt, formatted_filename);
+ }
+ vPrintf(stdout, fmt, ap);
+ va_end(ap);
+ Delete(formatted_filename);
+}
+
diff --git a/contrib/tools/swig/Source/Swig/extend.c b/contrib/tools/swig/Source/Swig/extend.c
new file mode 100644
index 00000000000..4e430ed5dee
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/extend.c
@@ -0,0 +1,140 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * extend.c
+ *
+ * Extensions support (%extend)
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+static Hash *extendhash = 0; /* Hash table of added methods */
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_hash()
+ *
+ * Access the extend hash
+ * ----------------------------------------------------------------------------- */
+Hash *Swig_extend_hash(void) {
+ if (!extendhash)
+ extendhash = NewHash();
+ return extendhash;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_merge()
+ *
+ * Extension merge. This function is used to handle the %extend directive
+ * when it appears before a class definition. To handle this, the %extend
+ * actually needs to take precedence. Therefore, we will selectively nuke symbols
+ * from the current symbol table, replacing them with the added methods.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_extend_merge(Node *cls, Node *am) {
+ Node *n;
+
+ n = firstChild(am);
+ while (n) {
+ String *symname;
+ if (Strcmp(nodeType(n),"constructor") == 0) {
+ symname = Getattr(n,"sym:name");
+ if (symname) {
+ if (Strcmp(symname,Getattr(n,"name")) == 0) {
+ /* If the name and the sym:name of a constructor are the same,
+ then it hasn't been renamed. However---the name of the class
+ itself might have been renamed so we need to do a consistency
+ check here */
+ if (Getattr(cls,"sym:name")) {
+ Setattr(n,"sym:name", Getattr(cls,"sym:name"));
+ }
+ }
+ }
+ }
+
+ symname = Getattr(n,"sym:name");
+ DohIncref(symname);
+ if ((symname) && (!Getattr(n,"error"))) {
+ Node *c;
+ /* Remove node from its symbol table */
+ Swig_symbol_remove(n);
+ c = Swig_symbol_add(symname,n);
+ if (c != n) {
+ /* Conflict with previous definition. Nuke previous definition */
+ String *e = NewStringEmpty();
+ String *en = NewStringEmpty();
+ String *ec = NewStringEmpty();
+ Printf(ec, "Redefinition of identifier '%s' by %%extend ignored,", symname);
+ Printf(en, "%%extend definition of '%s'.", symname);
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(WARN_PARSE_REDEFINED, Getfile(c), Getline(c), "%s\n", ec);
+ Swig_warning(WARN_PARSE_REDEFINED, Getfile(n), Getline(n), "%s\n", en);
+ SWIG_WARN_NODE_END(n);
+ Printf(e, "%s:%d:%s\n%s:%d:%s\n", Getfile(c), Getline(c), ec, Getfile(n),Getline(n),en);
+ Setattr(c, "error", e);
+ Delete(e);
+ Delete(en);
+ Delete(ec);
+ Swig_symbol_remove(c); /* Remove class definition */
+ Swig_symbol_add(symname, n); /* Insert extend definition */
+ }
+ }
+ n = nextSibling(n);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_append_previous()
+ * ----------------------------------------------------------------------------- */
+
+void Swig_extend_append_previous(Node *cls, Node *am) {
+ Node *n, *ne;
+ Node *pe = 0;
+ Node *ae = 0;
+
+ if (!am) return;
+
+ n = firstChild(am);
+ while (n) {
+ ne = nextSibling(n);
+ set_nextSibling(n,0);
+ /* typemaps and fragments need to be prepended */
+ if (((Cmp(nodeType(n),"typemap") == 0) || (Cmp(nodeType(n),"fragment") == 0))) {
+ if (!pe) pe = Swig_cparse_new_node("extend");
+ appendChild(pe, n);
+ } else {
+ if (!ae) ae = Swig_cparse_new_node("extend");
+ appendChild(ae, n);
+ }
+ n = ne;
+ }
+ if (pe) prependChild(cls,pe);
+ if (ae) appendChild(cls,ae);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_extend_unused_check()
+ *
+ * Check for unused %extend. Special case, don't report unused
+ * extensions for templates
+ * ----------------------------------------------------------------------------- */
+
+void Swig_extend_unused_check(void) {
+ Iterator ki;
+
+ if (!extendhash) return;
+ for (ki = First(extendhash); ki.key; ki = Next(ki)) {
+ if (!Strchr(ki.key,'<')) {
+ SWIG_WARN_NODE_BEGIN(ki.item);
+ Swig_warning(WARN_PARSE_EXTEND_UNDEF,Getfile(ki.item), Getline(ki.item), "%%extend defined for an undeclared class %s.\n", SwigType_namestr(ki.key));
+ SWIG_WARN_NODE_END(ki.item);
+ }
+ }
+}
+
diff --git a/contrib/tools/swig/Source/Swig/fragment.c b/contrib/tools/swig/Source/Swig/fragment.c
new file mode 100644
index 00000000000..84731f52ffa
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/fragment.c
@@ -0,0 +1,188 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * fragment.c
+ *
+ * This file manages named code fragments. Code fragments are typically
+ * used to hold helper-code that may or may not be included in the wrapper
+ * file (depending on what features are actually used in the interface).
+ *
+ * By using fragments, it's possible to greatly reduce the amount of
+ * wrapper code and to generate cleaner wrapper files.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "swigwarn.h"
+#include "cparse.h"
+
+static Hash *fragments = 0;
+static Hash *looking_fragments = 0;
+static int debug = 0;
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_fragment_register()
+ *
+ * Add a fragment. Use the original Node*, so, if something needs to be
+ * changed, lang.cxx doesn't need to be touched again.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_fragment_register(Node *fragment) {
+ if (Getattr(fragment, "emitonly")) {
+ Swig_fragment_emit(fragment);
+ return;
+ } else {
+ String *name = Copy(Getattr(fragment, "value"));
+ String *type = Getattr(fragment, "type");
+ if (type) {
+ SwigType *rtype = SwigType_typedef_resolve_all(type);
+ String *mangle = Swig_name_mangle_type(type);
+ Append(name, mangle);
+ Delete(mangle);
+ Delete(rtype);
+ if (debug)
+ Printf(stdout, "register fragment %s %s\n", name, type);
+ }
+ if (!fragments) {
+ fragments = NewHash();
+ }
+ if (!Getattr(fragments, name)) {
+ String *section = Copy(Getattr(fragment, "section"));
+ String *ccode = Copy(Getattr(fragment, "code"));
+ Hash *kwargs = Getattr(fragment, "kwargs");
+ Setmeta(ccode, "section", section);
+ if (kwargs) {
+ Setmeta(ccode, "kwargs", kwargs);
+ }
+ Setfile(ccode, Getfile(fragment));
+ Setline(ccode, Getline(fragment));
+ /* Replace $descriptor() macros */
+ Swig_cparse_replace_descriptor(ccode);
+ Setattr(fragments, name, ccode);
+ if (debug)
+ Printf(stdout, "registering fragment %s %s\n", name, section);
+ Delete(section);
+ Delete(ccode);
+ }
+ Delete(name);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_fragment_emit()
+ *
+ * Emit a fragment
+ * ----------------------------------------------------------------------------- */
+
+static
+char *char_index(char *str, char c) {
+ while (*str && (c != *str))
+ ++str;
+ return (c == *str) ? str : 0;
+}
+
+void Swig_fragment_emit(Node *n) {
+ String *code;
+ char *pc, *tok;
+ String *t;
+ String *mangle = 0;
+ String *name = 0;
+ String *type = 0;
+
+ name = Getattr(n, "value");
+ if (!name) {
+ name = n;
+ }
+
+ if (!fragments) {
+ Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name);
+ return;
+ }
+
+ type = Getattr(n, "type");
+ if (type) {
+ mangle = Swig_name_mangle_type(type);
+ }
+
+ if (debug)
+ Printf(stdout, "looking fragment %s %s\n", name, type);
+ t = Copy(name);
+ tok = Char(t);
+ pc = char_index(tok, ',');
+ if (pc)
+ *pc = 0;
+ while (tok) {
+ String *name = NewString(tok);
+ if (mangle)
+ Append(name, mangle);
+ if (looking_fragments && Getattr(looking_fragments, name)) {
+ return;
+ }
+ code = Getattr(fragments, name);
+ if (debug)
+ Printf(stdout, "looking subfragment %s\n", name);
+ if (code && (Strcmp(code, "ignore") != 0)) {
+ String *section = Getmeta(code, "section");
+ Hash *nn = Getmeta(code, "kwargs");
+ if (!looking_fragments)
+ looking_fragments = NewHash();
+ Setattr(looking_fragments, name, "1");
+ while (nn) {
+ if (Equal(Getattr(nn, "name"), "fragment")) {
+ if (debug)
+ Printf(stdout, "emitting fragment %s %s\n", nn, type);
+ Setfile(nn, Getfile(n));
+ Setline(nn, Getline(n));
+ Swig_fragment_emit(nn);
+ }
+ nn = nextSibling(nn);
+ }
+ if (section) {
+ File *f = Swig_filebyname(section);
+ if (!f) {
+ Swig_error(Getfile(code), Getline(code), "Bad section '%s' in %%fragment declaration for code fragment '%s'\n", section, name);
+ } else {
+ if (debug)
+ Printf(stdout, "emitting subfragment %s %s\n", name, section);
+ if (debug)
+ Printf(f, "/* begin fragment %s */\n", name);
+ Printf(f, "%s\n", code);
+ if (debug)
+ Printf(f, "/* end fragment %s */\n\n", name);
+ Setattr(fragments, name, "ignore");
+ Delattr(looking_fragments, name);
+ }
+ }
+ } else if (!code && type) {
+ SwigType *rtype = SwigType_typedef_resolve_all(type);
+ if (!Equal(type, rtype)) {
+ String *name = Copy(Getattr(n, "value"));
+ String *mangle = Swig_name_mangle_type(type);
+ Append(name, mangle);
+ Setfile(name, Getfile(n));
+ Setline(name, Getline(n));
+ Swig_fragment_emit(name);
+ Delete(mangle);
+ Delete(name);
+ }
+ Delete(rtype);
+ }
+
+ if (!code) {
+ Swig_warning(WARN_FRAGMENT_NOT_FOUND, Getfile(n), Getline(n), "Fragment '%s' not found.\n", name);
+ }
+ tok = pc ? pc + 1 : 0;
+ if (tok) {
+ pc = char_index(tok, ',');
+ if (pc)
+ *pc = 0;
+ }
+ Delete(name);
+ }
+ Delete(t);
+}
diff --git a/contrib/tools/swig/Source/Swig/getopt.c b/contrib/tools/swig/Source/Swig/getopt.c
new file mode 100644
index 00000000000..7791d13f72d
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/getopt.c
@@ -0,0 +1,104 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * getopt.c
+ *
+ * Handles the parsing of command line options. This is particularly nasty
+ * compared to other utilities given that command line options can potentially
+ * be read by many different modules within SWIG. Thus, in order to make sure
+ * there are no unrecognized options, each module is required to "mark"
+ * the options that it uses. Afterwards, we can make a quick scan to make
+ * sure there are no unmarked options.
+ *
+ * TODO:
+ * Should have cleaner error handling in general.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+static char **args;
+static int numargs;
+static int *marked;
+
+/* -----------------------------------------------------------------------------
+ * Swig_init_args()
+ *
+ * Initialize the argument list handler.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_init_args(int argc, char **argv) {
+ assert(argc > 0);
+ assert(argv);
+
+ numargs = argc;
+ args = argv;
+ marked = (int *) Calloc(numargs, sizeof(int));
+ marked[0] = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_mark_arg()
+ *
+ * Marks an argument as being parsed.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_mark_arg(int n) {
+ assert(marked);
+ assert((n >= 0) && (n < numargs));
+ marked[n] = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_check_marked()
+ *
+ * Checks to see if argument has been picked up.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_check_marked(int n) {
+ assert((n >= 0) && (n < numargs));
+ return marked[n];
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_check_options()
+ *
+ * Checkers for unprocessed command line options and errors.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_check_options(int check_input) {
+ int error = 0;
+ int i;
+ int max = check_input ? numargs - 1 : numargs;
+ assert(marked);
+ for (i = 1; i < max; i++) {
+ if (!marked[i]) {
+ Printf(stderr, "swig error : Unrecognized option %s\n", args[i]);
+ error = 1;
+ }
+ }
+ if (error) {
+ Printf(stderr, "Use 'swig -help' for available options.\n");
+ Exit(EXIT_FAILURE);
+ }
+ if (check_input && marked[numargs - 1]) {
+ Printf(stderr, "Must specify an input file. Use -help for available options.\n");
+ Exit(EXIT_FAILURE);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_arg_error()
+ *
+ * Generates a generic error message and exits.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_arg_error(void) {
+ Printf(stderr, "SWIG : Unable to parse command line options.\n");
+ Printf(stderr, "Use 'swig -help' for available options.\n");
+ Exit(EXIT_FAILURE);
+}
diff --git a/contrib/tools/swig/Source/Swig/include.c b/contrib/tools/swig/Source/Swig/include.c
new file mode 100644
index 00000000000..5bd65b6d439
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/include.c
@@ -0,0 +1,379 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * include.c
+ *
+ * The functions in this file are used to manage files in the SWIG library.
+ * General purpose functions for opening, including, and retrieving pathnames
+ * are provided.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+static List *directories = 0; /* List of include directories */
+static String *lastpath = 0; /* Last file that was included */
+static List *pdirectories = 0; /* List of pushed directories */
+static int dopush = 1; /* Whether to push directories */
+static int file_debug = 0;
+
+/* This functions determine whether to push/pop dirs in the preprocessor */
+void Swig_set_push_dir(int push) {
+ dopush = push;
+}
+
+int Swig_get_push_dir(void) {
+ return dopush;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_add_directory()
+ *
+ * Adds a directory to the SWIG search path.
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_add_directory(const_String_or_char_ptr dirname) {
+ String *adirname;
+ if (!directories)
+ directories = NewList();
+ assert(directories);
+ if (dirname) {
+ adirname = NewString(dirname);
+ Append(directories,adirname);
+ Delete(adirname);
+ }
+ return directories;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_push_directory()
+ *
+ * Inserts a directory at the front of the SWIG search path. This is used by
+ * the preprocessor to grab files in the same directory as other included files.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_push_directory(const_String_or_char_ptr dirname) {
+ String *pdirname;
+ if (!Swig_get_push_dir())
+ return;
+ if (!pdirectories)
+ pdirectories = NewList();
+ assert(pdirectories);
+ pdirname = NewString(dirname);
+ assert(pdirname);
+ Insert(pdirectories,0,pdirname);
+ Delete(pdirname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_pop_directory()
+ *
+ * Pops a directory off the front of the SWIG search path. This is used by
+ * the preprocessor.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_pop_directory(void) {
+ if (!Swig_get_push_dir())
+ return;
+ if (!pdirectories)
+ return;
+ Delitem(pdirectories, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_last_file()
+ *
+ * Returns the full pathname of the last file opened.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_last_file(void) {
+ assert(lastpath);
+ return lastpath;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_search_path_any()
+ *
+ * Returns a list of the current search paths.
+ * ----------------------------------------------------------------------------- */
+
+static List *Swig_search_path_any(int syspath) {
+ String *filename;
+ List *slist;
+ int i, ilen;
+
+ slist = NewList();
+ assert(slist);
+ filename = NewStringEmpty();
+ assert(filename);
+ Printf(filename, ".%s", SWIG_FILE_DELIMITER);
+ Append(slist, filename);
+ Delete(filename);
+
+ /* If there are any pushed directories. Add them first */
+ if (pdirectories) {
+ ilen = Len(pdirectories);
+ for (i = 0; i < ilen; i++) {
+ filename = NewString(Getitem(pdirectories,i));
+ Append(filename,SWIG_FILE_DELIMITER);
+ Append(slist,filename);
+ Delete(filename);
+ }
+ }
+ /* Add system directories next */
+ ilen = Len(directories);
+ for (i = 0; i < ilen; i++) {
+ filename = NewString(Getitem(directories,i));
+ Append(filename,SWIG_FILE_DELIMITER);
+ if (syspath) {
+ /* If doing a system include, put the system directories first */
+ Insert(slist,i,filename);
+ } else {
+ /* Otherwise, just put the system directories after the pushed directories (if any) */
+ Append(slist,filename);
+ }
+ Delete(filename);
+ }
+ return slist;
+}
+
+List *Swig_search_path(void) {
+ return Swig_search_path_any(0);
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_open()
+ *
+ * open a file, optionally looking for it in the include path. Returns an open
+ * FILE * on success.
+ * ----------------------------------------------------------------------------- */
+
+static FILE *Swig_open_file(const_String_or_char_ptr name, int sysfile, int use_include_path) {
+ FILE *f;
+ String *filename;
+ List *spath = 0;
+ char *cname;
+ int i, ilen, nbytes;
+ char bom[3];
+
+ if (!directories)
+ directories = NewList();
+ assert(directories);
+
+ cname = Char(name);
+ filename = NewString(cname);
+ assert(filename);
+ if (file_debug) {
+ Printf(stdout, " Open: %s\n", filename);
+ }
+ f = fopen(Char(filename), "r");
+ if (!f && use_include_path) {
+ spath = Swig_search_path_any(sysfile);
+ ilen = Len(spath);
+ for (i = 0; i < ilen; i++) {
+ Clear(filename);
+ Printf(filename, "%s%s", Getitem(spath, i), cname);
+ f = fopen(Char(filename), "r");
+ if (f)
+ break;
+ }
+ Delete(spath);
+ }
+ if (f) {
+ Delete(lastpath);
+ lastpath = filename;
+
+ /* Skip the UTF-8 BOM if it's present */
+ nbytes = (int)fread(bom, 1, 3, f);
+ if (nbytes == 3 && bom[0] == (char)0xEF && bom[1] == (char)0xBB && bom[2] == (char)0xBF) {
+ /* skip */
+ } else {
+ fseek(f, 0, SEEK_SET);
+ }
+ }
+ return f;
+}
+
+/* Open a file - searching the include paths to find it */
+FILE *Swig_include_open(const_String_or_char_ptr name) {
+ return Swig_open_file(name, 0, 1);
+}
+
+/* Open a file - does not use include paths to find it */
+FILE *Swig_open(const_String_or_char_ptr name) {
+ return Swig_open_file(name, 0, 0);
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_read_file()
+ *
+ * Reads data from an open FILE * and returns it as a string.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_read_file(FILE *f) {
+ int len;
+ char buffer[4096];
+ String *str = NewStringEmpty();
+
+ assert(str);
+ while (1) {
+ size_t c = fread(buffer, 1, sizeof(buffer), f);
+ if (c > 0) Write(str, buffer, (int)c);
+ if (c < sizeof(buffer)) break;
+ }
+ len = Len(str);
+ /* Add a newline if not present on last line -- the preprocessor seems to
+ * rely on \n and not EOF terminating lines */
+ if (len) {
+ char *cstr = Char(str);
+ if (cstr[len - 1] != '\n') {
+ Append(str, "\n");
+ }
+ }
+ return str;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_include()
+ *
+ * Opens a file and returns it as a string.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_include_any(const_String_or_char_ptr name, int sysfile) {
+ FILE *f;
+ String *str;
+ String *file;
+
+ f = Swig_open_file(name, sysfile, 1);
+ if (!f)
+ return 0;
+ str = Swig_read_file(f);
+ fclose(f);
+ Seek(str, 0, SEEK_SET);
+ file = Copy(Swig_last_file());
+ Setfile(str, file);
+ Delete(file);
+ Setline(str, 1);
+ return str;
+}
+
+String *Swig_include(const_String_or_char_ptr name) {
+ return Swig_include_any(name, 0);
+}
+
+String *Swig_include_sys(const_String_or_char_ptr name) {
+ return Swig_include_any(name, 1);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_insert_file()
+ *
+ * Copies the contents of a file into another file
+ * ----------------------------------------------------------------------------- */
+
+int Swig_insert_file(const_String_or_char_ptr filename, File *outfile) {
+ char buffer[4096];
+ int nbytes;
+ FILE *f = Swig_include_open(filename);
+
+ if (!f)
+ return -1;
+ while ((nbytes = Read(f, buffer, 4096)) > 0) {
+ Write(outfile, buffer, nbytes);
+ }
+ fclose(f);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_register_filebyname()
+ *
+ * Register a "named" file with the core. Named files can become targets
+ * for %insert directives and other SWIG operations. This function takes
+ * the place of the f_header, f_wrapper, f_init, and other global variables
+ * in SWIG1.1
+ * ----------------------------------------------------------------------------- */
+
+static Hash *named_files = 0;
+
+void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile) {
+ if (!named_files)
+ named_files = NewHash();
+ Setattr(named_files, filename, outfile);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filebyname()
+ *
+ * Get a named file
+ * ----------------------------------------------------------------------------- */
+
+File *Swig_filebyname(const_String_or_char_ptr filename) {
+ if (!named_files)
+ return 0;
+ return Getattr(named_files, filename);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_extension()
+ *
+ * Returns the extension of a file
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_file_extension(const_String_or_char_ptr filename) {
+ String *name = Swig_file_filename(filename);
+ const char *c = strrchr(Char(name), '.');
+ String *extension = c ? NewString(c) : NewString("");
+ Delete(name);
+ return extension;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_basename()
+ *
+ * Returns the filename with the extension removed.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_file_basename(const_String_or_char_ptr filename) {
+ String *extension = Swig_file_extension(filename);
+ String *basename = NewStringWithSize(filename, Len(filename) - Len(extension));
+ Delete(extension);
+ return basename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_filename()
+ *
+ * Return the file name with any leading path stripped off
+ * ----------------------------------------------------------------------------- */
+String *Swig_file_filename(const_String_or_char_ptr filename) {
+ const char *delim = SWIG_FILE_DELIMITER;
+ const char *c = strrchr(Char(filename), *delim);
+ return c ? NewString(c + 1) : NewString(filename);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_file_dirname()
+ *
+ * Return the name of the directory associated with a file
+ * ----------------------------------------------------------------------------- */
+String *Swig_file_dirname(const_String_or_char_ptr filename) {
+ const char *delim = SWIG_FILE_DELIMITER;
+ const char *c = strrchr(Char(filename), *delim);
+ return c ? NewStringWithSize(filename, (int)(c - Char(filename) + 1)) : NewString("");
+}
+
+/*
+ * Swig_file_debug()
+ */
+void Swig_file_debug_set(void) {
+ file_debug = 1;
+}
diff --git a/contrib/tools/swig/Source/Swig/misc.c b/contrib/tools/swig/Source/Swig/misc.c
new file mode 100644
index 00000000000..578b2d2855a
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/misc.c
@@ -0,0 +1,1503 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * misc.c
+ *
+ * Miscellaneous functions that don't really fit anywhere else.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
+#endif
+#endif
+
+static char *fake_version = 0;
+
+/* -----------------------------------------------------------------------------
+ * Swig_copy_string()
+ *
+ * Duplicate a NULL-terminate string given as a char *.
+ * ----------------------------------------------------------------------------- */
+
+char *Swig_copy_string(const char *s) {
+ char *c = 0;
+ if (s) {
+ c = (char *) Malloc(strlen(s) + 1);
+ strcpy(c, s);
+ }
+ return c;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_set_fakeversion()
+ *
+ * Version string override
+ * ----------------------------------------------------------------------------- */
+
+void Swig_set_fakeversion(const char *version) {
+ fake_version = Swig_copy_string(version);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_package_version()
+ *
+ * Return the package string containing the version number
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_package_version(void) {
+ return fake_version ? fake_version : PACKAGE_VERSION;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_package_version_hex()
+ *
+ * Return the package version in hex format "0xAABBCC" such as "0x040200" for 4.2.0
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_package_version_hex(void) {
+ String *package_version = NewString(Swig_package_version());
+ char *token = strtok(Char(package_version), ".");
+ String *vers = NewString("SWIG_VERSION 0x");
+ int count = 0;
+ while (token) {
+ int len = (int)strlen(token);
+ assert(len == 1 || len == 2);
+ Printf(vers, "%s%s", (len == 1) ? "0" : "", token);
+ token = strtok(NULL, ".");
+ count++;
+ }
+ Delete(package_version);
+ assert(count == 3); /* Check version format is correct */
+ return vers;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_obligatory_macros()
+ *
+ * Generates the SWIG_VERSION and SWIGXXX macros where XXX is the target language
+ * name (must be provided uppercase).
+ * ----------------------------------------------------------------------------- */
+
+void Swig_obligatory_macros(String *f_runtime, const char *language) {
+ String *version_hex = Swig_package_version_hex();
+ Printf(f_runtime, "\n\n");
+ Printf(f_runtime, "#define %s\n", version_hex);
+ Printf(f_runtime, "#define SWIG%s\n", language);
+ Delete(version_hex);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_banner()
+ *
+ * Emits the SWIG identifying banner for the C/C++ wrapper file.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_banner(File *f) {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n");
+
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_banner_target_lang()
+ *
+ * Emits a SWIG identifying banner in the target language
+ * ----------------------------------------------------------------------------- */
+
+void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar) {
+ Printf(f, "%s This file was automatically generated by SWIG (https://www.swig.org).\n", commentchar);
+ Printf(f, "%s Version %s\n", commentchar, Swig_package_version());
+ Printf(f, "%s\n", commentchar);
+ Printf(f, "%s Do not make changes to this file unless you know what you are doing - modify\n", commentchar);
+ Printf(f, "%s the SWIG interface file instead.\n", commentchar);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_strip_c_comments()
+ *
+ * Return a new string with C comments stripped from the input string. NULL is
+ * returned if there aren't any comments.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_strip_c_comments(const String *s) {
+ const char *c = Char(s);
+ const char *comment_begin = 0;
+ const char *comment_end = 0;
+ String *stripped = 0;
+
+ while (*c) {
+ if (!comment_begin && *c == '/') {
+ ++c;
+ if (!*c)
+ break;
+ if (*c == '*')
+ comment_begin = c-1;
+ } else if (comment_begin && !comment_end && *c == '*') {
+ ++c;
+ if (*c == '/') {
+ comment_end = c;
+ break;
+ }
+ }
+ ++c;
+ }
+
+ if (comment_begin && comment_end) {
+ int size = (int)(comment_begin - Char(s));
+ String *stripmore = 0;
+ stripped = NewStringWithSize(s, size);
+ Printv(stripped, comment_end + 1, NIL);
+ do {
+ stripmore = Swig_strip_c_comments(stripped);
+ if (stripmore) {
+ Delete(stripped);
+ stripped = stripmore;
+ }
+ } while (stripmore);
+ }
+ return stripped;
+}
+
+/* -----------------------------------------------------------------------------
+ * is_directory()
+ * ----------------------------------------------------------------------------- */
+static int is_directory(String *directory) {
+ int last = Len(directory) - 1;
+ int statres;
+ struct stat st;
+ char *dir = Char(directory);
+ if (dir[last] == SWIG_FILE_DELIMITER[0]) {
+ /* remove trailing slash - can cause S_ISDIR to fail on Windows, at least */
+ dir[last] = 0;
+ statres = stat(dir, &st);
+ dir[last] = SWIG_FILE_DELIMITER[0];
+ } else {
+ statres = stat(dir, &st);
+ }
+ return (statres == 0 && S_ISDIR(st.st_mode));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_new_subdirectory()
+ *
+ * Create the subdirectory only if the basedirectory already exists as a directory.
+ * basedirectory can be empty to indicate current directory but not NULL.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_new_subdirectory(String *basedirectory, String *subdirectory) {
+ String *error = 0;
+ int current_directory = Len(basedirectory) == 0;
+
+ if (current_directory || is_directory(basedirectory)) {
+ Iterator it;
+ String *dir = NewString(basedirectory);
+ List *subdirs = Split(subdirectory, SWIG_FILE_DELIMITER[0], INT_MAX);
+
+ for (it = First(subdirs); it.item; it = Next(it)) {
+ int result;
+ String *subdirectory = it.item;
+ Printf(dir, "%s", subdirectory);
+#ifdef _WIN32
+ result = _mkdir(Char(dir));
+#else
+ result = mkdir(Char(dir), 0777);
+#endif
+ if (result != 0 && errno != EEXIST) {
+ error = NewStringf("Cannot create directory %s: %s", dir, strerror(errno));
+ break;
+ }
+ if (!is_directory(dir)) {
+ error = NewStringf("Cannot create directory %s: it may already exist but not be a directory", dir);
+ break;
+ }
+ Printf(dir, SWIG_FILE_DELIMITER);
+ }
+ } else {
+ error = NewStringf("Cannot create subdirectory %s under the base directory %s. Either the base does not exist as a directory or it is not readable.", subdirectory, basedirectory);
+ }
+ return error;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_correct()
+ *
+ * Corrects filename paths by removing duplicate delimiters and on non-unix
+ * systems use the correct delimiter across the whole name.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_filename_correct(String *filename) {
+ int network_path = 0;
+ if (Len(filename) >= 2) {
+ const char *fname = Char(filename);
+ if (fname[0] == '\\' && fname[1] == '\\')
+ network_path = 1;
+ if (fname[0] == '/' && fname[1] == '/')
+ network_path = 1;
+ }
+#if defined(_WIN32)
+ /* accept Unix path separator on non-Unix systems */
+ Replaceall(filename, "/", SWIG_FILE_DELIMITER);
+#endif
+#if defined(__CYGWIN__)
+ /* accept Windows path separator in addition to Unix path separator */
+ Replaceall(filename, "\\", SWIG_FILE_DELIMITER);
+#endif
+ /* remove all duplicate file name delimiters */
+ while (Replaceall(filename, SWIG_FILE_DELIMITER SWIG_FILE_DELIMITER, SWIG_FILE_DELIMITER)) {
+ }
+ /* Network paths can start with a double slash on Windows - unremove the duplicate slash we just removed */
+ if (network_path)
+ Insert(filename, 0, SWIG_FILE_DELIMITER);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_escape()
+ *
+ * Escapes backslashes in filename - for Windows
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_filename_escape(String *filename) {
+ String *adjusted_filename = Copy(filename);
+ Swig_filename_correct(adjusted_filename);
+#if defined(_WIN32) /* Note not on Cygwin else filename is displayed with double '/' */
+ Replaceall(adjusted_filename, "\\", "\\\\");
+#endif
+ return adjusted_filename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_escape()
+ *
+ * Escapes spaces in filename - for Makefiles
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_filename_escape_space(String *filename) {
+ String *adjusted_filename = Copy(filename);
+ Swig_filename_correct(adjusted_filename);
+ Replaceall(adjusted_filename, " ", "\\ ");
+ return adjusted_filename;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_filename_unescape()
+ *
+ * Remove double backslash escaping in filename - for Windows
+ * ----------------------------------------------------------------------------- */
+
+void Swig_filename_unescape(String *filename) {
+ (void)filename;
+#if defined(_WIN32)
+ Replaceall(filename, "\\\\", "\\");
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isextern()
+ *
+ * Determine if the storage class specifier is extern (but not externc)
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isextern(Node *n) {
+ const String *storage = Getattr(n, "storage");
+ return storage ? Strcmp(storage, "extern") == 0 || Strncmp(storage, "extern ", 7) == 0 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isexternc()
+ *
+ * Determine if the storage class specifier is externc (but not plain extern)
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isexternc(Node *n) {
+ const String *storage = Getattr(n, "storage");
+ return storage ? Strcmp(storage, "externc") == 0 || Strncmp(storage, "externc ", 8) == 0 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isstatic_custom()
+ *
+ * Determine if the storage class specifier is static
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage_name) {
+ const String *storage = Getattr(n, storage_name);
+ return storage ? Strncmp(storage, "static", 6) == 0 : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_storage_isstatic()
+ *
+ * Determine if the storage class specifier is static
+ * ----------------------------------------------------------------------------- */
+
+int Swig_storage_isstatic(Node *n) {
+ return Swig_storage_isstatic_custom(n, "storage");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_escape()
+ *
+ * Takes a string object and produces a string with escape codes added to it.
+ * Octal escaping is used. The result is used for literal strings and characters
+ * in C/C++ and also Java, Python, R and Ruby.
+ *
+ * The result is suitable for wrapping in single or double quotes to form a
+ * character or string literal.
+ *
+ * Note that it's not safe to concatenate the results of escaping two strings
+ * - you need to concatenate first and escape second. The problem case is
+ * when the first string ends with a character which gets escaped using one or
+ * two octal digits and the second string starts with a character which is an
+ * octal digit.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_escape(String *s) {
+ String *ns = NewStringEmpty();
+ int c = Getc(s);
+ while (c != EOF) {
+ if (c == '\n') {
+ Printf(ns, "\\n");
+ } else if (c == '\r') {
+ Printf(ns, "\\r");
+ } else if (c == '\t') {
+ Printf(ns, "\\t");
+ } else if (c == '\\') {
+ Printf(ns, "\\\\");
+ } else if (c == '\'') {
+ Printf(ns, "\\'");
+ } else if (c == '\"') {
+ Printf(ns, "\\\"");
+ } else if (c >= 32 && c < 127) {
+ Putc(c, ns);
+ } else {
+ int next_c = Getc(s);
+ assert(c >= 0);
+ if (next_c >= '0' && next_c < '8') {
+ /* We need to emit 3 octal digits. */
+ Printf(ns, "\\%03o", c);
+ } else {
+ Printf(ns, "\\%o", c);
+ }
+ c = next_c;
+ continue;
+ }
+ c = Getc(s);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_csharpescape()
+ *
+ * Takes a string object and produces a string with escape codes added to it
+ * suitable for use as a C# string or character literal.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_csharpescape(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ while ((c = Getc(s)) != EOF) {
+ if (c == '\n') {
+ Printf(ns, "\\n");
+ } else if (c == '\r') {
+ Printf(ns, "\\r");
+ } else if (c == '\t') {
+ Printf(ns, "\\t");
+ } else if (c == '\\') {
+ Printf(ns, "\\\\");
+ } else if (c == '\'') {
+ Printf(ns, "\\'");
+ } else if (c == '\"') {
+ Printf(ns, "\\\"");
+ } else if (c >= 32 && c < 127) {
+ Putc(c, ns);
+ } else {
+ assert(c >= 0);
+ // Emit 4 hex digits in case the next character is a hex digit.
+ Printf(ns, "\\x%04X", c);
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_goescape()
+ *
+ * Takes a string object and produces a string with escape codes added to it
+ * suitable for use as a Go string or character literal.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_goescape(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ while ((c = Getc(s)) != EOF) {
+ if (c == '\n') {
+ Printf(ns, "\\n");
+ } else if (c == '\r') {
+ Printf(ns, "\\r");
+ } else if (c == '\t') {
+ Printf(ns, "\\t");
+ } else if (c == '\\') {
+ Printf(ns, "\\\\");
+ } else if (c >= 32 && c < 127 && c != '\'' && c != '"') {
+ Putc(c, ns);
+ } else {
+ // In Go, \' isn't valid in a double quoted string, while \" isn't valid
+ // in a single quoted rune, so to avoid needing two different escaping
+ // functions we always escape both using hex escapes.
+ assert(c >= 0);
+ Printf(ns, "\\x%02x", c);
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_upper()
+ *
+ * Takes a string object and returns a copy that is uppercase
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_upper(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ Putc(toupper(c), ns);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_lower()
+ *
+ * Takes a string object and returns a copy that is lowercase
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_lower(String *s) {
+ String *ns;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ Putc(tolower(c), ns);
+ }
+ return ns;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_title()
+ *
+ * Takes a string object and returns a copy that is lowercase with first letter
+ * capitalized
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_string_title(String *s) {
+ String *ns;
+ int first = 1;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ Putc(first ? toupper(c) : tolower(c), ns);
+ first = 0;
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_ccase()
+ *
+ * Takes a string object and returns a copy that is lowercase with the first
+ * letter capitalized and the one following '_', which are removed.
+ *
+ * camel_case -> CamelCase
+ * camelCase -> CamelCase
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_ccase(String *s) {
+ String *ns;
+ int first = 1;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ if (c == '_') {
+ first = 1;
+ continue;
+ }
+ Putc(first ? toupper(c) : c, ns);
+ first = 0;
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_lccase()
+ *
+ * Takes a string object and returns a copy with the character after
+ * each '_' capitalised, and the '_' removed. The first character is
+ * also forced to lowercase.
+ *
+ * camel_case -> camelCase
+ * CamelCase -> camelCase
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_lccase(String *s) {
+ String *ns;
+ int first = 1;
+ int after_underscore = 0;
+ int c;
+ ns = NewStringEmpty();
+
+ Seek(s, 0, SEEK_SET);
+ while ((c = Getc(s)) != EOF) {
+ if (c == '_') {
+ after_underscore = 1;
+ continue;
+ }
+ if (first) {
+ Putc(tolower(c), ns);
+ first = 0;
+ } else {
+ Putc(after_underscore ? toupper(c) : c, ns);
+ }
+ after_underscore = 0;
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_ucase()
+ *
+ * This is the reverse case of ccase, ie
+ *
+ * CamelCase -> camel_case
+ * get2D -> get_2d
+ * asFloat2 -> as_float2
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_ucase(String *s) {
+ String *ns;
+ int c;
+ int lastC = 0;
+ int nextC = 0;
+ int underscore = 0;
+ ns = NewStringEmpty();
+
+ /* We insert a underscore when:
+ 1. Lower case char followed by upper case char
+ getFoo > get_foo; getFOo > get_foo; GETFOO > getfoo
+ 2. Number preceded by char and not end of string
+ get2D > get_2d; get22D > get_22d; GET2D > get_2d
+ but:
+ asFloat2 > as_float2
+ */
+
+ Seek(s, 0, SEEK_SET);
+
+ while ((c = Getc(s)) != EOF) {
+ nextC = Getc(s); Ungetc(nextC, s);
+ if (isdigit(c) && isalpha(lastC) && nextC != EOF)
+ underscore = 1;
+ else if (isupper(c) && isalpha(lastC) && !isupper(lastC))
+ underscore = 1;
+
+ lastC = c;
+
+ if (underscore) {
+ Putc('_', ns);
+ underscore = 0;
+ }
+
+ Putc(tolower(c), ns);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_first_upper()
+ *
+ * Make the first character in the string uppercase, leave all the
+ * rest the same. This is used by the Ruby module to provide backwards
+ * compatibility with the old way of naming classes and constants. For
+ * more info see the Ruby documentation.
+ *
+ * firstUpper -> FirstUpper
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_first_upper(String *s) {
+ String *ns = NewStringEmpty();
+ char *cs = Char(s);
+ if (cs && cs[0] != 0) {
+ Putc(toupper((int)cs[0]), ns);
+ Append(ns, cs + 1);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_first_lower()
+ *
+ * Make the first character in the string lowercase, leave all the
+ * rest the same. This is used by the Ruby module to provide backwards
+ * compatibility with the old way of naming classes and constants. For
+ * more info see the Ruby documentation.
+ *
+ * firstLower -> FirstLower
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_first_lower(String *s) {
+ String *ns = NewStringEmpty();
+ char *cs = Char(s);
+ if (cs && cs[0] != 0) {
+ Putc(tolower((int)cs[0]), ns);
+ Append(ns, cs + 1);
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_schemify()
+ *
+ * Replace underscores with dashes, to make identifiers look nice to Schemers.
+ *
+ * under_scores -> under-scores
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_schemify(String *s) {
+ String *ns = NewString(s);
+ Replaceall(ns, "_", "-");
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_typecode()
+ *
+ * Takes a string with possible type-escapes in it and replaces them with
+ * real C datatypes.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_typecode(String *s) {
+ String *ns;
+ int c;
+ String *tc;
+ ns = NewStringEmpty();
+ while ((c = Getc(s)) != EOF) {
+ if (c == '`') {
+ String *str = 0;
+ tc = NewStringEmpty();
+ while ((c = Getc(s)) != EOF) {
+ if (c == '`')
+ break;
+ Putc(c, tc);
+ }
+ str = SwigType_str(tc, 0);
+ Append(ns, str);
+ Delete(str);
+ } else {
+ Putc(c, ns);
+ if (c == '\'') {
+ while ((c = Getc(s)) != EOF) {
+ Putc(c, ns);
+ if (c == '\'')
+ break;
+ if (c == '\\') {
+ c = Getc(s);
+ Putc(c, ns);
+ }
+ }
+ } else if (c == '\"') {
+ while ((c = Getc(s)) != EOF) {
+ Putc(c, ns);
+ if (c == '\"')
+ break;
+ if (c == '\\') {
+ c = Getc(s);
+ Putc(c, ns);
+ }
+ }
+ }
+ }
+ }
+ return ns;
+}
+
+static String *string_mangle(String *s) {
+ return Swig_name_mangle_string(s);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_split()
+ *
+ * Take a qualified name like "A::B::C" and splits off the last name.
+ * In this case, returns "C" as last and "A::B" as prefix.
+ * Always returns non NULL for last, but prefix may be NULL if there is no prefix.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_scopename_split(const String *s, String **rprefix, String **rlast) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *cc = c;
+ char *co = 0;
+ if (!strstr(c, "::")) {
+ *rprefix = 0;
+ *rlast = Copy(s);
+ }
+
+ co = strstr(cc, "operator ");
+ if (co) {
+ if (co == cc) {
+ *rprefix = 0;
+ *rlast = Copy(s);
+ return;
+ } else {
+ *rprefix = NewStringWithSize(cc, (int)(co - cc - 2));
+ *rlast = NewString(co);
+ return;
+ }
+ }
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ cc = c;
+ c += 2;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+
+ if (cc != tmp) {
+ *rprefix = NewStringWithSize(tmp, (int)(cc - tmp));
+ *rlast = NewString(cc + 2);
+ return;
+ } else {
+ *rprefix = 0;
+ *rlast = Copy(s);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_prefix()
+ *
+ * Take a qualified name like "A::B::C" and return the scope name.
+ * In this case, "A::B". Returns NULL if there is no base.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_prefix(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *cc = c;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return 0;
+ co = strstr(cc, "operator ");
+
+ if (co) {
+ if (co == cc) {
+ return 0;
+ } else {
+ String *prefix = NewStringWithSize(cc, (int)(co - cc - 2));
+ return prefix;
+ }
+ }
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ cc = c;
+ c += 2;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+
+ if (cc != tmp) {
+ return NewStringWithSize(tmp, (int)(cc - tmp));
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_last()
+ *
+ * Take a qualified name like "A::B::C" and returns the last. In this
+ * case, "C".
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_last(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *cc = c;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return NewString(s);
+
+ co = strstr(cc, "operator ");
+ if (co) {
+ return NewString(co);
+ }
+
+
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ c += 2;
+ cc = c;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ return NewString(cc);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_first()
+ *
+ * Take a qualified name like "A::B::C" and returns the first scope name.
+ * In this case, "A". Returns NULL if there is no base.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_first(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return 0;
+
+ co = strstr(c, "operator ");
+ if (co) {
+ if (co == c) {
+ return 0;
+ }
+ } else {
+ co = c + Len(s);
+ }
+
+ while (*c && (c != co)) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ break;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ if (*c && (c != tmp)) {
+ return NewStringWithSize(tmp, (int)(c - tmp));
+ } else {
+ return 0;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_suffix()
+ *
+ * Take a qualified name like "A::B::C" and returns the suffix.
+ * In this case, "B::C". Returns NULL if there is no suffix.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_scopename_suffix(const String *s) {
+ char *tmp = Char(s);
+ char *c = tmp;
+ char *co = 0;
+ if (!strstr(c, "::"))
+ return 0;
+
+ co = strstr(c, "operator ");
+ if (co) {
+ if (co == c)
+ return 0;
+ }
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ break;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ if (*c && (c != tmp)) {
+ return NewString(c + 2);
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_tolist()
+ *
+ * Take a qualified scope name like "A::B::C" and convert it to a list.
+ * In this case, return a list of 3 elements "A", "B", "C".
+ * Returns an empty list if the input is empty.
+ * ----------------------------------------------------------------------------- */
+
+List *Swig_scopename_tolist(const String *s) {
+ List *scopes = NewList();
+ String *name = Len(s) == 0 ? 0 : NewString(s);
+
+ while (name) {
+ String *last = 0;
+ String *prefix = 0;
+ Swig_scopename_split(name, &prefix, &last);
+ Insert(scopes, 0, last);
+ Delete(last);
+ Delete(name);
+ name = prefix;
+ }
+ Delete(name);
+ return scopes;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_isvalid()
+ *
+ * Checks that s is a valid scopename (C++ namespace scope)
+ * ----------------------------------------------------------------------------- */
+
+int Swig_scopename_isvalid(const String *s) {
+ List *scopes = Swig_scopename_tolist(s);
+ int valid = 0;
+ Iterator si;
+
+ for (si = First(scopes); si.item; si = Next(si)) {
+ String *subscope = si.item;
+ valid = subscope && Len(subscope) > 0;
+ if (valid)
+ valid = Swig_symbol_isvalid(subscope);
+ if (!valid)
+ break;
+ }
+ return valid;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_scopename_check()
+ *
+ * Checks to see if a name is qualified with a scope name, examples:
+ * foo -> 0
+ * ::foo -> 1
+ * foo::bar -> 1
+ * foo< ::bar > -> 0
+ * ----------------------------------------------------------------------------- */
+
+int Swig_scopename_check(const String *s) {
+ char *c = Char(s);
+ char *co = strstr(c, "operator ");
+
+ if (co) {
+ if (co == c)
+ return 0;
+ }
+ if (!strstr(c, "::"))
+ return 0;
+ while (*c) {
+ if ((*c == ':') && (*(c + 1) == ':')) {
+ return 1;
+ } else {
+ if (*c == '<') {
+ int level = 1;
+ c++;
+ while (*c && level) {
+ if (*c == '<')
+ level++;
+ if (*c == '>')
+ level--;
+ c++;
+ }
+ } else {
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_command()
+ *
+ * Feature removed in SWIG 4.1.0.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_command(String *s) {
+ Swig_error("SWIG", Getline(s), "Command encoder no longer supported - use regex encoder instead, command:%s\n", s);
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_strip()
+ *
+ * Strip given prefix from identifiers
+ *
+ * Printf(stderr,"%(strip:[wx])s","wxHello") -> Hello
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_strip(String *s) {
+ String *ns;
+ if (!Len(s)) {
+ ns = NewString(s);
+ } else {
+ const char *cs = Char(s);
+ const char *ce = Strchr(cs, ']');
+ if (*cs != '[' || !ce) {
+ ns = NewString(s);
+ } else {
+ String *fmt = NewStringf("%%.%ds", ce-cs-1);
+ String *prefix = NewStringf(fmt, cs+1);
+ if (0 == Strncmp(ce+1, prefix, Len(prefix))) {
+ ns = NewString(ce+1+Len(prefix));
+ } else {
+ ns = NewString(ce+1);
+ }
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_rstrip()
+ *
+ * Strip given suffix from identifiers
+ *
+ * Printf(stderr,"%(rstrip:[Cls])s","HelloCls") -> Hello
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_string_rstrip(String *s) {
+ String *ns;
+ int len = Len(s);
+ if (!len) {
+ ns = NewString(s);
+ } else {
+ const char *cs = Char(s);
+ const char *ce = Strchr(cs, ']');
+ if (*cs != '[' || !ce) {
+ ns = NewString(s);
+ } else {
+ String *fmt = NewStringf("%%.%ds", ce-cs-1);
+ String *suffix = NewStringf(fmt, cs+1);
+ int suffix_len = Len(suffix);
+ if (0 == Strncmp(cs+len-suffix_len, suffix, suffix_len)) {
+ int copy_len = len-suffix_len-(int)(ce+1-cs);
+ ns = NewStringWithSize(ce+1, copy_len);
+ } else {
+ ns = NewString(ce+1);
+ }
+ }
+ }
+ return ns;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_offset_string()
+ *
+ * Insert number tabs before each new line in s
+ * ----------------------------------------------------------------------------- */
+
+void Swig_offset_string(String *s, int number) {
+ char *res, *p, *end, *start;
+ /* count a number of lines in s */
+ int lines = 1;
+ int len = Len(s);
+ if (len == 0)
+ return;
+ 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
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
+static int split_regex_pattern_subst(String *s, String **pattern, String **subst, const char **input)
+{
+ const char *pats, *pate;
+ const char *subs, *sube;
+
+ /* Locate the search pattern */
+ const char *p = Char(s);
+ if (*p++ != '/') goto err_out;
+ pats = p;
+ p = strchr(p, '/');
+ if (!p) goto err_out;
+ pate = p;
+
+ /* Locate the substitution string */
+ subs = ++p;
+ p = strchr(p, '/');
+ if (!p) goto err_out;
+ sube = p;
+
+ *pattern = NewStringWithSize(pats, (int)(pate - pats));
+ *subst = NewStringWithSize(subs, (int)(sube - subs));
+ *input = p + 1;
+ return 1;
+
+err_out:
+ Swig_error("SWIG", Getline(s), "Invalid regex substitution: '%s'.\n", s);
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+/* This function copies len characters from src to dst, possibly applying case conversions to them: if convertCase is 1, to upper case and if it is -1, to lower
+ * case. If convertNextOnly is 1, only a single character is converted (and convertCase is reset), otherwise all of them are. */
+static void copy_with_maybe_case_conversion(String *dst, const char *src, int len, int *convertCase, int convertNextOnly)
+{
+ /* Deal with the trivial cases first. */
+ if (!len)
+ return;
+
+ if (!*convertCase) {
+ Write(dst, src, len);
+ return;
+ }
+
+ /* If we must convert only the first character, do it and write the rest at once. */
+ if (convertNextOnly) {
+ int src_char = *src;
+ Putc(*convertCase == 1 ? toupper(src_char) : tolower(src_char), dst);
+ *convertCase = 0;
+ if (len > 1) {
+ Write(dst, src + 1, len - 1);
+ }
+ } else {
+ /* We need to convert all characters. */
+ int i;
+ for (i = 0; i < len; i++, src++) {
+ int src_char = *src;
+ Putc(*convertCase == 1 ? toupper(src_char) : tolower(src_char), dst);
+ }
+ }
+}
+
+static String *replace_captures(int num_captures, const char *input, String *subst, size_t captures[], String *pattern, String *s)
+{
+ int convertCase = 0, convertNextOnly = 0;
+ String *result = NewStringEmpty();
+ const char *p = Char(subst);
+
+ while (*p) {
+ /* Copy part without substitutions */
+ const char *q = strchr(p, '\\');
+ if (!q) {
+ copy_with_maybe_case_conversion(result, p, (int)strlen(p), &convertCase, convertNextOnly);
+ break;
+ }
+ copy_with_maybe_case_conversion(result, p, (int)(q - p), &convertCase, convertNextOnly);
+ p = q + 1;
+
+ /* Handle substitution */
+ if (*p == '\0') {
+ Putc('\\', result);
+ } else if (isdigit((unsigned char)*p)) {
+ int group = *p++ - '0';
+ if (group < num_captures) {
+ int l = (int)captures[group*2], r = (int)captures[group*2 + 1];
+ if (l != -1) {
+ copy_with_maybe_case_conversion(result, input + l, r - l, &convertCase, convertNextOnly);
+ }
+ } else {
+ Swig_error("SWIG", Getline(s), "PCRE capture replacement failed while matching \"%s\" using \"%s\" - request for group %d is greater than the number of captures %d.\n",
+ Char(pattern), input, group, num_captures-1);
+ }
+ } else {
+ /* Handle Perl-like case conversion escapes. */
+ switch (*p) {
+ case 'u':
+ convertCase = 1;
+ convertNextOnly = 1;
+ break;
+ case 'U':
+ convertCase = 1;
+ convertNextOnly = 0;
+ break;
+ case 'l':
+ convertCase = -1;
+ convertNextOnly = 1;
+ break;
+ case 'L':
+ convertCase = -1;
+ convertNextOnly = 0;
+ break;
+ case 'E':
+ convertCase = 0;
+ break;
+ default:
+ Swig_error("SWIG", Getline(s), "Unrecognized escape character '%c' in the replacement string \"%s\".\n",
+ *p, Char(subst));
+ }
+ p++;
+ }
+ }
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_string_regex()
+ *
+ * Executes a regular expression substitution. For example:
+ *
+ * Printf(stderr,"gsl%(regex:/GSL_(.*)_/\\1/)s", "GSL_Hello_") -> gslHello
+ * ----------------------------------------------------------------------------- */
+static String *Swig_string_regex(String *s) {
+ const int pcre_options = 0;
+
+ String *res = 0;
+ pcre2_code *compiled_pat = 0;
+ const char *input;
+ PCRE2_UCHAR pcre_error[256];
+ int pcre_errornum;
+ size_t pcre_errorpos;
+ String *pattern = 0, *subst = 0;
+ size_t *captures = 0;
+ pcre2_match_data *match_data = 0;
+ if (split_regex_pattern_subst(s, &pattern, &subst, &input)) {
+ int rc;
+
+ compiled_pat = pcre2_compile(
+ (PCRE2_SPTR8)Char(pattern), PCRE2_ZERO_TERMINATED, pcre_options, &pcre_errornum, &pcre_errorpos, NULL);
+ if (!compiled_pat) {
+ pcre2_get_error_message (pcre_errornum, pcre_error, sizeof pcre_error);
+ Swig_error("SWIG", Getline(s), "PCRE compilation failed: '%s' in '%s':%i.\n",
+ pcre_error, Char(pattern), pcre_errorpos);
+ Exit(EXIT_FAILURE);
+ }
+ match_data = pcre2_match_data_create_from_pattern (compiled_pat, NULL);
+ rc = pcre2_match(compiled_pat, (PCRE2_SPTR8)input, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL);
+ captures = pcre2_get_ovector_pointer (match_data);
+ if (rc >= 0) {
+ res = replace_captures(rc, input, subst, captures, pattern, s);
+ } else if (rc != PCRE2_ERROR_NOMATCH) {
+ Swig_error("SWIG", Getline(s), "PCRE execution failed: error %d while matching \"%s\" using \"%s\".\n",
+ rc, Char(pattern), input);
+ Exit(EXIT_FAILURE);
+ }
+ }
+
+ Delete(pattern);
+ Delete(subst);
+ pcre2_code_free(compiled_pat);
+ pcre2_match_data_free(match_data);
+ return res ? res : NewStringEmpty();
+}
+
+String *Swig_pcre_version(void) {
+ int len = pcre2_config(PCRE2_CONFIG_VERSION, NULL);
+ char *buf = Malloc(len);
+ String *result;
+ pcre2_config(PCRE2_CONFIG_VERSION, buf);
+ result = NewStringf("PCRE2 Version: %s", buf);
+ Free(buf);
+ return result;
+}
+
+#else
+
+String *Swig_string_regex(String *s) {
+ Swig_error("SWIG", Getline(s), "PCRE regex support not enabled in this SWIG build.\n");
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+String *Swig_pcre_version(void) {
+ return NewStringf("PCRE not used");
+}
+
+#endif
+
+/* ------------------------------------------------------------
+ * Swig_is_generated_overload()
+ * Check if the function is an automatically generated
+ * overload created because a method has default parameters.
+ * ------------------------------------------------------------ */
+
+int Swig_is_generated_overload(Node *n) {
+ Node *base_method = Getattr(n, "sym:overloaded");
+ Node *default_args = Getattr(n, "defaultargs");
+ return ((base_method != NULL) && (default_args != NULL) && (base_method == default_args));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_item_in_list()
+ *
+ * If the input item is in the list, return the item.
+ * Note: uses DohCmp for comparisons so for a List of String *, Strcmp is ultimately
+ * used for item comparisons to determine if a string is in the list.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_item_in_list(List *list, const DOH *item) {
+ Node *found_item = 0;
+ if (list) {
+ Iterator it;
+ for (it = First(list); it.item; it = Next(it)) {
+ if (DohCmp(item, it.item) == 0) {
+ found_item = it.item;
+ break;
+ }
+ }
+ }
+ return found_item;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_init()
+ *
+ * Initialize the SWIG core
+ * ----------------------------------------------------------------------------- */
+
+void Swig_init(void) {
+ /* Set some useful string encoding methods */
+ DohEncoding("escape", Swig_string_escape);
+ DohEncoding("csharpescape", Swig_string_csharpescape);
+ DohEncoding("goescape", Swig_string_goescape);
+ DohEncoding("upper", Swig_string_upper);
+ DohEncoding("lower", Swig_string_lower);
+ DohEncoding("title", Swig_string_title);
+ DohEncoding("ctitle", Swig_string_ccase);
+ DohEncoding("lctitle", Swig_string_lccase);
+ DohEncoding("utitle", Swig_string_ucase);
+ DohEncoding("typecode", Swig_string_typecode);
+ DohEncoding("mangle", string_mangle);
+ DohEncoding("command", Swig_string_command);
+ DohEncoding("schemify", Swig_string_schemify);
+ DohEncoding("strip", Swig_string_strip);
+ DohEncoding("rstrip", Swig_string_rstrip);
+ DohEncoding("regex", Swig_string_regex);
+
+ /* aliases for the case encoders */
+ DohEncoding("uppercase", Swig_string_upper);
+ DohEncoding("lowercase", Swig_string_lower);
+ DohEncoding("camelcase", Swig_string_ccase);
+ DohEncoding("lowercamelcase", Swig_string_lccase);
+ DohEncoding("undercase", Swig_string_ucase);
+ DohEncoding("firstuppercase", Swig_string_first_upper);
+ DohEncoding("firstlowercase", Swig_string_first_lower);
+
+ /* Initialize typemaps */
+ Swig_typemap_init();
+
+ /* Initialize symbol table */
+ Swig_symbol_init();
+
+ /* Initialize type system */
+ SwigType_typesystem_init();
+
+ /* Initialize template system */
+ SwigType_template_init();
+}
diff --git a/contrib/tools/swig/Source/Swig/naming.c b/contrib/tools/swig/Source/Swig/naming.c
new file mode 100644
index 00000000000..3f34aab5995
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/naming.c
@@ -0,0 +1,1949 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * naming.c
+ *
+ * Functions for generating various kinds of names during code generation.
+ *
+ * Swig_name_register is used to register a format string for generating names.
+ * The format string makes use of the following format specifiers:
+ *
+ * %c - class name is substituted
+ * %f - function name is substituted
+ * %m - member name is substituted
+ * %n - namespace is substituted
+ * %v - variable name is substituted
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* Hash table containing naming data */
+
+static Hash *naming_hash = 0;
+
+#if 0
+#define SWIG_DEBUG
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_register()
+ *
+ * Register a new naming format.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_register(const_String_or_char_ptr method, const_String_or_char_ptr format) {
+ if (!naming_hash)
+ naming_hash = NewHash();
+ Setattr(naming_hash, method, format);
+}
+
+void Swig_name_unregister(const_String_or_char_ptr method) {
+ if (naming_hash) {
+ Delattr(naming_hash, method);
+ }
+}
+
+/* Return naming format for the specified method or the default format if none was explicitly registered */
+static String* get_naming_format_for(const char *method, const char *def_format) {
+ String* f = naming_hash ? Getattr(naming_hash, method) : NULL;
+
+ return f ? Copy(f) : NewString(def_format);
+}
+
+static int name_mangle(String *r) {
+ char *c;
+ int special;
+ special = 0;
+ Replaceall(r, "::", "_");
+ c = Char(r);
+ while (*c) {
+ if (!isalnum((int) *c) && (*c != '_')) {
+ special = 1;
+ switch (*c) {
+ case '+':
+ *c = 'a';
+ break;
+ case '-':
+ *c = 's';
+ break;
+ case '*':
+ *c = 'm';
+ break;
+ case '/':
+ *c = 'd';
+ break;
+ case '<':
+ *c = 'l';
+ break;
+ case '>':
+ *c = 'g';
+ break;
+ case '=':
+ *c = 'e';
+ break;
+ case ',':
+ *c = 'c';
+ break;
+ case '(':
+ *c = 'p';
+ break;
+ case ')':
+ *c = 'P';
+ break;
+ case '[':
+ *c = 'b';
+ break;
+ case ']':
+ *c = 'B';
+ break;
+ case '^':
+ *c = 'x';
+ break;
+ case '&':
+ *c = 'A';
+ break;
+ case '|':
+ *c = 'o';
+ break;
+ case '~':
+ *c = 'n';
+ break;
+ case '!':
+ *c = 'N';
+ break;
+ case '%':
+ *c = 'M';
+ break;
+ case '.':
+ *c = 'f';
+ break;
+ case '?':
+ *c = 'q';
+ break;
+ default:
+ *c = '_';
+ break;
+ }
+ }
+ c++;
+ }
+ if (special)
+ Append(r, "___");
+ return special;
+}
+
+/* -----------------------------------------------------------------------------
+ * replace_nspace()
+ *
+ * Mangles in the namespace from nspace by replacing %n in name if nspace feature required.
+ * ----------------------------------------------------------------------------- */
+
+static void replace_nspace(String *name, const_String_or_char_ptr nspace) {
+ if (nspace) {
+ String *namspace = NewStringf("%s_", nspace);
+ Replaceall(namspace, NSPACE_SEPARATOR, "_");
+ Replace(name, "%n", namspace, DOH_REPLACE_ANY);
+ Delete(namspace);
+ } else {
+ Replace(name, "%n", "", DOH_REPLACE_ANY);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_mangle_type()
+ *
+ * Same as Swig_name_mangle_string, but converting internal SwigType * to a human
+ * readable string of the type (for templates). Simplifies a type that is a
+ * template to the default template if possible.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_mangle_type(const SwigType *s) {
+ String *mangled = 0;
+ String *b = Copy(s);
+ if (SwigType_istemplate(b)) {
+ String *st = Swig_symbol_template_deftype(b, 0);
+ String *sq = Swig_symbol_type_qualify(st, 0);
+ String *t = SwigType_namestr(sq);
+ Delete(st);
+ Delete(sq);
+ Delete(b);
+ b = t;
+ }
+ mangled = Swig_name_mangle_string(b);
+ Delete(b);
+ return mangled;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_type()
+ *
+ * Returns the name of a type.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_type(const_String_or_char_ptr tname) {
+ String *r, *s;
+ String* f = naming_hash ? Getattr(naming_hash, "type") : NULL;
+
+ /* Don't bother doing anything else if there is no special naming format. */
+ if (f) {
+ s = Copy(f);
+ Replace(s, "%c", tname, DOH_REPLACE_ANY);
+ } else {
+ s = (String*)tname;
+ }
+
+ r = Swig_name_mangle_string(s);
+
+ if (s != tname)
+ Delete(s);
+
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_mangle_string()
+ *
+ * Take a string and mangle it by stripping all non-valid C identifier
+ * characters.
+ *
+ * This routine skips unnecessary blank spaces, therefore mangling
+ * 'char *' and 'char*', 'std::pair<int, int >' and
+ * 'std::pair<int,int>', produce the same result.
+ *
+ * However, note that 'long long' and 'long_long' produce different
+ * mangled strings.
+ *
+ * The mangling method still is not 'perfect', for example std::pair and
+ * std_pair return the same mangling. This is just a little better
+ * than before, but it seems to be enough for most of the purposes.
+ *
+ * Having a perfect mangling will break some examples and code which
+ * assume, for example, that A::get_value will be mangled as
+ * A_get_value.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_mangle_string(const String *s) {
+ String *result = NewStringEmpty();
+ int space = 0;
+ int state = 0;
+ char *pc, *cb;
+
+ pc = cb = Char(s);
+ while (*pc) {
+ char c = *pc;
+ if (isalnum((int) c) || (c == '_')) {
+ state = 1;
+ if (space && (space == state)) {
+ Append(result, "_SS_");
+ }
+ space = 0;
+ Printf(result, "%c", (int) c);
+
+ } else {
+ if (isspace((int) c)) {
+ space = state;
+ ++pc;
+ continue;
+ } else {
+ state = 3;
+ space = 0;
+ }
+ switch (c) {
+ case '.':
+ if ((cb != pc) && (*(pc - 1) == 'p')) {
+ Append(result, "_");
+ ++pc;
+ continue;
+ } else {
+ c = 'f';
+ }
+ break;
+ case ':':
+ if (*(pc + 1) == ':') {
+ Append(result, "_");
+ ++pc;
+ ++pc;
+ continue;
+ }
+ break;
+ case '*':
+ c = 'm';
+ break;
+ case '&':
+ c = 'A';
+ break;
+ case '<':
+ c = 'l';
+ break;
+ case '>':
+ c = 'g';
+ break;
+ case '=':
+ c = 'e';
+ break;
+ case ',':
+ c = 'c';
+ break;
+ case '(':
+ c = 'p';
+ break;
+ case ')':
+ c = 'P';
+ break;
+ case '[':
+ c = 'b';
+ break;
+ case ']':
+ c = 'B';
+ break;
+ case '^':
+ c = 'x';
+ break;
+ case '|':
+ c = 'o';
+ break;
+ case '~':
+ c = 'n';
+ break;
+ case '!':
+ c = 'N';
+ break;
+ case '%':
+ c = 'M';
+ break;
+ case '?':
+ c = 'q';
+ break;
+ case '+':
+ c = 'a';
+ break;
+ case '-':
+ c = 's';
+ break;
+ case '/':
+ c = 'd';
+ break;
+ default:
+ break;
+ }
+ if (isalpha((int) c)) {
+ Printf(result, "_S%c_", (int) c);
+ } else {
+ Printf(result, "_S%02X_", (int) c);
+ }
+ }
+ ++pc;
+ }
+ return result;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_wrapper()
+ *
+ * Returns the name of a wrapper function.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_wrapper(const_String_or_char_ptr fname) {
+ String *r = get_naming_format_for("wrapper", "_wrap_%f");
+
+ Replace(r, "%f", fname, DOH_REPLACE_ANY);
+ name_mangle(r);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_member()
+ *
+ * Returns the name of a class method.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_member(const_String_or_char_ptr nspace, const_String_or_char_ptr classname, const_String_or_char_ptr membername) {
+ String *r;
+ String *rclassname;
+ String *rmembername;
+ char *cname;
+
+ rclassname = SwigType_namestr(classname);
+ rmembername = SwigType_namestr(membername);
+ r = get_naming_format_for("member", "%n%c_%m");
+ cname = Char(rclassname);
+ if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) {
+ cname = strchr(cname, ' ') + 1;
+ }
+ replace_nspace(r, nspace);
+ Replace(r, "%c", cname, DOH_REPLACE_ANY);
+ Replace(r, "%m", rmembername, DOH_REPLACE_ANY);
+ /* name_mangle(r); */
+ Delete(rclassname);
+ Delete(rmembername);
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_get()
+ *
+ * Returns the name of the accessor function used to get a variable.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_get(const_String_or_char_ptr nspace, const_String_or_char_ptr vname) {
+ String *r = get_naming_format_for("get", "%n%v_get");
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_get: '%s'\n", vname);
+#endif
+
+ replace_nspace(r, nspace);
+ Replace(r, "%v", vname, DOH_REPLACE_ANY);
+ /* name_mangle(r); */
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_set()
+ *
+ * Returns the name of the accessor function used to set a variable.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_set(const_String_or_char_ptr nspace, const_String_or_char_ptr vname) {
+ String *r = get_naming_format_for("set", "%n%v_set");
+
+ replace_nspace(r, nspace);
+ Replace(r, "%v", vname, DOH_REPLACE_ANY);
+ /* name_mangle(r); */
+ return r;
+}
+
+/* Common implementation of all Swig_name_<special-method>() functions below. */
+static String *make_full_name_for(const char *method, const char *def_format, const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ String *r;
+ String *rclassname;
+ char *cname;
+
+ rclassname = SwigType_namestr(classname);
+ r = get_naming_format_for(method, def_format);
+
+ cname = Char(rclassname);
+ if ((strncmp(cname, "struct ", 7) == 0) || ((strncmp(cname, "class ", 6) == 0)) || ((strncmp(cname, "union ", 6) == 0))) {
+ cname = strchr(cname, ' ') + 1;
+ }
+
+ replace_nspace(r, nspace);
+ Replace(r, "%c", cname, DOH_REPLACE_ANY);
+ Delete(rclassname);
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_construct()
+ *
+ * Returns the name of the accessor function used to create an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_construct(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("construct", "new_%n%c", nspace, classname);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_copyconstructor()
+ *
+ * Returns the name of the accessor function used to copy an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_copyconstructor(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("copy", "copy_%n%c", nspace, classname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_destroy()
+ *
+ * Returns the name of the accessor function used to destroy an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_destroy(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("destroy", "delete_%n%c", nspace, classname);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_disown()
+ *
+ * Returns the name of the accessor function used to disown an object.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_disown(const_String_or_char_ptr nspace, const_String_or_char_ptr classname) {
+ return make_full_name_for("disown", "disown_%n%c", nspace, classname);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_object_set()
+ *
+ * Sets an object associated with a name and optional declarators.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object) {
+ DOH *n;
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_object_set: '%s', '%s'\n", name, decl);
+#endif
+ n = Getattr(namehash, name);
+ if (!n) {
+ n = NewHash();
+ Setattr(namehash, name, n);
+ Delete(n);
+ }
+ /* Add an object based on the declarator value */
+ if (!decl) {
+ Setattr(n, "start", object);
+ } else {
+ SwigType *cd = Copy(decl);
+ Setattr(n, cd, object);
+ Delete(cd);
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_object_get()
+ *
+ * Return an object associated with an optional class prefix, name, and
+ * declarator. This function operates according to name matching rules
+ * described for the %rename directive in the SWIG manual.
+ * ----------------------------------------------------------------------------- */
+
+static DOH *get_object(Hash *n, String *decl) {
+ DOH *rn = 0;
+ if (!n)
+ return 0;
+ if (decl) {
+ rn = Getattr(n, decl);
+ } else {
+ rn = Getattr(n, "start");
+ }
+ return rn;
+}
+
+static DOH *name_object_get(Hash *namehash, String *tname, SwigType *decl, SwigType *ncdecl) {
+ DOH *rn = 0;
+ Hash *n = Getattr(namehash, tname);
+ if (n) {
+ rn = get_object(n, decl);
+ if ((!rn) && ncdecl)
+ rn = get_object(n, ncdecl);
+ if (!rn)
+ rn = get_object(n, 0);
+ }
+ return rn;
+}
+
+DOH *Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *decl) {
+ String *tname = NewStringEmpty();
+ DOH *rn = 0;
+ char *ncdecl = 0;
+
+ if (!namehash)
+ return 0;
+
+ /* DB: This removed to more tightly control feature/name matching */
+ /* if ((decl) && (SwigType_isqualifier(decl))) {
+ ncdecl = strchr(Char(decl),'.');
+ ncdecl++;
+ }
+ */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_object_get: '%s' '%s', '%s'\n", prefix, name, decl);
+#endif
+
+
+ /* Perform a class-based lookup (if class prefix supplied) */
+ if (prefix) {
+ if (Len(prefix)) {
+ Printf(tname, "%s::%s", prefix, name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ if (!rn) {
+ String *cls = Swig_scopename_last(prefix);
+ if (!Equal(cls, prefix)) {
+ Clear(tname);
+ Printf(tname, "*::%s::%s", cls, name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ }
+ Delete(cls);
+ }
+ /* Lookup a name within a templated-based class */
+ if (!rn) {
+ String *t_name = SwigType_istemplate_templateprefix(prefix);
+ if (t_name) {
+ Clear(tname);
+ Printf(tname, "%s::%s", t_name, name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ Delete(t_name);
+ }
+ }
+ /* Lookup a template-based name within a class */
+ if (!rn) {
+ String *t_name = SwigType_istemplate_templateprefix(name);
+ if (t_name)
+ rn = Swig_name_object_get(namehash, prefix, t_name, decl);
+ Delete(t_name);
+ }
+ }
+ /* A wildcard-based class lookup */
+ if (!rn) {
+ Clear(tname);
+ Printf(tname, "*::%s", name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ }
+ } else {
+ /* Lookup in the global namespace only */
+ Clear(tname);
+ Printf(tname, "::%s", name);
+ rn = name_object_get(namehash, tname, decl, ncdecl);
+ }
+ /* Catch-all */
+ if (!rn) {
+ rn = name_object_get(namehash, name, decl, ncdecl);
+ }
+ if (!rn && Swig_scopename_check(name)) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ rn = name_object_get(namehash, nlast, decl, ncdecl);
+ Delete(nlast);
+ Delete(nprefix);
+ }
+
+ Delete(tname);
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_object_get: found %d\n", rn ? 1 : 0);
+#endif
+
+ return rn;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_object_inherit()
+ *
+ * Implements name-based inheritance scheme.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_object_inherit(Hash *namehash, String *base, String *derived) {
+ Iterator ki;
+ Hash *derh;
+ String *bprefix;
+ String *dprefix;
+ char *cbprefix;
+ int plen;
+
+ if (!namehash)
+ return;
+
+ /* Temporary hash holding all the entries we add while we iterate over
+ namehash itself as we can't modify the latter while iterating over it. */
+ derh = NULL;
+ bprefix = NewStringf("%s::", base);
+ dprefix = NewStringf("%s::", derived);
+ cbprefix = Char(bprefix);
+ plen = (int)strlen(cbprefix);
+ for (ki = First(namehash); ki.key; ki = Next(ki)) {
+ char *k = Char(ki.key);
+ if (strncmp(k, cbprefix, plen) == 0) {
+ /* Copy, adjusting name, this element to the derived hash. */
+ Iterator oi;
+ String *nkey = NewStringf("%s%s", dprefix, k + plen);
+ Hash *n = ki.item;
+ Hash *newh;
+
+ /* Don't overwrite an existing value for the derived class, if any. */
+ newh = Getattr(namehash, nkey);
+ if (!newh) {
+ if (!derh)
+ derh = NewHash();
+
+ newh = NewHash();
+ Setattr(derh, nkey, newh);
+ Delete(newh);
+ }
+ for (oi = First(n); oi.key; oi = Next(oi)) {
+ if (!Getattr(newh, oi.key)) {
+ String *ci = Copy(oi.item);
+ Setattr(newh, oi.key, ci);
+ Delete(ci);
+ }
+ }
+ Delete(nkey);
+ }
+ }
+
+ /* Merge the contents of derived hash into the main hash. */
+ if (derh) {
+ for (ki = First(derh); ki.key; ki = Next(ki)) {
+ Setattr(namehash, ki.key, ki.item);
+ }
+ }
+
+ Delete(bprefix);
+ Delete(dprefix);
+ Delete(derh);
+}
+
+/* -----------------------------------------------------------------------------
+ * merge_features()
+ *
+ * Given a hash, this function merges the features in the hash into the node.
+ * ----------------------------------------------------------------------------- */
+
+static void merge_features(Hash *features, Node *n) {
+ Iterator ki;
+
+ if (!features)
+ return;
+ for (ki = First(features); ki.key; ki = Next(ki)) {
+ String *ci = Copy(ki.item);
+ Setattr(n, ki.key, ci);
+ Delete(ci);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_features_get()
+ *
+ * Attaches any features in the features hash to the node that matches
+ * the declaration, decl.
+ * ----------------------------------------------------------------------------- */
+
+static void features_get(Hash *features, const String *tname, SwigType *decl, SwigType *ncdecl, Node *node) {
+ Node *n = Getattr(features, tname);
+#ifdef SWIG_DEBUG
+ Printf(stdout, " features_get: %s\n", tname);
+#endif
+ if (n) {
+ merge_features(get_object(n, 0), node);
+ if (ncdecl)
+ merge_features(get_object(n, ncdecl), node);
+ merge_features(get_object(n, decl), node);
+ }
+}
+
+void Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl, Node *node) {
+ char *ncdecl = 0;
+ String *rdecl = 0;
+ String *rname = 0;
+ if (!features)
+ return;
+
+ /* MM: This removed to more tightly control feature/name matching */
+ /*
+ if ((decl) && (SwigType_isqualifier(decl))) {
+ ncdecl = strchr(Char(decl),'.');
+ ncdecl++;
+ }
+ */
+
+ /* very specific hack for template constructors/destructors */
+ if (name && SwigType_istemplate(name)) {
+ String *nodetype = nodeType(node);
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ Delete(nlast);
+ if (Len(nprefix)) {
+ Append(nprefix, "::");
+ Append(nprefix, tprefix);
+ Delete(tprefix);
+ rname = nprefix;
+ } else {
+ rname = tprefix;
+ Delete(nprefix);
+ }
+ rdecl = Copy(decl);
+ Replaceall(rdecl, name, rname);
+ decl = rdecl;
+ name = rname;
+ }
+ }
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_features_get: '%s' '%s' '%s'\n", prefix, name, decl);
+#endif
+
+ /* Global features */
+ features_get(features, "", 0, 0, node);
+ if (name) {
+ String *tname = NewStringEmpty();
+ /* add features for 'root' template */
+ String *dname = SwigType_istemplate_templateprefix(name);
+ if (dname) {
+ features_get(features, dname, decl, ncdecl, node);
+ }
+ /* Catch-all */
+ features_get(features, name, decl, ncdecl, node);
+ /* Perform a class-based lookup (if class prefix supplied) */
+ if (prefix) {
+ /* A class-generic feature */
+ if (Len(prefix)) {
+ Printf(tname, "%s::", prefix);
+ features_get(features, tname, decl, ncdecl, node);
+ }
+ /* A wildcard-based class lookup */
+ Clear(tname);
+ Printf(tname, "*::%s", name);
+ features_get(features, tname, decl, ncdecl, node);
+ /* A specific class lookup */
+ if (Len(prefix)) {
+ /* A template-based class lookup */
+ String *tprefix = SwigType_istemplate_templateprefix(prefix);
+ if (tprefix) {
+ Clear(tname);
+ Printf(tname, "%s::%s", tprefix, name);
+ features_get(features, tname, decl, ncdecl, node);
+ }
+ Clear(tname);
+ Printf(tname, "%s::%s", prefix, name);
+ features_get(features, tname, decl, ncdecl, node);
+ Delete(tprefix);
+ }
+ } else {
+ /* Lookup in the global namespace only */
+ Clear(tname);
+ Printf(tname, "::%s", name);
+ features_get(features, tname, decl, ncdecl, node);
+ }
+ Delete(tname);
+ Delete(dname);
+ }
+ if (name && SwigType_istemplate(name)) {
+ /* add features for complete template type */
+ String *dname = Swig_symbol_template_deftype(name, 0);
+ if (!Equal(dname, name)) {
+ Swig_features_get(features, prefix, dname, decl, node);
+ }
+ Delete(dname);
+ }
+
+ if (rname)
+ Delete(rname);
+ if (rdecl)
+ Delete(rdecl);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_feature_set()
+ *
+ * Sets a feature name and value. Also sets optional feature attributes as
+ * passed in by featureattribs. Optional feature attributes are given a full name
+ * 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, const_String_or_char_ptr value, Hash *featureattribs) {
+ Hash *n;
+ Hash *fhash;
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_feature_set: '%s' '%s' '%s' '%s'\n", name, decl, featurename, value);
+#endif
+
+ n = Getattr(features, name);
+ if (!n) {
+ n = NewHash();
+ Setattr(features, name, n);
+ Delete(n);
+ }
+ if (!decl) {
+ fhash = Getattr(n, "start");
+ if (!fhash) {
+ fhash = NewHash();
+ Setattr(n, "start", fhash);
+ Delete(fhash);
+ }
+ } else {
+ fhash = Getattr(n, decl);
+ if (!fhash) {
+ String *cdecl_ = Copy(decl);
+ fhash = NewHash();
+ Setattr(n, cdecl_, fhash);
+ Delete(cdecl_);
+ Delete(fhash);
+ }
+ }
+ if (value) {
+ Setattr(fhash, featurename, value);
+ } else {
+ Delattr(fhash, featurename);
+ }
+
+ {
+ /* Add in the optional feature attributes */
+ Hash *attribs = featureattribs;
+ while (attribs) {
+ String *attribname = Getattr(attribs, "name");
+ String *featureattribname = NewStringf("%s:%s", featurename, attribname);
+ if (value) {
+ String *attribvalue = Getattr(attribs, "value");
+ Setattr(fhash, featureattribname, attribvalue);
+ } else {
+ Delattr(fhash, featureattribname);
+ }
+ attribs = nextSibling(attribs);
+ Delete(featureattribname);
+ }
+ }
+
+ if (name && SwigType_istemplate(name)) {
+ String *dname = Swig_symbol_template_deftype(name, 0);
+ if (Strcmp(dname, name)) {
+ Swig_feature_set(features, dname, decl, featurename, value, featureattribs);
+ }
+ Delete(dname);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * The rename/namewarn engine
+ *
+ * Code below was in parser.y for a while
+ * ----------------------------------------------------------------------------- */
+
+static Hash *namewarn_hash = 0;
+static Hash *name_namewarn_hash(void) {
+ if (!namewarn_hash)
+ namewarn_hash = NewHash();
+ return namewarn_hash;
+}
+
+static Hash *rename_hash = 0;
+static Hash *name_rename_hash(void) {
+ if (!rename_hash)
+ rename_hash = NewHash();
+ return rename_hash;
+}
+
+static List *namewarn_list = 0;
+static List *name_namewarn_list(void) {
+ if (!namewarn_list)
+ namewarn_list = NewList();
+ return namewarn_list;
+}
+
+static List *rename_list = 0;
+static List *name_rename_list(void) {
+ if (!rename_list)
+ rename_list = NewList();
+ return rename_list;
+}
+
+/* -----------------------------------------------------------------------------
+ * int need_name_warning(Node *n)
+ *
+ * Detects if a node needs name warnings
+ *
+ * ----------------------------------------------------------------------------- */
+
+static int need_name_warning(Node *n) {
+ int need = 1;
+ /*
+ We don't use name warnings for:
+ - class forwards, no symbol is generated at the target language.
+ - template declarations, only for real instances using %template(name).
+ - typedefs, have no effect at the target language.
+ - using declarations and using directives, have no effect at the target language.
+ */
+ if (checkAttribute(n, "nodeType", "classforward")) {
+ need = 0;
+ } else if (checkAttribute(n, "nodeType", "using")) {
+ need = 0;
+ } else if (checkAttribute(n, "storage", "typedef")) {
+ need = 0;
+ } else if (Getattr(n, "hidden")) {
+ need = 0;
+ } else if (Getattr(n, "ignore")) {
+ need = 0;
+ } else if (Getattr(n, "templatetype")) {
+ need = 0;
+ } else if (GetFlag(n, "parsing_template_declaration")) {
+ need = 0;
+ }
+ return need;
+}
+
+/* -----------------------------------------------------------------------------
+ * int Swig_need_redefined_warn()
+ *
+ * Detects when a redefined object needs a warning
+ *
+ * ----------------------------------------------------------------------------- */
+
+static int nodes_are_equivalent(Node *a, Node *b, int a_inclass) {
+ /* they must have the same type */
+ String *ta = nodeType(a);
+ String *tb = nodeType(b);
+ if (!Equal(ta, tb)) {
+ if (!(Equal(ta, "using") && Equal(tb, "cdecl"))) {
+ return 0;
+ }
+ }
+
+ if (Equal(ta, "cdecl") || Equal(ta, "constructor")) {
+ /* both cdecl or constructor case */
+ /* typedef */
+ String *a_storage = Getattr(a, "storage");
+ String *b_storage = Getattr(b, "storage");
+
+ if ((Cmp(a_storage, "typedef") == 0)
+ || (Cmp(b_storage, "typedef") == 0)) {
+ if (Cmp(a_storage, b_storage) == 0) {
+ String *a_type = (Getattr(a, "type"));
+ String *b_type = (Getattr(b, "type"));
+ if (Cmp(a_type, b_type) == 0)
+ return 1;
+ }
+ return 0;
+ }
+
+ /* static functions */
+ if (Swig_storage_isstatic(a) || Swig_storage_isstatic(b)) {
+ if (Cmp(a_storage, b_storage) != 0)
+ return 0;
+ }
+
+ /* friend methods */
+
+ if (!a_inclass || Strstr(a_storage, "friend")) {
+ /* check declaration */
+
+ String *a_decl = (Getattr(a, "decl"));
+ String *b_decl = (Getattr(b, "decl"));
+ if (Cmp(a_decl, b_decl) == 0) {
+ /* check return type */
+ String *a_type = (Getattr(a, "type"));
+ String *b_type = (Getattr(b, "type"));
+ if (Cmp(a_type, b_type) == 0) {
+ /* check parameters */
+ Parm *ap = (Getattr(a, "parms"));
+ Parm *bp = (Getattr(b, "parms"));
+ while (ap && bp) {
+ SwigType *at = Getattr(ap, "type");
+ SwigType *bt = Getattr(bp, "type");
+ if (Cmp(at, bt) != 0)
+ return 0;
+ ap = nextSibling(ap);
+ bp = nextSibling(bp);
+ }
+ if (ap || bp) {
+ return 0;
+ } else {
+ Node *a_template = Getattr(a, "template");
+ Node *b_template = Getattr(b, "template");
+ /* Not equivalent if one is a template instantiation (via %template) and the other is a non-templated function */
+ if ((a_template && !b_template) || (!a_template && b_template))
+ return 0;
+ }
+ return 1;
+ }
+ }
+ }
+ } else if (Equal(ta, "using")) {
+ /* using and cdecl case */
+ String *b_storage = Getattr(b, "storage");
+ if (Equal(b_storage, "typedef")) {
+ String *a_name = Getattr(a, "name");
+ String *b_name = Getattr(b, "name");
+ if (Equal(a_name, b_name))
+ return 1;
+ }
+ } else {
+ /* both %constant case */
+ String *a_storage = Getattr(a, "storage");
+ String *b_storage = Getattr(b, "storage");
+ if ((Cmp(a_storage, "%constant") == 0)
+ || (Cmp(b_storage, "%constant") == 0)) {
+ if (Cmp(a_storage, b_storage) == 0) {
+ String *a_type = (Getattr(a, "type"));
+ String *b_type = (Getattr(b, "type"));
+ if ((Cmp(a_type, b_type) == 0)
+ && (Cmp(Getattr(a, "value"), Getattr(b, "value")) == 0))
+ return 1;
+ }
+ return 0;
+ }
+ if (Equal(ta, "template") && Equal(tb, "template")) {
+ if (Strstr(a_storage, "friend") || Strstr(b_storage, "friend"))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int Swig_need_redefined_warn(Node *a, Node *b, int InClass) {
+ String *a_name = Getattr(a, "name");
+ String *b_name = Getattr(b, "name");
+ String *a_symname = Getattr(a, "sym:name");
+ String *b_symname = Getattr(b, "sym:name");
+ /* always send a warning if a 'rename' is involved */
+ if ((a_symname && !Equal(a_symname, a_name))
+ || (b_symname && !Equal(b_symname, b_name))) {
+ if (!Equal(a_name, b_name)) {
+ return 1;
+ }
+ }
+
+
+ return !nodes_are_equivalent(a, b, InClass);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * int Swig_need_protected(Node* n)
+ *
+ * Detects when we need to fully register the protected member.
+ * This is basically any protected members when the allprotected mode is set.
+ * Otherwise we take just the protected virtual methods and non-static methods
+ * (potentially virtual methods) as well as constructors/destructors.
+ * Also any "using" statements in a class may potentially be virtual.
+ * ----------------------------------------------------------------------------- */
+
+int Swig_need_protected(Node *n) {
+ String *nodetype = nodeType(n);
+ if (checkAttribute(n, "access", "protected")) {
+ if ((Equal(nodetype, "cdecl"))) {
+ if (Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode()) {
+ return 1;
+ }
+ if (SwigType_isfunction(Getattr(n, "decl"))) {
+ String *storage = Getattr(n, "storage");
+ /* The function is declared virtual, or it has no storage. This eliminates typedef, static etc. */
+ return !storage || Equal(storage, "virtual");
+ }
+ } else if (Equal(nodetype, "constructor") || Equal(nodetype, "destructor")) {
+ return 1;
+ } else if (Equal(nodetype, "using") && !Getattr(n, "namespace")) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * void name_nameobj_add()
+ *
+ * Add nameobj (rename/namewarn)
+ *
+ * ----------------------------------------------------------------------------- */
+
+static List *make_attrlist(const char *ckey) {
+ List *list = NewList();
+ const char *cattr = strchr(ckey, '$');
+ if (cattr) {
+ String *nattr;
+ const char *rattr = strchr(++cattr, '$');
+ while (rattr) {
+ nattr = NewStringWithSize(cattr, (int)(rattr - cattr));
+ Append(list, nattr);
+ Delete(nattr);
+ cattr = rattr + 1;
+ rattr = strchr(cattr, '$');
+ }
+ nattr = NewString(cattr);
+ Append(list, nattr);
+ Delete(nattr);
+ } else {
+ Append(list, "nodeType");
+ }
+ return list;
+}
+
+static void name_object_attach_keys(const char *keys[], Hash *nameobj) {
+ Node *kw = nextSibling(nameobj);
+ List *matchlist = 0;
+ while (kw) {
+ Node *next = nextSibling(kw);
+ String *kname = Getattr(kw, "name");
+ char *ckey = kname ? Char(kname) : 0;
+ if (ckey) {
+ const char **rkey;
+ int isnotmatch = 0;
+ int isregexmatch = 0;
+ if ((strncmp(ckey, "match", 5) == 0)
+ || (isnotmatch = (strncmp(ckey, "notmatch", 8) == 0))
+ || (isregexmatch = (strncmp(ckey, "regexmatch", 10) == 0))
+ || (isnotmatch = isregexmatch = (strncmp(ckey, "notregexmatch", 13) == 0))) {
+ Hash *mi = NewHash();
+ List *attrlist = make_attrlist(ckey);
+ if (!matchlist)
+ matchlist = NewList();
+ Setattr(mi, "value", Getattr(kw, "value"));
+ Setattr(mi, "attrlist", attrlist);
+ if (isnotmatch)
+ SetFlag(mi, "notmatch");
+ if (isregexmatch)
+ SetFlag(mi, "regexmatch");
+ Delete(attrlist);
+ Append(matchlist, mi);
+ Delete(mi);
+ removeNode(kw);
+ } else {
+ for (rkey = keys; *rkey != 0; ++rkey) {
+ if (strcmp(ckey, *rkey) == 0) {
+ Setattr(nameobj, *rkey, Getattr(kw, "value"));
+ removeNode(kw);
+ }
+ }
+ }
+ }
+ kw = next;
+ }
+ if (matchlist) {
+ Setattr(nameobj, "matchlist", matchlist);
+ Delete(matchlist);
+ }
+}
+
+static void name_nameobj_add(Hash *name_hash, List *name_list, String *prefix, String *name, SwigType *decl, Hash *nameobj) {
+ String *nname = 0;
+ if (name && Len(name)) {
+ String *target_fmt = Getattr(nameobj, "targetfmt");
+ nname = prefix ? NewStringf("%s::%s", prefix, name) : NewString(name);
+ if (target_fmt) {
+ String *tmp = NewStringf(target_fmt, nname);
+ Delete(nname);
+ nname = tmp;
+ }
+ }
+
+ if (!nname || !Len(nname) || Getattr(nameobj, "fullname") || /* any of these options trigger a 'list' nameobj */
+ Getattr(nameobj, "sourcefmt") || Getattr(nameobj, "matchlist") || Getattr(nameobj, "regextarget")) {
+ if (decl)
+ Setattr(nameobj, "decl", decl);
+ if (nname && Len(nname))
+ Setattr(nameobj, "targetname", nname);
+ /* put the new nameobj at the beginning of the list, such that the
+ last inserted rule take precedence */
+ Insert(name_list, 0, nameobj);
+ } else {
+ /* here we add an old 'hash' nameobj, simple and fast */
+ Swig_name_object_set(name_hash, nname, decl, nameobj);
+ }
+ Delete(nname);
+}
+
+/* -----------------------------------------------------------------------------
+ * int name_match_nameobj()
+ *
+ * Apply and check the nameobj's math list to the node
+ *
+ * ----------------------------------------------------------------------------- */
+
+static DOH *get_lattr(Node *n, List *lattr) {
+ DOH *res = 0;
+ int ilen = Len(lattr);
+ int i;
+ for (i = 0; n && (i < ilen); ++i) {
+ String *nattr = Getitem(lattr, i);
+ res = Getattr(n, nattr);
+#ifdef SWIG_DEBUG
+ if (!res) {
+ Printf(stdout, "missing %s %s %s\n", nattr, Getattr(n, "name"), Getattr(n, "member"));
+ } else {
+ Printf(stdout, "lattr %d %s %s\n", i, nattr, DohIsString(res) ? res : Getattr(res, "name"));
+ }
+#endif
+ n = res;
+ }
+ return res;
+}
+
+#ifdef HAVE_PCRE
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
+static int name_regexmatch_value(Node *n, String *pattern, String *s) {
+ pcre2_code *compiled_pat;
+ PCRE2_UCHAR err[256];
+ int errornum;
+ size_t errpos;
+ int rc;
+ pcre2_match_data *match_data = 0;
+
+ compiled_pat = pcre2_compile((PCRE2_SPTR8)Char(pattern), PCRE2_ZERO_TERMINATED, 0, &errornum, &errpos, NULL);
+ if (!compiled_pat) {
+ pcre2_get_error_message (errornum, err, sizeof err);
+ Swig_error("SWIG", Getline(n),
+ "Invalid regex \"%s\": compilation failed at %d: %s\n",
+ Char(pattern), errpos, err);
+ Exit(EXIT_FAILURE);
+ }
+
+ match_data = pcre2_match_data_create_from_pattern (compiled_pat, NULL);
+ rc = pcre2_match(compiled_pat, (PCRE2_SPTR8)Char(s), PCRE2_ZERO_TERMINATED, 0, 0, match_data, 0);
+ pcre2_code_free(compiled_pat);
+ pcre2_match_data_free(match_data);
+
+ if (rc == PCRE2_ERROR_NOMATCH)
+ return 0;
+
+ if (rc < 0 ) {
+ Swig_error("SWIG", Getline(n),
+ "Matching \"%s\" against regex \"%s\" failed: %d\n",
+ Char(s), Char(pattern), rc);
+ Exit(EXIT_FAILURE);
+ }
+
+ return 1;
+}
+
+#else /* !HAVE_PCRE */
+
+static int name_regexmatch_value(Node *n, String *pattern, String *s) {
+ (void)pattern;
+ (void)s;
+ Swig_error("SWIG", Getline(n),
+ "PCRE regex matching is not available in this SWIG build.\n");
+ Exit(EXIT_FAILURE);
+ return 0;
+}
+
+#endif /* HAVE_PCRE/!HAVE_PCRE */
+
+static int name_match_value(String *mvalue, String *value) {
+#if defined(SWIG_USE_SIMPLE_MATCHOR)
+ int match = 0;
+ char *cvalue = Char(value);
+ char *cmvalue = Char(mvalue);
+ char *sep = strchr(cmvalue, '|');
+ while (sep && !match) {
+ match = strncmp(cvalue, cmvalue, sep - cmvalue) == 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match);
+#endif
+ cmvalue = sep + 1;
+ sep = strchr(cmvalue, '|');
+ }
+ if (!match) {
+ match = strcmp(cvalue, cmvalue) == 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "match_value: %s %s %d\n", cvalue, cmvalue, match);
+#endif
+ }
+ return match;
+#else
+ return Equal(mvalue, value);
+#endif
+}
+
+static int name_match_nameobj(Hash *rn, Node *n) {
+ int match = 1;
+ List *matchlist = Getattr(rn, "matchlist");
+#ifdef SWIG_DEBUG
+ Printf(stdout, "name_match_nameobj: %s\n", Getattr(n, "name"));
+#endif
+ if (matchlist) {
+ int ilen = Len(matchlist);
+ int i;
+ for (i = 0; match && (i < ilen); ++i) {
+ Node *mi = Getitem(matchlist, i);
+ List *lattr = Getattr(mi, "attrlist");
+ String *nval = get_lattr(n, lattr);
+ int notmatch = GetFlag(mi, "notmatch");
+ int regexmatch = GetFlag(mi, "regexmatch");
+ match = 0;
+ if (nval) {
+ String *kwval = Getattr(mi, "value");
+ match = regexmatch ? name_regexmatch_value(n, kwval, nval)
+ : name_match_value(kwval, nval);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen);
+#endif
+ }
+ if (notmatch)
+ match = !match;
+ }
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "name_match_nameobj: %d\n", match);
+#endif
+ return match;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash *name_nameobj_lget()
+ *
+ * Get a nameobj (rename/namewarn) from the list of filters
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *name_nameobj_lget(List *namelist, Node *n, String *prefix, String *name, String *decl) {
+ Hash *res = 0;
+ if (namelist) {
+ int len = Len(namelist);
+ int i;
+ int match = 0;
+ for (i = 0; !match && (i < len); i++) {
+ Hash *rn = Getitem(namelist, i);
+ String *rdecl = Getattr(rn, "decl");
+ if (rdecl && (!decl || !Equal(rdecl, decl))) {
+ continue;
+ } else if (name_match_nameobj(rn, n)) {
+ String *tname = Getattr(rn, "targetname");
+ if (tname) {
+ String *sfmt = Getattr(rn, "sourcefmt");
+ String *sname = 0;
+ int fullname = GetFlag(rn, "fullname");
+ int regextarget = GetFlag(rn, "regextarget");
+ if (sfmt) {
+ if (fullname && prefix) {
+ String *pname = NewStringf("%s::%s", prefix, name);
+ sname = NewStringf(sfmt, pname);
+ Delete(pname);
+ } else {
+ sname = NewStringf(sfmt, name);
+ }
+ } else {
+ if (fullname && prefix) {
+ sname = NewStringf("%s::%s", prefix, name);
+ } else {
+ sname = name;
+ DohIncref(name);
+ }
+ }
+ match = regextarget ? name_regexmatch_value(n, tname, sname)
+ : name_match_value(tname, sname);
+ Delete(sname);
+ } else {
+ /* Applying the renaming rule may fail if it contains a %(regex)s expression that doesn't match the given name. */
+ String *sname = NewStringf(Getattr(rn, "name"), name);
+ if (sname) {
+ if (Len(sname))
+ match = 1;
+ Delete(sname);
+ }
+ }
+ }
+ if (match) {
+ res = rn;
+ break;
+ }
+ }
+ }
+ return res;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_namewarn_add
+ *
+ * Add a namewarn objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn) {
+ const char *namewrn_keys[] = { "rename", "error", "fullname", "sourcefmt", "targetfmt", 0 };
+ name_object_attach_keys(namewrn_keys, namewrn);
+ name_nameobj_add(name_namewarn_hash(), name_namewarn_list(), prefix, name, decl, namewrn);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hash *name_namewarn_get()
+ *
+ * Return the namewarn object, if there is one.
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *name_namewarn_get(Node *n, String *prefix, String *name, SwigType *decl) {
+ if (!namewarn_hash && !namewarn_list)
+ return 0;
+ if (n) {
+ /* Return in the obvious cases */
+ if (!name || !need_name_warning(n)) {
+ return 0;
+ } else {
+ String *access = Getattr(n, "access");
+ int is_public = !access || Equal(access, "public");
+ if (!is_public && !Swig_need_protected(n)) {
+ return 0;
+ }
+ }
+ }
+ if (name) {
+ /* Check to see if the name is in the hash */
+ Hash *wrn = Swig_name_object_get(name_namewarn_hash(), prefix, name, decl);
+ if (wrn && !name_match_nameobj(wrn, n))
+ wrn = 0;
+ if (!wrn) {
+ wrn = name_nameobj_lget(name_namewarn_list(), n, prefix, name, decl);
+ }
+ if (wrn && Getattr(wrn, "error")) {
+ if (n) {
+ Swig_error(Getfile(n), Getline(n), "%s\n", Getattr(wrn, "name"));
+ } else {
+ Swig_error(cparse_file, cparse_line, "%s\n", Getattr(wrn, "name"));
+ }
+ }
+ return wrn;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * String *Swig_name_warning()
+ *
+ * Return the name warning, if there is one.
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_warning(Node *n, String *prefix, String *name, SwigType *decl) {
+ Hash *wrn = name_namewarn_get(n, prefix, name, decl);
+ return (name && wrn) ? Getattr(wrn, "name") : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_name_rename_add()
+ *
+ * Manage the rename objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+static void single_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname) {
+ name_nameobj_add(name_rename_hash(), name_rename_list(), prefix, name, decl, newname);
+}
+
+/* Add a new rename. Works much like new_feature including default argument handling. */
+void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *newname, ParmList *declaratorparms) {
+
+ ParmList *declparms = declaratorparms;
+
+ const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "regextarget", 0 };
+ name_object_attach_keys(rename_keys, newname);
+
+ /* Add the name */
+ single_rename_add(prefix, name, decl, newname);
+
+ /* Add extra names if there are default parameters in the parameter list */
+ if (decl) {
+ int constqualifier = SwigType_isconst(decl);
+ while (declparms) {
+ if (ParmList_has_defaultargs(declparms)) {
+
+ /* Create a parameter list for the new rename by copying all
+ but the last (defaulted) parameter */
+ ParmList *newparms = CopyParmListMax(declparms,ParmList_len(declparms)-1);
+
+ /* Create new declaration - with the last parameter removed */
+ SwigType *newdecl = Copy(decl);
+ Delete(SwigType_pop_function(newdecl)); /* remove the old parameter list from newdecl */
+ SwigType_add_function(newdecl, newparms);
+ if (constqualifier)
+ SwigType_add_qualifier(newdecl, "const");
+
+ single_rename_add(prefix, name, newdecl, newname);
+ declparms = newparms;
+ Delete(newdecl);
+ } else {
+ declparms = 0;
+ }
+ }
+ }
+}
+
+
+/* Create a name for the given node applying rename/namewarn if needed */
+static String *apply_rename(Node* n, String *newname, int fullname, String *prefix, String *name) {
+ String *result = 0;
+ if (newname && Len(newname)) {
+ if (Strcmp(newname, "$ignore") == 0) {
+ /* $ignore doesn't apply to parameters and while it's rare to explicitly write %ignore directives for them they could be caught by a wildcard ignore using
+ regex match, just ignore the attempt to ignore them in this case */
+ if (!Equal(nodeType(n), "parm"))
+ result = Copy(newname);
+ } else {
+ char *cnewname = Char(newname);
+ if (cnewname) {
+ int destructor = name && (*(Char(name)) == '~');
+ String *fmt = newname;
+ /* use name as a fmt, but avoid C++ "%" and "%=" operators */
+ if (Len(newname) > 1 && strchr(cnewname, '%') && !(strcmp(cnewname, "%=") == 0)) {
+ if (fullname && prefix) {
+ result = NewStringf(fmt, prefix, name);
+ } else {
+ result = NewStringf(fmt, name);
+ }
+ } else {
+ result = Copy(newname);
+ }
+ if (destructor && result && (*(Char(result)) != '~')) {
+ Insert(result, 0, "~");
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * String *Swig_name_make()
+ *
+ * Make a name after applying all the rename/namewarn objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, SwigType *decl, String *oldname) {
+ String *nname = 0;
+ String *result = 0;
+ String *name = NewString(cname);
+ Hash *wrn = 0;
+ String *rdecl = 0;
+ String *rname = 0;
+
+ /* very specific hack for template constructors/destructors */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_make: looking for %s %s %s %s\n", prefix, name, decl, oldname);
+#endif
+
+ if (name && n && SwigType_istemplate(name)) {
+ String *nodetype = nodeType(n);
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ Delete(nlast);
+ if (Len(nprefix)) {
+ Append(nprefix, "::");
+ Append(nprefix, tprefix);
+ Delete(tprefix);
+ rname = nprefix;
+ } else {
+ rname = tprefix;
+ Delete(nprefix);
+ }
+ rdecl = Copy(decl);
+ Replaceall(rdecl, name, rname);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "SWIG_name_make: use new name %s %s : %s %s\n", name, decl, rname, rdecl);
+#endif
+ decl = rdecl;
+ Delete(name);
+ name = rname;
+ }
+ }
+
+ if (rename_hash || rename_list || namewarn_hash || namewarn_list) {
+ Hash *rn = Swig_name_object_get(name_rename_hash(), prefix, name, decl);
+ if (!rn || !name_match_nameobj(rn, n)) {
+ rn = name_nameobj_lget(name_rename_list(), n, prefix, name, decl);
+ if (rn) {
+ String *sfmt = Getattr(rn, "sourcefmt");
+ int fullname = GetFlag(rn, "fullname");
+ if (fullname && prefix) {
+ String *sname = NewStringf("%s::%s", prefix, name);
+ Delete(name);
+ name = sname;
+ prefix = 0;
+ }
+ if (sfmt) {
+ String *sname = NewStringf(sfmt, name);
+ Delete(name);
+ name = sname;
+ }
+ }
+ }
+ if (rn) {
+ String *newname = Getattr(rn, "name");
+ int fullname = GetFlag(rn, "fullname");
+ result = apply_rename(n, newname, fullname, prefix, name);
+ }
+ if (result && !Equal(result, name)) {
+ /* operators in C++ allow aliases, we look for them */
+ char *cresult = Char(result);
+ if (cresult && (strncmp(cresult, "operator ", 9) == 0)) {
+ String *nresult = Swig_name_make(n, prefix, result, decl, oldname);
+ if (!Equal(nresult, result)) {
+ Delete(result);
+ result = nresult;
+ } else {
+ Delete(nresult);
+ }
+ }
+ }
+ nname = result ? result : name;
+ wrn = name_namewarn_get(n, prefix, nname, decl);
+ if (wrn) {
+ String *rename = Getattr(wrn, "rename");
+ if (rename) {
+ String *msg = Getattr(wrn, "name");
+ int fullname = GetFlag(wrn, "fullname");
+ if (result)
+ Delete(result);
+ result = apply_rename(n, rename, fullname, prefix, name);
+ if ((msg) && (Len(msg))) {
+ if (!Getmeta(nname, "already_warned")) {
+ String* suffix = 0;
+ if (Strcmp(result, "$ignore") == 0) {
+ suffix = NewStringf(": ignoring '%s'\n", name);
+ } else if (Strcmp(result, name) != 0) {
+ suffix = NewStringf(", renaming to '%s'\n", result);
+ } else {
+ /* No rename was performed */
+ suffix = NewString("\n");
+ }
+ if (n) {
+ /* Parameter renaming is not fully implemented. Mainly because there is no C/C++ syntax to
+ * for %rename to fully qualify a function's parameter name from outside the function. Hence it
+ * is not possible to implemented targeted warning suppression on one parameter in one function. */
+ int suppress_parameter_rename_warning = Equal(nodeType(n), "parm");
+ if (!suppress_parameter_rename_warning) {
+ SWIG_WARN_NODE_BEGIN(n);
+ Swig_warning(0, Getfile(n), Getline(n), "%s%s", msg, suffix);
+ SWIG_WARN_NODE_END(n);
+ }
+ } else {
+ Swig_warning(0, Getfile(name), Getline(name), "%s%s", msg, suffix);
+ }
+ Setmeta(nname, "already_warned", "1");
+ Delete(suffix);
+ }
+ }
+ }
+ }
+ }
+ if (!result || !Len(result)) {
+ if (result)
+ Delete(result);
+ if (oldname) {
+ result = NewString(oldname);
+ } else {
+ result = NewString(cname);
+ }
+ }
+ Delete(name);
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_name_make: result '%s' '%s'\n", cname, result);
+#endif
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_inherit()
+ *
+ * Inherit namewarn, rename, and feature objects
+ *
+ * ----------------------------------------------------------------------------- */
+
+void Swig_name_inherit(String *base, String *derived) {
+ /* Printf(stdout,"base = '%s', derived = '%s'\n", base, derived); */
+ Swig_name_object_inherit(name_rename_hash(), base, derived);
+ Swig_name_object_inherit(name_namewarn_hash(), base, derived);
+ Swig_name_object_inherit(Swig_cparse_features(), base, 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.
+ * The node passed in is expected to be a function, constructor, destructor or
+ * variable. Some example return values:
+ * "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate"
+ * "MyNameSpace::ABC::ABC"
+ * "MyNameSpace::ABC::constmethod"
+ * "MyNameSpace::ABC::variablename"
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_str(Node *n) {
+ String *qname;
+ String *qualifier = Swig_symbol_qualified(n);
+ String *name = Swig_scopename_last(Getattr(n, "name"));
+ if (qualifier)
+ qualifier = SwigType_namestr(qualifier);
+
+ /* Very specific hack for template constructors/destructors */
+ if (SwigType_istemplate(name)) {
+ String *nodetype = nodeType(n);
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ String *nprefix = 0;
+ String *nlast = 0;
+ String *tprefix;
+ Swig_scopename_split(name, &nprefix, &nlast);
+ tprefix = SwigType_templateprefix(nlast);
+ Delete(nlast);
+ Delete(nprefix);
+ Delete(name);
+ name = tprefix;
+ }
+ }
+
+ qname = NewString("");
+ if (qualifier && Len(qualifier) > 0)
+ Printf(qname, "%s::", qualifier);
+ Printf(qname, "%s", SwigType_str(name, 0));
+
+ Delete(name);
+ Delete(qualifier);
+
+ return qname;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_decl()
+ *
+ * Return a stringified version of a C/C++ declaration without the return type.
+ * The node passed in is usually a function, constructor, destructor.
+ * Other nodes result in a simple fully qualified string of the symbol.
+ * Some example return values:
+ * "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate()"
+ * "MyNameSpace::ABC::ABC(int,double)"
+ * "MyNameSpace::ABC::constmethod(int) const"
+ * "MyNameSpace::ABC::refqualifiermethod(int) const &"
+ * "MyNameSpace::ABC::variablename"
+ * "MyNameSpace::ABC::MyClass"
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_decl(Node *n) {
+ String *qname;
+ String *decl;
+ String *nodetype = nodeType(n);
+
+ qname = Swig_name_str(n);
+ decl = NewStringf("%s", qname);
+
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor") || Equal(nodetype, "cdecl"))) {
+ String *d = Getattr(n, "decl");
+ if (SwigType_isfunction(d)) {
+ SwigType *decl_temp = Copy(d);
+ SwigType *qualifiers = SwigType_pop_function_qualifiers(decl_temp);
+ Printv(decl, "(", ParmList_errorstr(Getattr(n, "parms")), ")", NIL);
+ if (qualifiers) {
+ String *qualifiers_string = SwigType_str(qualifiers, 0);
+ Printv(decl, " ", qualifiers_string, NIL);
+ Delete(qualifiers_string);
+ }
+ Delete(decl_temp);
+ }
+ }
+
+ Delete(qname);
+
+ return decl;
+}
+
+/* -----------------------------------------------------------------------------
+ * void Swig_name_fulldecl()
+ *
+ * Return a stringified version of a C/C++ declaration including the return type.
+ * The node passed in is expected to be a function, constructor or destructor.
+ * Some example return values:
+ * "MyNameSpace::MyTemplate<MyNameSpace::ABC >::~MyTemplate()"
+ * "MyNameSpace::ABC::ABC(int,double)"
+ * "int * MyNameSpace::ABC::constmethod(int) const"
+ *
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_name_fulldecl(Node *n) {
+ String *decl = Swig_name_decl(n);
+ String *type = Getattr(n, "type");
+ String *nodetype = nodeType(n);
+ String *fulldecl;
+ /* add on the return type */
+ if (nodetype && (Equal(nodetype, "constructor") || Equal(nodetype, "destructor"))) {
+ fulldecl = decl;
+ } else {
+ String *t = SwigType_str(type, 0);
+ fulldecl = NewStringf("%s %s", t, decl);
+ Delete(decl);
+ Delete(t);
+ }
+ return fulldecl;
+}
+
diff --git a/contrib/tools/swig/Source/Swig/parms.c b/contrib/tools/swig/Source/Swig/parms.c
new file mode 100644
index 00000000000..c1dffb57286
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/parms.c
@@ -0,0 +1,350 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * parms.c
+ *
+ * Parameter list class.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+
+/* ------------------------------------------------------------------------
+ * NewParm()
+ *
+ * Create a new parameter from datatype 'type' and name 'name' copying
+ * the file and line number from the Node from_node.
+ * ------------------------------------------------------------------------ */
+
+Parm *NewParm(SwigType *type, const_String_or_char_ptr name, Node *from_node) {
+ Parm *p = NewParmWithoutFileLineInfo(type, name);
+ Setfile(p, Getfile(from_node));
+ Setline(p, Getline(from_node));
+ return p;
+}
+
+/* ------------------------------------------------------------------------
+ * NewParmWithoutFileLineInfo()
+ *
+ * Create a new parameter from datatype 'type' and name 'name' without any
+ * file / line numbering information.
+ * ------------------------------------------------------------------------ */
+
+Parm *NewParmWithoutFileLineInfo(SwigType *type, const_String_or_char_ptr name) {
+ Parm *p = NewHash();
+ set_nodeType(p, "parm");
+ if (type) {
+ SwigType *ntype = Copy(type);
+ Setattr(p, "type", ntype);
+ Delete(ntype);
+ }
+ Setattr(p, "name", name);
+ return p;
+}
+
+/* ------------------------------------------------------------------------
+ * NewParmNode()
+ *
+ * Create a new parameter from datatype 'type' and name and symbol table as
+ * well as file and line number from the 'from_node'.
+ * The resulting Parm will be similar to a Node used for typemap lookups.
+ * ------------------------------------------------------------------------ */
+
+Parm *NewParmNode(SwigType *type, Node *from_node) {
+ Parm *p = NewParm(type, Getattr(from_node, "name"), from_node);
+ Setattr(p, "sym:symtab", Getattr(from_node, "sym:symtab"));
+ return p;
+}
+
+/* ------------------------------------------------------------------------
+ * CopyParm()
+ * ------------------------------------------------------------------------ */
+
+Parm *CopyParm(Parm *p) {
+ Parm *np = NewHash();
+ Iterator ki;
+ for (ki = First(p); ki.key; ki = Next(ki)) {
+ if (DohIsString(ki.item)) {
+ DOH *c = Copy(ki.item);
+ Setattr(np,ki.key,c);
+ Delete(c);
+ }
+ }
+ Setfile(np, Getfile(p));
+ Setline(np, Getline(p));
+ return np;
+}
+
+/* ------------------------------------------------------------------
+ * CopyParmListMax()
+ * CopyParmList()
+ * ------------------------------------------------------------------ */
+
+ParmList *CopyParmListMax(ParmList *p, int count) {
+ Parm *np;
+ Parm *pp = 0;
+ Parm *fp = 0;
+
+ if (!p)
+ return 0;
+
+ while (p) {
+ if (count == 0) break;
+ np = CopyParm(p);
+ if (pp) {
+ set_nextSibling(pp, np);
+ Delete(np);
+ } else {
+ fp = np;
+ }
+ pp = np;
+ p = nextSibling(p);
+ count--;
+ }
+ return fp;
+}
+
+ParmList *CopyParmList(ParmList *p) {
+ return CopyParmListMax(p,-1);
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_join()
+ *
+ * Join two parameter lists. Appends p2 to the end of p.
+ * No copies are made.
+ * Returns start of joined parameter list.
+ * ----------------------------------------------------------------------------- */
+
+ParmList *ParmList_join(ParmList *p, ParmList *p2) {
+ Parm *firstparm = p ? p : p2;
+ Parm *lastparm = 0;
+ while (p) {
+ lastparm = p;
+ p = nextSibling(p);
+ }
+ if (lastparm)
+ set_nextSibling(lastparm, p2);
+
+ return firstparm;
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_replace_last()
+ *
+ * Delete last parameter in p and replace it with parameter list p2.
+ * p must have at least one element, that is, must not be NULL.
+ * Return beginning of modified parameter list.
+ * ----------------------------------------------------------------------------- */
+
+ParmList *ParmList_replace_last(ParmList *p, ParmList *p2) {
+ ParmList *start = p;
+ int len = ParmList_len(p);
+ assert(p);
+ if (len == 1) {
+ start = p2;
+ } else if (len > 1) {
+ Parm *secondlastparm = ParmList_nth_parm(p, len - 2);
+ set_nextSibling(secondlastparm, p2);
+ }
+ return start;
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_nth_parm()
+ *
+ * return the nth parameter (0 based) in the parameter list
+ * return NULL if there are not enough parameters in the list
+ * ----------------------------------------------------------------------------- */
+
+Parm *ParmList_nth_parm(ParmList *p, unsigned int n) {
+ while (p) {
+ if (n == 0) {
+ break;
+ }
+ n--;
+ p = nextSibling(p);
+ }
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_variadic_parm()
+ *
+ * Return the variadic parm (last in list if it is variadic), NULL otherwise
+ * ----------------------------------------------------------------------------- */
+
+Parm *ParmList_variadic_parm(ParmList *p) {
+ Parm *lastparm = 0;
+ while (p) {
+ lastparm = p;
+ p = nextSibling(p);
+ }
+ return lastparm && SwigType_isvariadic(Getattr(lastparm, "type")) ? lastparm : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_numrequired()
+ *
+ * Return number of required arguments - the number of arguments excluding
+ * default arguments
+ * ----------------------------------------------------------------------------- */
+
+int ParmList_numrequired(ParmList *p) {
+ int i = 0;
+ while (p) {
+ SwigType *t = Getattr(p, "type");
+ String *value = Getattr(p, "value");
+ if (value)
+ return i;
+ if (!(SwigType_type(t) == T_VOID))
+ i++;
+ else
+ break;
+ p = nextSibling(p);
+ }
+ return i;
+}
+
+/* -----------------------------------------------------------------------------
+ * int ParmList_len()
+ * ----------------------------------------------------------------------------- */
+
+int ParmList_len(ParmList *p) {
+ int i = 0;
+ while (p) {
+ i++;
+ p = nextSibling(p);
+ }
+ return i;
+}
+
+/* ---------------------------------------------------------------------
+ * get_empty_type()
+ * ---------------------------------------------------------------------- */
+
+static SwigType *get_empty_type(void) {
+ return NewStringEmpty();
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_str()
+ *
+ * Generates a string of parameters
+ * ---------------------------------------------------------------------- */
+
+String *ParmList_str(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ String *type = Getattr(p, "type");
+ String *pstr = SwigType_str(type ? type : get_empty_type(), Getattr(p, "name"));
+ Append(out, pstr);
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ return out;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_str_defaultargs()
+ *
+ * Generates a string of parameters including default arguments
+ * ---------------------------------------------------------------------- */
+
+String *ParmList_str_defaultargs(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ String *value = Getattr(p, "value");
+ String *type = Getattr(p, "type");
+ String *pstr = SwigType_str(type ? type : get_empty_type(), Getattr(p, "name"));
+ Append(out, pstr);
+ if (value) {
+ Printf(out, "=%s", value);
+ }
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ return out;
+}
+
+/* -----------------------------------------------------------------------------
+ * ParmList_str_multibrackets()
+ *
+ * Generates a string of parameters including default arguments adding brackets
+ * if more than one parameter
+ * ----------------------------------------------------------------------------- */
+
+String *ParmList_str_multibrackets(ParmList *p) {
+ String *out;
+ String *parm_str = ParmList_str_defaultargs(p);
+ if (ParmList_len(p) > 1)
+ out = NewStringf("(%s)", parm_str);
+ else
+ out = NewStringf("%s", parm_str);
+ Delete(parm_str);
+ return out;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_protostr()
+ *
+ * Generate a prototype string.
+ * ---------------------------------------------------------------------- */
+
+String *ParmList_protostr(ParmList *p) {
+ String *out = NewStringEmpty();
+ while (p) {
+ String *type = Getattr(p, "type");
+ String *pstr = SwigType_str(type ? type : get_empty_type(), 0);
+ Append(out, pstr);
+ p = nextSibling(p);
+ if (p) {
+ Append(out, ",");
+ }
+ Delete(pstr);
+ }
+ return out;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_has_defaultargs()
+ *
+ * Returns 1 if the parameter list passed in is has one or more default
+ * arguments. Otherwise returns 0.
+ * ---------------------------------------------------------------------- */
+
+int ParmList_has_defaultargs(ParmList *p) {
+ while (p) {
+ if (Getattr(p, "value")) {
+ return 1;
+ }
+ p = nextSibling(p);
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------
+ * ParmList_has_varargs()
+ *
+ * Returns 1 if the parameter list passed in has varargs.
+ * Otherwise returns 0.
+ * ---------------------------------------------------------------------- */
+
+int ParmList_has_varargs(ParmList *p) {
+ Parm *lastparm = 0;
+ while (p) {
+ lastparm = p;
+ p = nextSibling(p);
+ }
+ return lastparm ? SwigType_isvarargs(Getattr(lastparm, "type")) : 0;
+}
diff --git a/contrib/tools/swig/Source/Swig/scanner.c b/contrib/tools/swig/Source/Swig/scanner.c
new file mode 100644
index 00000000000..4287691da95
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/scanner.c
@@ -0,0 +1,1810 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * scanner.c
+ *
+ * This file implements a general purpose C/C++ compatible lexical scanner.
+ * This scanner isn't intended to be plugged directly into a parser built
+ * with yacc. Rather, it contains a lot of generic code that could be used
+ * to easily construct yacc-compatible scanners.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <ctype.h>
+
+extern String *cparse_file;
+extern int cparse_line;
+extern int cparse_cplusplus;
+extern int cparse_start_line;
+
+struct Scanner {
+ String *text; /* Current token value */
+ List *scanobjs; /* Objects being scanned */
+ String *str; /* Current object being scanned */
+ char *idstart; /* Optional identifier start characters */
+ int nexttoken; /* Next token to be returned */
+ int start_line; /* Starting line of certain declarations */
+ int line;
+ int yylen; /* Length of text pushed into text */
+ String *error; /* Last error message (if any) */
+ int error_line; /* Error line number */
+ int freeze_line; /* Suspend line number updates */
+ List *brackets; /* Current level of < > brackets on each level */
+};
+
+typedef struct Locator {
+ String *filename;
+ int line_number;
+ struct Locator *next;
+} Locator;
+static int follow_locators = 0;
+
+static void brackets_push(Scanner *);
+static void brackets_clear(Scanner *);
+
+/* -----------------------------------------------------------------------------
+ * NewScanner()
+ *
+ * Create a new scanner object
+ * ----------------------------------------------------------------------------- */
+
+Scanner *NewScanner(void) {
+ Scanner *s;
+ s = (Scanner *) Malloc(sizeof(Scanner));
+ s->line = 1;
+ s->nexttoken = -1;
+ s->start_line = 1;
+ s->yylen = 0;
+ s->idstart = NULL;
+ s->scanobjs = NewList();
+ s->text = NewStringEmpty();
+ s->str = 0;
+ s->error = 0;
+ s->error_line = 0;
+ s->freeze_line = 0;
+ s->brackets = NewList();
+ brackets_push(s);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * DelScanner()
+ *
+ * Delete a scanner object.
+ * ----------------------------------------------------------------------------- */
+
+void DelScanner(Scanner *s) {
+ assert(s);
+ Delete(s->scanobjs);
+ Delete(s->brackets);
+ Delete(s->text);
+ Delete(s->error);
+ Delete(s->str);
+ Free(s->idstart);
+ Free(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_clear()
+ *
+ * Clear the contents of a scanner object.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_clear(Scanner *s) {
+ assert(s);
+ Delete(s->str);
+ Clear(s->text);
+ Clear(s->scanobjs);
+ brackets_clear(s);
+ Delete(s->error);
+ s->str = 0;
+ s->error = 0;
+ s->line = 1;
+ s->nexttoken = -1;
+ s->start_line = 0;
+ s->yylen = 0;
+ /* Should these be cleared too?
+ s->idstart;
+ s->error_line;
+ s->freeze_line;
+ */
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_push()
+ *
+ * Push some new text into the scanner. The scanner will start parsing this text
+ * immediately before returning to the old text.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_push(Scanner *s, String *txt) {
+ assert(s && txt);
+ Push(s->scanobjs, txt);
+ if (s->str) {
+ Setline(s->str,s->line);
+ Delete(s->str);
+ }
+ s->str = txt;
+ DohIncref(s->str);
+ s->line = Getline(txt);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_pushtoken()
+ *
+ * Push a token into the scanner. This token will be returned on the next
+ * call to Scanner_token().
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_pushtoken(Scanner *s, int nt, const_String_or_char_ptr val) {
+ assert(s);
+ assert((nt >= 0) && (nt < SWIG_MAXTOKENS));
+ s->nexttoken = nt;
+ if ( Char(val) != Char(s->text) ) {
+ Clear(s->text);
+ Append(s->text,val);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_set_location()
+ *
+ * Set the file and line number location of the scanner.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_set_location(Scanner *s, String *file, int line) {
+ Setline(s->str, line);
+ Setfile(s->str, file);
+ s->line = line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_file()
+ *
+ * Get the current file.
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_file(Scanner *s) {
+ return Getfile(s->str);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_line()
+ *
+ * Get the current line number
+ * ----------------------------------------------------------------------------- */
+int Scanner_line(Scanner *s) {
+ return s->line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_start_line()
+ *
+ * Get the line number on which the current token starts
+ * ----------------------------------------------------------------------------- */
+int Scanner_start_line(Scanner *s) {
+ return s->start_line;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_idstart()
+ *
+ * Change the set of additional characters that can be used to start an identifier.
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_idstart(Scanner *s, const char *id) {
+ Free(s->idstart);
+ s->idstart = Swig_copy_string(id);
+}
+
+/* -----------------------------------------------------------------------------
+ * nextchar()
+ *
+ * Returns the next character from the scanner or EOF if end of the string.
+ * ----------------------------------------------------------------------------- */
+static int nextchar(Scanner *s) {
+ int nc;
+ if (!s->str)
+ return EOF;
+ while ((nc = Getc(s->str)) == EOF) {
+ Delete(s->str);
+ s->str = 0;
+ Delitem(s->scanobjs, 0);
+ if (Len(s->scanobjs) == 0)
+ return EOF;
+ s->str = Getitem(s->scanobjs, 0);
+ s->line = Getline(s->str);
+ DohIncref(s->str);
+ }
+ if ((nc == '\n') && (!s->freeze_line))
+ s->line++;
+ Putc(nc, s->text);
+ return nc;
+}
+
+/* -----------------------------------------------------------------------------
+ * set_error()
+ *
+ * Sets error information on the scanner.
+ * ----------------------------------------------------------------------------- */
+
+static void set_error(Scanner *s, int line, const_String_or_char_ptr msg) {
+ s->error_line = line;
+ s->error = NewString(msg);
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_errmsg()
+ * Scanner_errline()
+ *
+ * Returns error information (if any)
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_errmsg(Scanner *s) {
+ return s->error;
+}
+
+int Scanner_errline(Scanner *s) {
+ return s->error_line;
+}
+
+/* -----------------------------------------------------------------------------
+ * freeze_line()
+ *
+ * Freezes the current line number.
+ * ----------------------------------------------------------------------------- */
+
+static void freeze_line(Scanner *s, int val) {
+ s->freeze_line = val;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_count()
+ *
+ * Returns the number of brackets at the current depth.
+ * A syntax error with unbalanced ) brackets will result in a NULL pointer return.
+ * ----------------------------------------------------------------------------- */
+static int *brackets_count(Scanner *s) {
+ int *count;
+ if (Len(s->brackets) > 0)
+ count = (int *)Data(Getitem(s->brackets, 0));
+ else
+ count = 0;
+ return count;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_clear()
+ *
+ * Resets the current depth and clears all brackets.
+ * Usually called at the end of statements;
+ * ----------------------------------------------------------------------------- */
+static void brackets_clear(Scanner *s) {
+ Clear(s->brackets);
+ brackets_push(s); /* base bracket count should always be created */
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_increment()
+ *
+ * Increases the number of brackets at the current depth.
+ * Usually called when a single '<' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_increment(Scanner *s) {
+ int *count = brackets_count(s);
+ if (count)
+ (*count)++;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_decrement()
+ *
+ * Decreases the number of brackets at the current depth.
+ * Usually called when a single '>' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_decrement(Scanner *s) {
+ int *count = brackets_count(s);
+ if (count)
+ (*count)--;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_reset()
+ *
+ * Sets the number of '<' brackets back to zero. Called at the point where
+ * it is no longer possible to have a matching closing >> pair for a template.
+ * ----------------------------------------------------------------------------- */
+static void brackets_reset(Scanner *s) {
+ int *count = brackets_count(s);
+ if (count)
+ *count = 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_push()
+ *
+ * Increases the depth of brackets.
+ * Usually called when '(' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_push(Scanner *s) {
+ int *newInt = (int *)Malloc(sizeof(int));
+ *newInt = 0;
+ Push(s->brackets, NewVoid(newInt, Free));
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_pop()
+ *
+ * Decreases the depth of brackets.
+ * Usually called when ')' is found.
+ * ----------------------------------------------------------------------------- */
+static void brackets_pop(Scanner *s) {
+ if (Len(s->brackets) > 0) /* protect against unbalanced ')' brackets */
+ Delitem(s->brackets, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * brackets_allow_shift()
+ *
+ * Return 1 to allow shift (>>), or 0 if (>>) should be split into (> >).
+ * This is for C++11 template syntax for closing templates.
+ * ----------------------------------------------------------------------------- */
+static int brackets_allow_shift(Scanner *s) {
+ int *count = brackets_count(s);
+ return !count || (*count <= 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * retract()
+ *
+ * Retract n characters
+ * ----------------------------------------------------------------------------- */
+static void retract(Scanner *s, int n) {
+ int i, l;
+ char *str;
+
+ str = Char(s->text);
+ l = Len(s->text);
+ assert(n <= l);
+ for (i = 0; i < n; i++) {
+ if (str[l - 1] == '\n') {
+ if (!s->freeze_line) s->line--;
+ }
+ (void)Seek(s->str, -1, SEEK_CUR);
+ Delitem(s->text, DOH_END);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * get_escape()
+ *
+ * Get escape sequence. Called when a backslash is found in a string
+ * ----------------------------------------------------------------------------- */
+
+static void get_escape(Scanner *s) {
+ int result = 0;
+ int state = 0;
+ int c;
+
+ while (1) {
+ c = nextchar(s);
+ if (c == EOF)
+ break;
+ switch (state) {
+ case 0:
+ if (c == 'n') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\n");
+ return;
+ }
+ if (c == 'r') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\r");
+ return;
+ }
+ if (c == 't') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\t");
+ return;
+ }
+ if (c == 'a') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\a");
+ return;
+ }
+ if (c == 'b') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\b");
+ return;
+ }
+ if (c == 'f') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\f");
+ return;
+ }
+ if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\\");
+ return;
+ }
+ if (c == 'v') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\v");
+ return;
+ }
+ if (c == 'e') {
+ // '\e' is a non-standard alternative to '\033' (the escape character)
+ // in both C and C++, but is supported by at least GCC and clang. MSVC
+ // issues a warning and treats it as an 'e'.
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\033");
+ return;
+ }
+ if (c == '\'') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\'");
+ return;
+ }
+ if (c == '\"') {
+ Delitem(s->text, DOH_END);
+ Append(s->text,"\"");
+ return;
+ }
+ if (c == '\n') {
+ Delitem(s->text, DOH_END);
+ return;
+ }
+ if (isdigit(c)) {
+ state = 10;
+ result = (c - '0');
+ Delitem(s->text, DOH_END);
+ } else if (c == 'x') {
+ state = 20;
+ Delitem(s->text, DOH_END);
+ } else {
+ Delitem(s->text, DOH_END);
+ Putc('\\',s->text);
+ Putc((char)c,s->text);
+ return;
+ }
+ break;
+ case 10: // Second digit of octal escape sequence
+ case 11: // Third digit of octal escape sequence
+ if (c < '0' || c > '7') {
+ retract(s,1);
+ Putc((char)result,s->text);
+ return;
+ }
+ result = (result << 3) + (c - '0');
+ Delitem(s->text, DOH_END);
+ if (state == 11) {
+ if (result > 255)
+ Swig_error(Scanner_file(s), Scanner_line(s), "octal escape sequence out of range\n");
+ Putc((char)result,s->text);
+ return;
+ }
+ state = 11;
+ break;
+ case 20:
+ if (!isxdigit(c)) {
+ retract(s,1);
+ Putc((char)result, s->text);
+ return;
+ }
+ if (isdigit(c))
+ result = (result << 4) + (c - '0');
+ else
+ result = (result << 4) + (10 + tolower(c) - 'a');
+ Delitem(s->text, DOH_END);
+ break;
+ }
+ }
+ return;
+}
+
+/* -----------------------------------------------------------------------------
+ * look()
+ *
+ * Return the raw value of the next token.
+ * ----------------------------------------------------------------------------- */
+
+static int look(Scanner *s) {
+ int state = 0;
+ int c = 0;
+ String *str_delimiter = 0;
+
+ Clear(s->text);
+ s->start_line = s->line;
+ Setfile(s->text, Getfile(s->str));
+
+
+ while (1) {
+ switch (state) {
+ case 0:
+ if ((c = nextchar(s)) == EOF)
+ return (0);
+
+ /* Process delimiters */
+
+ if (c == '\n') {
+ return SWIG_TOKEN_ENDLINE;
+ } else if (!isspace(c)) {
+ retract(s, 1);
+ state = 1000;
+ Clear(s->text);
+ Setline(s->text, s->line);
+ Setfile(s->text, Getfile(s->str));
+ }
+ break;
+
+ case 1000:
+ if ((c = nextchar(s)) == EOF)
+ return (0);
+ if (c == '%')
+ state = 4; /* Possibly a SWIG directive */
+
+ /* Look for possible identifiers or unicode/delimiter strings */
+ else if ((isalpha(c)) || (c == '_') ||
+ (s->idstart && strchr(s->idstart, c))) {
+ state = 7;
+ }
+
+ /* Look for single character symbols */
+
+ else if (c == '(') {
+ brackets_push(s);
+ return SWIG_TOKEN_LPAREN;
+ }
+ else if (c == ')') {
+ brackets_pop(s);
+ return SWIG_TOKEN_RPAREN;
+ }
+ else if (c == ';') {
+ brackets_clear(s);
+ return SWIG_TOKEN_SEMI;
+ }
+ else if (c == ',')
+ return SWIG_TOKEN_COMMA;
+ else if (c == '*')
+ state = 220;
+ else if (c == '}')
+ return SWIG_TOKEN_RBRACE;
+ else if (c == '{') {
+ brackets_reset(s);
+ return SWIG_TOKEN_LBRACE;
+ }
+ else if (c == '=')
+ state = 33;
+ else if (c == '+')
+ state = 200;
+ else if (c == '-')
+ state = 210;
+ else if (c == '&')
+ state = 31;
+ else if (c == '|')
+ state = 32;
+ else if (c == '^')
+ state = 230;
+ else if (c == '<')
+ state = 60;
+ else if (c == '>')
+ state = 61;
+ else if (c == '~')
+ return SWIG_TOKEN_NOT;
+ else if (c == '!')
+ state = 3;
+ else if (c == '\\')
+ return SWIG_TOKEN_BACKSLASH;
+ else if (c == '@')
+ return SWIG_TOKEN_AT;
+ else if (c == '$')
+ state = 75;
+ else if (c == '#')
+ return SWIG_TOKEN_POUND;
+ else if (c == '?')
+ return SWIG_TOKEN_QUESTION;
+
+ /* Look for multi-character sequences */
+
+ else if (c == '/') {
+ state = 1; /* Comment (maybe) */
+ s->start_line = s->line;
+ }
+
+ else if (c == ':')
+ state = 5; /* maybe double colon */
+ else if (c == '0')
+ state = 83; /* Maybe a hex, octal or binary number */
+ else if (c == '\"') {
+ state = 2; /* A string constant */
+ s->start_line = s->line;
+ Clear(s->text);
+ }
+ else if (c == '\'') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 9; /* A character constant */
+ } else if (c == '`') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 900;
+ }
+
+ else if (c == '.')
+ state = 100; /* Maybe a number, maybe ellipsis, just a period */
+ else if (c == '[')
+ state = 102; /* Maybe a bracket or a double bracket */
+ else if (c == ']')
+ state = 103; /* Maybe a bracket or a double bracket */
+ else if (isdigit(c))
+ state = 8; /* A numerical value */
+ else
+ state = 99; /* An error */
+ break;
+
+ case 1: /* Comment block */
+ if ((c = nextchar(s)) == EOF)
+ return (0);
+ if (c == '/') {
+ state = 10; /* C++ style comment */
+ Clear(s->text);
+ Setline(s->text, Getline(s->str));
+ Setfile(s->text, Getfile(s->str));
+ Append(s->text, "//");
+ } else if (c == '*') {
+ state = 11; /* C style comment */
+ Clear(s->text);
+ Setline(s->text, Getline(s->str));
+ Setfile(s->text, Getfile(s->str));
+ Append(s->text, "/*");
+ } else if (c == '=') {
+ return SWIG_TOKEN_DIVEQUAL;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_SLASH;
+ }
+ break;
+ case 10: /* C++ style comment */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\n') {
+ retract(s,1);
+ return SWIG_TOKEN_COMMENT;
+ } else {
+ state = 10;
+ }
+ break;
+ case 11: /* C style comment block */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '*') {
+ state = 12;
+ } else {
+ state = 11;
+ }
+ break;
+ case 12: /* Still in C style comment */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated comment\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '*') {
+ state = 12;
+ } else if (c == '/') {
+ return SWIG_TOKEN_COMMENT;
+ } else {
+ state = 11;
+ }
+ break;
+
+ case 2: /* Processing a string */
+ if (!str_delimiter) {
+ state=20;
+ break;
+ }
+
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ else if (c == '(') {
+ state = 20;
+ }
+ else {
+ Putc( (char)c, str_delimiter );
+ }
+
+ break;
+
+ case 20: /* Inside the string */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+
+ if (!str_delimiter) { /* Ordinary string: "value" */
+ if (c == '\"') {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_STRING;
+ } else if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ get_escape(s);
+ }
+ } else { /* Custom delimiter string: R"XXXX(value)XXXX" */
+ if (c==')') {
+ int i=0;
+ String *end_delimiter = NewStringEmpty();
+ while ((c = nextchar(s)) != EOF && c != '\"') {
+ Putc( (char)c, end_delimiter );
+ i++;
+ }
+
+ if (Strcmp( str_delimiter, end_delimiter )==0) {
+ int len = Len(s->text);
+ Delslice(s->text, len - 2 - Len(str_delimiter), len); /* Delete ending )XXXX" */
+ Delslice(s->text, 0, Len(str_delimiter) + 1); /* Delete starting XXXX( */
+ Delete( end_delimiter ); /* Correct end delimiter )XXXX" occurred */
+ Delete( str_delimiter );
+ str_delimiter = 0;
+ return SWIG_TOKEN_STRING;
+ } else { /* Incorrect end delimiter occurred */
+ if (c == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated raw string, started with R\"%s( is not terminated by )%s\"\n", str_delimiter, str_delimiter);
+ return SWIG_TOKEN_ERROR;
+ }
+ retract( s, i );
+ Delete( end_delimiter );
+ }
+ }
+ }
+
+ break;
+
+ case 3: /* Maybe a not equals */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_LNOT;
+ else if (c == '=')
+ return SWIG_TOKEN_NOTEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_LNOT;
+ }
+ break;
+
+ case 31: /* AND or Logical AND or ANDEQUAL */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_AND;
+ else if (c == '&')
+ return SWIG_TOKEN_LAND;
+ else if (c == '=')
+ return SWIG_TOKEN_ANDEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_AND;
+ }
+ break;
+
+ case 32: /* OR or Logical OR */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_OR;
+ else if (c == '|')
+ return SWIG_TOKEN_LOR;
+ else if (c == '=')
+ return SWIG_TOKEN_OREQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_OR;
+ }
+ break;
+
+ case 33: /* EQUAL or EQUALTO */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_EQUAL;
+ else if (c == '=')
+ return SWIG_TOKEN_EQUALTO;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_EQUAL;
+ }
+ break;
+
+ case 4: /* A wrapper generator directive (maybe) */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_PERCENT;
+ if (c == '{') {
+ state = 40; /* Include block */
+ Clear(s->text);
+ Setline(s->text, Getline(s->str));
+ Setfile(s->text, Getfile(s->str));
+ s->start_line = s->line;
+ } else if (s->idstart && strchr(s->idstart, '%') &&
+ ((isalpha(c)) || (c == '_'))) {
+ state = 7;
+ } else if (c == '=') {
+ return SWIG_TOKEN_MODEQUAL;
+ } else if (c == '}') {
+ Swig_error(cparse_file, cparse_line, "Syntax error. Extraneous '%%}'\n");
+ Exit(EXIT_FAILURE);
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_PERCENT;
+ }
+ break;
+
+ case 40: /* Process an include block */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated block\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '%')
+ state = 41;
+ break;
+ case 41: /* Still processing include block */
+ if ((c = nextchar(s)) == EOF) {
+ set_error(s,s->start_line,"Unterminated code block");
+ return 0;
+ }
+ if (c == '}') {
+ Delitem(s->text, DOH_END);
+ Delitem(s->text, DOH_END);
+ Seek(s->text,0,SEEK_SET);
+ return SWIG_TOKEN_CODEBLOCK;
+ } else {
+ state = 40;
+ }
+ break;
+
+ case 5: /* Maybe a double colon */
+
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_COLON;
+ if (c == ':')
+ state = 50;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_COLON;
+ }
+ break;
+
+ case 50: /* DCOLON, DCOLONSTAR */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_DCOLON;
+ else if (c == '*')
+ return SWIG_TOKEN_DCOLONSTAR;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_DCOLON;
+ }
+ break;
+
+ case 60: /* shift operators */
+ if ((c = nextchar(s)) == EOF) {
+ brackets_increment(s);
+ return SWIG_TOKEN_LESSTHAN;
+ }
+ if (c == '<')
+ state = 240;
+ else if (c == '=') {
+ if ((c = nextchar(s)) == EOF) {
+ return SWIG_TOKEN_LTEQUAL;
+ } else if (c == '>' && cparse_cplusplus) { /* Spaceship operator */
+ return SWIG_TOKEN_LTEQUALGT;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LTEQUAL;
+ }
+ } else {
+ retract(s, 1);
+ brackets_increment(s);
+ return SWIG_TOKEN_LESSTHAN;
+ }
+ break;
+ case 61:
+ if ((c = nextchar(s)) == EOF) {
+ brackets_decrement(s);
+ return SWIG_TOKEN_GREATERTHAN;
+ }
+ if (c == '>' && brackets_allow_shift(s))
+ state = 250;
+ else if (c == '=')
+ return SWIG_TOKEN_GTEQUAL;
+ else {
+ retract(s, 1);
+ brackets_decrement(s);
+ return SWIG_TOKEN_GREATERTHAN;
+ }
+ break;
+
+ case 7: /* Identifier or true/false or unicode/custom delimiter string */
+ if (c == 'R') { /* Possibly CUSTOM DELIMITER string */
+ state = 72;
+ break;
+ }
+ else if (c == 'L') { /* Probably identifier but may be a wide string literal */
+ state = 77;
+ break;
+ }
+ else if (c != 'u' && c != 'U') { /* Definitely an identifier */
+ state = 70;
+ break;
+ }
+
+ if ((c = nextchar(s)) == EOF) {
+ state = 76;
+ }
+ else if (c == '\"') { /* Definitely u, U or L string */
+ retract(s, 1);
+ state = 1000;
+ }
+ else if (c == '\'') { /* Definitely u, U or L char */
+ retract(s, 1);
+ state = 77;
+ }
+ else if (c == 'R') { /* Possibly CUSTOM DELIMITER u, U, L string */
+ state = 73;
+ }
+ else if (c == '8') { /* Possibly u8 string/char */
+ state = 71;
+ }
+ else {
+ retract(s, 1); /* Definitely an identifier */
+ state = 70;
+ }
+ break;
+
+ case 70: /* Identifier */
+ if ((c = nextchar(s)) == EOF)
+ state = 76;
+ else if (isalnum(c) || (c == '_') || (c == '$')) {
+ state = 70;
+ } else {
+ retract(s, 1);
+ state = 76;
+ }
+ break;
+
+ case 71: /* Possibly u8 string/char */
+ if ((c = nextchar(s)) == EOF) {
+ state = 76;
+ }
+ else if (c=='\"') {
+ retract(s, 1); /* Definitely u8 string */
+ state = 1000;
+ }
+ else if (c=='\'') {
+ retract(s, 1); /* Definitely u8 char */
+ state = 77;
+ }
+ else if (c=='R') {
+ state = 74; /* Possibly CUSTOM DELIMITER u8 string */
+ }
+ else {
+ retract(s, 2); /* Definitely an identifier. Retract 8" */
+ state = 70;
+ }
+
+ break;
+
+ case 72: /* Possibly CUSTOM DELIMITER string */
+ case 73:
+ case 74:
+ if ((c = nextchar(s)) == EOF) {
+ state = 76;
+ }
+ else if (c=='\"') {
+ retract(s, 1); /* Definitely custom delimiter u, U or L string */
+ str_delimiter = NewStringEmpty();
+ state = 1000;
+ }
+ else {
+ if (state==72) {
+ retract(s, 1); /* Definitely an identifier. Retract ? */
+ }
+ else if (state==73) {
+ retract(s, 2); /* Definitely an identifier. Retract R? */
+ }
+ else if (state==74) {
+ retract(s, 3); /* Definitely an identifier. Retract 8R? */
+ }
+ state = 70;
+ }
+
+ break;
+
+ case 75: /* Special identifier $ */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_DOLLAR;
+ if (isalnum(c) || (c == '_') || (c == '*') || (c == '&')) {
+ state = 70;
+ } else {
+ retract(s,1);
+ if (Len(s->text) == 1) return SWIG_TOKEN_DOLLAR;
+ state = 76;
+ }
+ break;
+
+ case 76: /* Identifier, true/false or alternative token */
+ if (cparse_cplusplus) {
+ if (Strcmp(s->text, "true") == 0)
+ return SWIG_TOKEN_BOOL;
+ if (Strcmp(s->text, "false") == 0)
+ return SWIG_TOKEN_BOOL;
+
+ if (Strcmp(s->text, "and") == 0)
+ return SWIG_TOKEN_LAND;
+ if (Strcmp(s->text, "and_eq") == 0)
+ return SWIG_TOKEN_ANDEQUAL;
+ if (Strcmp(s->text, "bitand") == 0)
+ return SWIG_TOKEN_AND;
+ if (Strcmp(s->text, "bitor") == 0)
+ return SWIG_TOKEN_OR;
+ if (Strcmp(s->text, "compl") == 0)
+ return SWIG_TOKEN_NOT;
+ if (Strcmp(s->text, "not") == 0)
+ return SWIG_TOKEN_LNOT;
+ if (Strcmp(s->text, "not_eq") == 0)
+ return SWIG_TOKEN_NOTEQUAL;
+ if (Strcmp(s->text, "or") == 0)
+ return SWIG_TOKEN_LOR;
+ if (Strcmp(s->text, "or_eq") == 0)
+ return SWIG_TOKEN_OREQUAL;
+ if (Strcmp(s->text, "xor") == 0)
+ return SWIG_TOKEN_XOR;
+ if (Strcmp(s->text, "xor_eq") == 0)
+ return SWIG_TOKEN_XOREQUAL;
+ }
+ return SWIG_TOKEN_ID;
+
+ case 77: /*identifier or wide string literal*/
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_ID;
+ else if (c == '\"') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 78;
+ }
+ else if (c == '\'') {
+ s->start_line = s->line;
+ Clear(s->text);
+ state = 79;
+ }
+ else if (isalnum(c) || (c == '_') || (c == '$'))
+ state = 7;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_ID;
+ }
+ break;
+
+ case 78: /* Processing a wide string literal*/
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated wide string\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\"') {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_WSTRING;
+ } else if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ get_escape(s);
+ }
+ break;
+
+ case 79: /* Processing a wide char literal */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated wide character constant\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\'') {
+ Delitem(s->text, DOH_END);
+ return (SWIG_TOKEN_WCHAR);
+ } else if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ get_escape(s);
+ }
+ break;
+
+ case 8: /* A numerical digit */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_INT;
+ if (c == '.') {
+ state = 81;
+ } else if ((c == 'e') || (c == 'E')) {
+ state = 82;
+ } else if ((c == 'f') || (c == 'F')) {
+ return SWIG_TOKEN_FLOAT;
+ } else if (isdigit(c)) {
+ state = 8;
+ } else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 81: /* A floating pointer number of some sort */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_DOUBLE;
+ if (isdigit(c))
+ state = 81;
+ else if ((c == 'e') || (c == 'E'))
+ state = 820;
+ else if ((c == 'f') || (c == 'F')) {
+ return SWIG_TOKEN_FLOAT;
+ } else if ((c == 'l') || (c == 'L')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_LONGDOUBLE;
+ } else {
+ retract(s, 1);
+ return (SWIG_TOKEN_DOUBLE);
+ }
+ break;
+ case 82:
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if ((isdigit(c)) || (c == '-') || (c == '+'))
+ state = 86;
+ else {
+ retract(s, 2);
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ break;
+ case 820:
+ /* Like case 82, but we've seen a decimal point. */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if ((isdigit(c)) || (c == '-') || (c == '+'))
+ state = 86;
+ else {
+ retract(s, 2);
+ Swig_error(cparse_file, cparse_start_line, "Exponent does not have any digits\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ break;
+ case 83:
+ /* Might be a hexadecimal, octal or binary number */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_INT;
+ if (isdigit(c))
+ state = 84;
+ else if ((c == 'e') || (c == 'E'))
+ state = 82;
+ else if ((c == 'x') || (c == 'X'))
+ state = 85;
+ else if ((c == 'b') || (c == 'B'))
+ state = 850;
+ else if (c == '.')
+ state = 81;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 84:
+ /* This is an octal number */
+ if (c == '8' || c == '9') {
+ Swig_error(Scanner_file(s), Scanner_line(s), "Invalid digit '%c' in octal constant\n", c);
+ }
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_INT;
+ if (isdigit(c))
+ state = 84;
+ else if (c == '.')
+ state = 81;
+ else if ((c == 'e') || (c == 'E'))
+ state = 82;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 85:
+ /* This is an hex number */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_INT;
+ if (isxdigit(c))
+ state = 85;
+ else if (c == '.') /* hexadecimal float */
+ state = 860;
+ else if ((c == 'p') || (c == 'P')) /* hexadecimal float */
+ state = 820;
+ else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 850:
+ /* This is a binary number */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_INT;
+ if ((c == '0') || (c == '1'))
+ state = 850;
+ else if (isdigit(c)) {
+ Swig_error(Scanner_file(s), Scanner_line(s), "Invalid digit '%c' in binary constant\n", c);
+ } else if ((c == 'l') || (c == 'L')) {
+ state = 87;
+ } else if ((c == 'u') || (c == 'U')) {
+ state = 88;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_INT;
+ }
+ break;
+ case 860:
+ /* hexadecimal float */
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (isxdigit(c))
+ state = 860;
+ else if ((c == 'p') || (c == 'P'))
+ state = 820;
+ else {
+ retract(s, 2);
+ Swig_error(cparse_file, cparse_start_line, "Hexadecimal floating literals require an exponent\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ break;
+ case 86:
+ /* Rest of floating point number */
+
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_DOUBLE;
+ if (isdigit(c))
+ state = 86;
+ else if ((c == 'f') || (c == 'F')) {
+ return SWIG_TOKEN_FLOAT;
+ } else if ((c == 'l') || (c == 'L')) {
+ Delitem(s->text, DOH_END);
+ return SWIG_TOKEN_LONGDOUBLE;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_DOUBLE;
+ }
+ break;
+
+ case 87:
+ /* A long integer of some sort */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_LONG;
+ if ((c == 'u') || (c == 'U')) {
+ return SWIG_TOKEN_ULONG;
+ } else if ((c == 'l') || (c == 'L')) {
+ state = 870;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LONG;
+ }
+ break;
+
+ /* A long long integer */
+
+ case 870:
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_LONGLONG;
+ if ((c == 'u') || (c == 'U')) {
+ return SWIG_TOKEN_ULONGLONG;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LONGLONG;
+ }
+
+ /* An unsigned number */
+ case 88:
+
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_UINT;
+ if ((c == 'l') || (c == 'L')) {
+ state = 880;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_UINT;
+ }
+ break;
+
+ /* Possibly an unsigned long long or unsigned long */
+ case 880:
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_ULONG;
+ if ((c == 'l') || (c == 'L'))
+ return SWIG_TOKEN_ULONGLONG;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_ULONG;
+ }
+
+ /* A character constant */
+ case 9:
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '\'') {
+ Delitem(s->text, DOH_END);
+ return (SWIG_TOKEN_CHAR);
+ } else if (c == '\\') {
+ Delitem(s->text, DOH_END);
+ get_escape(s);
+ }
+ break;
+
+ /* A period or an ellipsis or maybe a floating point number */
+
+ case 100:
+ if ((c = nextchar(s)) == EOF)
+ return (0);
+ if (isdigit(c))
+ state = 81;
+ else if (c == '.')
+ state = 101;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_PERIOD;
+ }
+ break;
+
+ /* An ellipsis */
+
+ case 101:
+ if ((c = nextchar(s)) == EOF)
+ return (0);
+ if (c == '.') {
+ return SWIG_TOKEN_ELLIPSIS;
+ } else {
+ retract(s, 2);
+ return SWIG_TOKEN_PERIOD;
+ }
+ break;
+
+ /* A left bracket or a double left bracket */
+ case 102:
+
+ if ((c = nextchar(s)) == EOF) {
+ return SWIG_TOKEN_LBRACKET;
+ } else if (c == '[') {
+ return SWIG_TOKEN_LLBRACKET;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_LBRACKET;
+ }
+ break;
+
+ /* a right bracket or a double right bracket */
+ case 103:
+ if ((c = nextchar(s)) == EOF) {
+ return SWIG_TOKEN_RBRACKET;
+ } else if (c == ']') {
+ return SWIG_TOKEN_RRBRACKET;
+ } else {
+ retract(s, 1);
+ return SWIG_TOKEN_RBRACKET;
+ }
+ break;
+
+ case 200: /* PLUS, PLUSPLUS, PLUSEQUAL */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_PLUS;
+ else if (c == '+')
+ return SWIG_TOKEN_PLUSPLUS;
+ else if (c == '=')
+ return SWIG_TOKEN_PLUSEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_PLUS;
+ }
+ break;
+
+ case 210: /* MINUS, MINUSMINUS, MINUSEQUAL, ARROW */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_MINUS;
+ else if (c == '-')
+ return SWIG_TOKEN_MINUSMINUS;
+ else if (c == '=')
+ return SWIG_TOKEN_MINUSEQUAL;
+ else if (c == '>')
+ state = 211;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_MINUS;
+ }
+ break;
+
+ case 211: /* ARROW, ARROWSTAR */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_ARROW;
+ else if (c == '*')
+ return SWIG_TOKEN_ARROWSTAR;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_ARROW;
+ }
+ break;
+
+
+ case 220: /* STAR, TIMESEQUAL */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_STAR;
+ else if (c == '=')
+ return SWIG_TOKEN_TIMESEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_STAR;
+ }
+ break;
+
+ case 230: /* XOR, XOREQUAL */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_XOR;
+ else if (c == '=')
+ return SWIG_TOKEN_XOREQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_XOR;
+ }
+ break;
+
+ case 240: /* LSHIFT, LSEQUAL */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_LSHIFT;
+ else if (c == '=')
+ return SWIG_TOKEN_LSEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_LSHIFT;
+ }
+ break;
+
+ case 250: /* RSHIFT, RSEQUAL */
+ if ((c = nextchar(s)) == EOF)
+ return SWIG_TOKEN_RSHIFT;
+ else if (c == '=')
+ return SWIG_TOKEN_RSEQUAL;
+ else {
+ retract(s, 1);
+ return SWIG_TOKEN_RSHIFT;
+ }
+ break;
+
+ /* Reverse string */
+ case 900:
+ if ((c = nextchar(s)) == EOF) {
+ Swig_error(cparse_file, cparse_start_line, "Unterminated character constant\n");
+ return SWIG_TOKEN_ERROR;
+ }
+ if (c == '`') {
+ Delitem(s->text, DOH_END);
+ return (SWIG_TOKEN_RSTRING);
+ }
+ break;
+
+ /* An illegal character */
+ default:
+ return SWIG_TOKEN_ILLEGAL;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_token()
+ *
+ * Real entry point to return the next token. Returns 0 if at end of input.
+ * ----------------------------------------------------------------------------- */
+
+int Scanner_token(Scanner *s) {
+ int t;
+ Delete(s->error);
+ if (s->nexttoken >= 0) {
+ t = s->nexttoken;
+ s->nexttoken = -1;
+ return t;
+ }
+ s->start_line = 0;
+ t = look(s);
+ if (!s->start_line) {
+ Setline(s->text,s->line);
+ } else {
+ Setline(s->text,s->start_line);
+ }
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_text()
+ *
+ * Return the lexene associated with the last returned token.
+ * ----------------------------------------------------------------------------- */
+
+String *Scanner_text(Scanner *s) {
+ return s->text;
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_skip_line()
+ *
+ * Skips to the end of a line
+ * ----------------------------------------------------------------------------- */
+
+void Scanner_skip_line(Scanner *s) {
+ Clear(s->text);
+ Setfile(s->text, Getfile(s->str));
+ Setline(s->text, s->line);
+ while (1) {
+ int c;
+ if ((c = nextchar(s)) == EOF)
+ return;
+ if (c == '\\') {
+ nextchar(s);
+ } else if (c == '\n') {
+ return;
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Scanner_skip_balanced()
+ *
+ * Skips a piece of code enclosed in begin/end symbols such as '{...}' or
+ * (...). Ignores symbols inside comments or strings.
+ *
+ * Returns 0 on success, -1 if no matching endchar could be found.
+ * ----------------------------------------------------------------------------- */
+
+int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) {
+ int old_line = s->line;
+ long position = Tell(s->str);
+
+ int num_levels = 1;
+ int starttok = 0;
+ int endtok = 0;
+ switch (endchar) {
+ case '}':
+ starttok = SWIG_TOKEN_LBRACE;
+ endtok = SWIG_TOKEN_RBRACE;
+ break;
+ case ')':
+ starttok = SWIG_TOKEN_LPAREN;
+ endtok = SWIG_TOKEN_RPAREN;
+ break;
+ case ']':
+ starttok = SWIG_TOKEN_LBRACKET;
+ endtok = SWIG_TOKEN_RBRACKET;
+ break;
+ case '>':
+ starttok = SWIG_TOKEN_LESSTHAN;
+ endtok = SWIG_TOKEN_GREATERTHAN;
+ break;
+ default:
+ assert(0);
+ }
+
+ while (1) {
+ int tok = Scanner_token(s);
+ if (tok == starttok) {
+ num_levels++;
+ } else if (tok == endtok) {
+ if (--num_levels == 0) break;
+ } else if (tok == SWIG_TOKEN_RRBRACKET && endtok == SWIG_TOKEN_RBRACKET) {
+ num_levels -= 2;
+ if (num_levels <= 0) {
+ if (num_levels < 0) Scanner_pushtoken(s, SWIG_TOKEN_RBRACKET, "]");
+ break;
+ }
+ } else if (tok == SWIG_TOKEN_COMMENT) {
+ char *loc = Char(s->text);
+ if (strncmp(loc, "/*@SWIG", 7) == 0 && loc[Len(s->text)-3] == '@') {
+ Scanner_locator(s, s->text);
+ }
+ } else if (tok == 0) {
+ return -1;
+ }
+ }
+
+ Delete(s->text);
+ s->text = NewStringWithSize(Char(s->str) + position - 1,
+ Tell(s->str) - position + 1);
+ Char(s->text)[0] = startchar;
+ Setfile(s->text, Getfile(s->str));
+ Setline(s->text, old_line);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * 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 = NULL;
+ int old_line = s->line;
+ String *old_text = Copy(s->text);
+ long position = Tell(s->str);
+
+ int num_levels = 1;
+ int starttok = 0;
+ int endtok = 0;
+ switch (endchar) {
+ case '}':
+ starttok = SWIG_TOKEN_LBRACE;
+ endtok = SWIG_TOKEN_RBRACE;
+ break;
+ case ')':
+ starttok = SWIG_TOKEN_LPAREN;
+ endtok = SWIG_TOKEN_RPAREN;
+ break;
+ case ']':
+ starttok = SWIG_TOKEN_LBRACKET;
+ endtok = SWIG_TOKEN_RBRACKET;
+ break;
+ case '>':
+ starttok = SWIG_TOKEN_LESSTHAN;
+ endtok = SWIG_TOKEN_GREATERTHAN;
+ break;
+ default:
+ assert(0);
+ }
+
+ while (1) {
+ int tok = Scanner_token(s);
+ if (tok == starttok) {
+ num_levels++;
+ } else if (tok == endtok) {
+ if (--num_levels == 0) {
+ result = NewStringWithSize(Char(s->str) + position - 1,
+ Tell(s->str) - position + 1);
+ Char(result)[0] = startchar;
+ Setfile(result, Getfile(s->str));
+ Setline(result, old_line);
+ break;
+ }
+ } else if (tok == SWIG_TOKEN_COMMENT) {
+ char *loc = Char(s->text);
+ if (strncmp(loc, "/*@SWIG", 7) == 0 && loc[Len(s->text)-3] == '@') {
+ Scanner_locator(s, s->text);
+ }
+ } else if (tok == 0) {
+ break;
+ }
+ }
+
+ /* Reset the scanner state. */
+ Seek(s->str, position, SEEK_SET);
+ Delete(s->text);
+ s->text = 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++
+ * operator.
+ * ----------------------------------------------------------------------------- */
+
+int Scanner_isoperator(int tokval) {
+ if (tokval >= 100) return 1;
+ return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * Scanner_locator()
+ *
+ * Support for locator strings. These are strings of the form
+ * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
+ * are primarily used for macro line number reporting.
+ * We just use the locator to mark when to activate/deactivate linecounting.
+ * ---------------------------------------------------------------------- */
+
+
+void Scanner_locator(Scanner *s, String *loc) {
+ static Locator *locs = 0;
+ static int expanding_macro = 0;
+
+ if (!follow_locators) {
+ if (Equal(loc, "/*@SWIG@*/")) {
+ /* End locator. */
+ if (expanding_macro)
+ --expanding_macro;
+ } else {
+ /* Begin locator. */
+ ++expanding_macro;
+ }
+ /* Freeze line number processing in Scanner */
+ freeze_line(s,expanding_macro);
+ } else {
+ int c;
+ Locator *l;
+ (void)Seek(loc, 7, SEEK_SET);
+ c = Getc(loc);
+ if (c == '@') {
+ /* Empty locator. We pop the last location off */
+ if (locs) {
+ Scanner_set_location(s, locs->filename, locs->line_number);
+ cparse_file = locs->filename;
+ cparse_line = locs->line_number;
+ l = locs->next;
+ Free(locs);
+ locs = l;
+ }
+ return;
+ }
+
+ /* We're going to push a new location */
+ l = (Locator *) Malloc(sizeof(Locator));
+ l->filename = cparse_file;
+ l->line_number = cparse_line;
+ l->next = locs;
+ locs = l;
+
+ /* Now, parse the new location out of the locator string */
+ {
+ String *fn = NewStringEmpty();
+ /* Putc(c, fn); */
+
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_file = Swig_copy_string(Char(fn));
+ Clear(fn);
+ cparse_line = 1;
+ /* Get the line number */
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_line = atoi(Char(fn));
+ Clear(fn);
+
+ /* Get the rest of it */
+ while ((c = Getc(loc)) != EOF) {
+ if (c == '@')
+ break;
+ Putc(c, fn);
+ }
+ /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */
+ Scanner_set_location(s, cparse_file, cparse_line);
+ Delete(fn);
+ }
+ }
+}
+
+void Swig_cparse_follow_locators(int v) {
+ follow_locators = v;
+}
+
+
diff --git a/contrib/tools/swig/Source/Swig/stype.c b/contrib/tools/swig/Source/Swig/stype.c
new file mode 100644
index 00000000000..b0eec2fdb92
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/stype.c
@@ -0,0 +1,1503 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * stype.c
+ *
+ * This file provides general support for datatypes that are encoded in
+ * the form of simple strings.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * The purpose of this module is to provide a general purpose type representation
+ * based on simple text strings.
+ *
+ * General idea:
+ *
+ * Types are represented by a base type (e.g., "int") and a collection of
+ * type operators applied to the base (e.g., pointers, arrays, etc...).
+ *
+ * Encoding:
+ *
+ * Types are encoded as strings of type constructors such as follows:
+ *
+ * String Encoding C Example
+ * --------------- ---------
+ * p.p.int int **
+ * a(300).a(400).int int [300][400]
+ * p.q(const).char char const *
+ *
+ * All type constructors are denoted by a trailing '.':
+ *
+ * 'p.' = Pointer (*)
+ * 'r.' = Reference (&)
+ * 'z.' = Rvalue reference (&&)
+ * 'v.' = Variadic (...)
+ * 'a(n).' = Array of size n [n]
+ * 'f(..,..).' = Function with arguments (args)
+ * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier)
+ * 'm(cls).' = Pointer to member (cls::*)
+ *
+ * The encoding follows the order that you might describe a type in words.
+ * For example "p.a(200).int" is "A pointer to array of int's" and
+ * "p.q(const).char" is "a pointer to a const char".
+ *
+ * This representation of types is fairly convenient because ordinary string
+ * operations can be used for type manipulation. For example, a type could be
+ * formed by combining two strings such as the following:
+ *
+ * "p.p." + "a(400).int" = "p.p.a(400).int"
+ *
+ * Similarly, one could strip a 'const' declaration from a type doing something
+ * like this:
+ *
+ * Replace(t,"q(const).","",DOH_REPLACE_ANY)
+ *
+ * More examples:
+ *
+ * String Encoding C++ Example
+ * --------------- -----------
+ * p.f(bool).r.q(const).long const long & (*)(bool)
+ * m(Funcs).q(const).f(bool).long long (Funcs::*)(bool) const
+ * r.q(const).m(Funcs).f(int).long long (Funcs::*const &)(int)
+ * m(Funcs).z.q(const).f(bool).long long (Funcs::*)(bool) const &&
+ *
+ * Function decl examples:
+ *
+ * f(bool). long a(bool);
+ * r.f(bool). long b(bool) &;
+ * z.f(bool). long c(bool) &&;
+ * z.q(const).f(bool). long d(bool) const &&;
+ *
+ * For the most part, this module tries to minimize the use of special
+ * characters (*, [, <, etc...) in its type encoding. One reason for this
+ * is that SWIG might be extended to encode data in formats such as XML
+ * where you might want to do this:
+ *
+ * <function>
+ * <type>p.p.int</type>
+ * ...
+ * </function>
+ *
+ * Or alternatively,
+ *
+ * <function type="p.p.int" ...>blah</function>
+ *
+ * In either case, it's probably best to avoid characters such as '&', '*', or '<'.
+ *
+ * Why not use C syntax? Well, C syntax is fairly complicated to parse
+ * and not particularly easy to manipulate---especially for adding, deleting and
+ * composing type constructors. The string representation presented here makes
+ * this pretty easy.
+ *
+ * Why not use a bunch of nested data structures? Are you kidding? How
+ * would that be easier to use than a few simple string operations?
+ * ----------------------------------------------------------------------------- */
+
+
+SwigType *NewSwigType(int t) {
+ switch (t) {
+ case T_BOOL:
+ return NewString("bool");
+ case T_UNKNOWN:
+ /* Handle like T_INT since we used to just use T_INT where we now use
+ * T_UNKNOWN.
+ */
+ case T_INT:
+ return NewString("int");
+ case T_UINT:
+ return NewString("unsigned int");
+ case T_SHORT:
+ return NewString("short");
+ case T_USHORT:
+ return NewString("unsigned short");
+ case T_LONG:
+ return NewString("long");
+ case T_ULONG:
+ return NewString("unsigned long");
+ case T_FLOAT:
+ return NewString("float");
+ case T_DOUBLE:
+ return NewString("double");
+ case T_LONGDOUBLE:
+ return NewString("long double");
+ case T_FLTCPLX:
+ return NewString("float _Complex");
+ case T_COMPLEX:
+ return NewString("_Complex");
+ case T_CHAR:
+ return NewString("char");
+ case T_SCHAR:
+ return NewString("signed char");
+ case T_UCHAR:
+ return NewString("unsigned char");
+ case T_STRING: {
+ SwigType *t = NewString("char");
+ SwigType_add_qualifier(t, "const");
+ SwigType_add_pointer(t);
+ return t;
+ }
+ case T_WCHAR:
+ return NewString("wchar_t");
+ case T_WSTRING: {
+ SwigType *t = NewString("wchar_t");
+ SwigType_add_pointer(t);
+ return t;
+ }
+ case T_LONGLONG:
+ return NewString("long long");
+ case T_ULONGLONG:
+ return NewString("unsigned long long");
+ case T_VOID:
+ return NewString("void");
+ case T_AUTO:
+ return NewString("auto");
+ default:
+ break;
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_push()
+ *
+ * Push a type constructor onto the type
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_push(SwigType *t, String *cons) {
+ if (!cons)
+ return;
+ if (!Len(cons))
+ return;
+
+ if (Len(t)) {
+ char *c = Char(cons);
+ if (c[strlen(c) - 1] != '.')
+ Insert(t, 0, ".");
+ }
+ Insert(t, 0, cons);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_ispointer_return()
+ *
+ * Testing functions for querying a raw datatype
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_ispointer_return(const SwigType *t) {
+ char *c;
+ int idx;
+ if (!t)
+ return 0;
+ c = Char(t);
+ idx = (int)strlen(c) - 4;
+ if (idx >= 0) {
+ return (strcmp(c + idx, ").p.") == 0);
+ }
+ return 0;
+}
+
+int SwigType_isreference_return(const SwigType *t) {
+ char *c;
+ int idx;
+ if (!t)
+ return 0;
+ c = Char(t);
+ idx = (int)strlen(c) - 4;
+ if (idx >= 0) {
+ return (strcmp(c + idx, ").r.") == 0);
+ }
+ return 0;
+}
+
+int SwigType_isconst(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ String *q = SwigType_parm(t);
+ if (strstr(Char(q), "const")) {
+ Delete(q);
+ return 1;
+ }
+ Delete(q);
+ }
+ /* Hmmm. Might be const through a typedef */
+ if (SwigType_issimple(t)) {
+ int ret;
+ SwigType *td = SwigType_typedef_resolve(t);
+ if (td) {
+ ret = SwigType_isconst(td);
+ Delete(td);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int SwigType_ismutable(const SwigType *t) {
+ int r;
+ SwigType *qt = SwigType_typedef_resolve_all(t);
+ if (SwigType_isreference(qt) || SwigType_isrvalue_reference(qt)) {
+ Delete(SwigType_pop(qt));
+ } else {
+ while (SwigType_isarray(qt)) {
+ Delete(SwigType_pop(qt));
+ }
+ }
+ r = SwigType_isconst(qt);
+ Delete(qt);
+ return r ? 0 : 1;
+}
+
+int SwigType_isenum(const SwigType *t) {
+ char *c = Char(t);
+ if (!t)
+ return 0;
+ if (strncmp(c, "enum ", 5) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+int SwigType_issimple(const SwigType *t) {
+ char *c = Char(t);
+ if (!t)
+ return 0;
+ while (*c) {
+ if (*c == '<') {
+ int nest = 1;
+ c++;
+ while (*c && nest) {
+ if (*c == '<')
+ nest++;
+ if (*c == '>')
+ nest--;
+ c++;
+ }
+ c--;
+ }
+ if (*c == '.')
+ return 0;
+ c++;
+ }
+ return 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_default_create()
+ *
+ * Create the default type for this datatype. This takes a type and strips it
+ * down to a generic form first by resolving all typedefs.
+ *
+ * Rules:
+ * Pointers: p.SWIGTYPE
+ * References: r.SWIGTYPE
+ * Arrays no dimension: a().SWIGTYPE
+ * Arrays with dimension: a(ANY).SWIGTYPE
+ * Member pointer: m(CLASS).SWIGTYPE
+ * Function pointer: f(ANY).SWIGTYPE
+ * Enums: enum SWIGTYPE
+ * Types: SWIGTYPE
+ *
+ * Examples (also see SwigType_default_deduce):
+ *
+ * int [2][4]
+ * a(2).a(4).int
+ * a(ANY).a(ANY).SWIGTYPE
+ *
+ * struct A {};
+ * typedef A *Aptr;
+ * Aptr const &
+ * r.q(const).Aptr
+ * r.q(const).p.SWIGTYPE
+ *
+ * enum E {e1, e2};
+ * enum E const &
+ * r.q(const).enum E
+ * r.q(const).enum SWIGTYPE
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_default_create(const SwigType *ty) {
+ SwigType *r = 0;
+ List *l;
+ Iterator it;
+ int numitems;
+
+ if (!SwigType_isvarargs(ty)) {
+ SwigType *t = SwigType_typedef_resolve_all(ty);
+ r = NewStringEmpty();
+ l = SwigType_split(t);
+ numitems = Len(l);
+
+ if (numitems >= 1) {
+ String *last_subtype = Getitem(l, numitems-1);
+ if (SwigType_isenum(last_subtype))
+ Setitem(l, numitems-1, NewString("enum SWIGTYPE"));
+ else
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ }
+
+ for (it = First(l); it.item; it = Next(it)) {
+ String *subtype = it.item;
+ if (SwigType_isarray(subtype)) {
+ if (Equal(subtype, "a()."))
+ Append(r, NewString("a()."));
+ else
+ Append(r, NewString("a(ANY)."));
+ } else if (SwigType_isfunction(subtype)) {
+ Append(r, NewString("f(ANY).SWIGTYPE"));
+ break;
+ } else if (SwigType_ismemberpointer(subtype)) {
+ Append(r, NewString("m(CLASS).SWIGTYPE"));
+ break;
+ } else {
+ Append(r, subtype);
+ }
+ }
+
+ Delete(l);
+ Delete(t);
+ }
+
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_default_deduce()
+ *
+ * This function implements type deduction used in the typemap matching rules
+ * and is very close to the type deduction used in partial template class
+ * specialization matching in that the most specialized type is always chosen.
+ * SWIGTYPE is used as the generic type. The basic idea is to repeatedly call
+ * this function to find a deduced type until nothing matches.
+ *
+ * The type t must have already been converted to the default type via a call to
+ * SwigType_default_create() before calling this function.
+ *
+ * Example deductions (matching the examples described in SwigType_default_create),
+ * where the most specialized matches are highest in the list:
+ *
+ * a(ANY).a(ANY).SWIGTYPE
+ * a(ANY).a().SWIGTYPE
+ * a(ANY).p.SWIGTYPE
+ * a(ANY).SWIGTYPE
+ * a().SWIGTYPE
+ * p.SWIGTYPE
+ * SWIGTYPE
+ *
+ * r.q(const).p.SWIGTYPE
+ * r.q(const).SWIGTYPE
+ * r.SWIGTYPE
+ * SWIGTYPE
+ *
+ * r.q(const).enum SWIGTYPE
+ * r.enum SWIGTYPE
+ * r.SWIGTYPE
+ * SWIGTYPE
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_default_deduce(const SwigType *t) {
+ SwigType *r = NewStringEmpty();
+ List *l;
+ Iterator it;
+ int numitems;
+
+ l = SwigType_split(t);
+
+ numitems = Len(l);
+ if (numitems >= 1) {
+ String *last_subtype = Getitem(l, numitems-1);
+ int is_enum = SwigType_isenum(last_subtype);
+
+ if (numitems >=2 ) {
+ String *subtype = Getitem(l, numitems-2); /* last but one */
+ if (SwigType_isarray(subtype)) {
+ if (is_enum) {
+ /* enum deduction, enum SWIGTYPE => SWIGTYPE */
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ } else {
+ /* array deduction, a(ANY). => a(). => p. */
+ String *deduced_subtype = 0;
+ if (Strcmp(subtype, "a().") == 0) {
+ deduced_subtype = NewString("p.");
+ } else if (Strcmp(subtype, "a(ANY).") == 0) {
+ deduced_subtype = NewString("a().");
+ } else {
+ assert(0);
+ }
+ Setitem(l, numitems-2, deduced_subtype);
+ }
+ } else if (SwigType_ismemberpointer(subtype)) {
+ /* member pointer deduction, m(CLASS). => p. */
+ Setitem(l, numitems-2, NewString("p."));
+ } else if (is_enum && !SwigType_isqualifier(subtype)) {
+ /* enum deduction, enum SWIGTYPE => SWIGTYPE */
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ } else {
+ /* simple type deduction, eg, r.p.p. => r.p. */
+ /* also function pointers eg, p.f(ANY). => p. */
+ Delitem(l, numitems-2);
+ }
+ } else {
+ if (is_enum) {
+ /* enum deduction, enum SWIGTYPE => SWIGTYPE */
+ Setitem(l, numitems-1, NewString("SWIGTYPE"));
+ } else {
+ /* delete the only item, we are done with deduction */
+ Delitem(l, 0);
+ }
+ }
+ } else {
+ assert(0);
+ }
+
+ for (it = First(l); it.item; it = Next(it)) {
+ Append(r, it.item);
+ }
+
+ if (Len(r) == 0) {
+ Delete(r);
+ r = 0;
+ }
+
+ Delete(l);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_namestr()
+ *
+ * Returns a string of the base type. Takes care of template expansions
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_namestr(const SwigType *t) {
+ String *r;
+ String *suffix;
+ List *p;
+ int i, sz;
+ char *d = Char(t);
+ char *c = strstr(d, "<(");
+
+ if (!c || !strstr(c + 2, ")>"))
+ return NewString(t);
+
+ r = NewStringWithSize(d, (int)(c - d));
+ if (*(c - 1) == '<')
+ Putc(' ', r);
+ Putc('<', r);
+
+ p = SwigType_parmlist(c + 1);
+ sz = Len(p);
+ for (i = 0; i < sz; i++) {
+ String *str = SwigType_str(Getitem(p, i), 0);
+ /* Avoid creating a <: token, which is the same as [ in C++ - put a space after '<'. */
+ if (i == 0 && Len(str))
+ Putc(' ', r);
+ Append(r, str);
+ if ((i + 1) < sz)
+ Putc(',', r);
+ Delete(str);
+ }
+ Putc(' ', r);
+ Putc('>', r);
+ suffix = SwigType_templatesuffix(t);
+ if (Len(suffix) > 0) {
+ String *suffix_namestr = SwigType_namestr(suffix);
+ Append(r, suffix_namestr);
+ Delete(suffix_namestr);
+ } else {
+ Append(r, suffix);
+ }
+ Delete(suffix);
+ Delete(p);
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_str()
+ *
+ * Create a C string representation of a datatype.
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
+ String *result;
+ String *element = 0;
+ String *nextelement;
+ String *forwardelement;
+ SwigType *member_function_qualifiers = 0;
+ List *elements;
+ int nelements, i;
+
+ if (id) {
+ /* Stringify the id expanding templates, for example when the id is a fully qualified class template name */
+ String *id_str = NewString(id); /* unfortunate copy due to current const limitations */
+ result = SwigType_str(id_str, 0);
+ Delete(id_str);
+ } else {
+ result = NewStringEmpty();
+ }
+
+ elements = SwigType_split(s);
+ nelements = Len(elements);
+
+ if (nelements > 0) {
+ element = Getitem(elements, 0);
+ }
+ /* Now, walk the type list and start emitting */
+ for (i = 0; i < nelements; i++) {
+ if (i < (nelements - 1)) {
+ nextelement = Getitem(elements, i + 1);
+ forwardelement = nextelement;
+ if (SwigType_isqualifier(nextelement)) {
+ if (i < (nelements - 2))
+ forwardelement = Getitem(elements, i + 2);
+ }
+ } else {
+ nextelement = 0;
+ forwardelement = 0;
+ }
+ if (SwigType_isqualifier(element)) {
+ if (!member_function_qualifiers) {
+ DOH *q = 0;
+ q = SwigType_parm(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, q);
+ Delete(q);
+ }
+ } else if (SwigType_ispointer(element)) {
+ Insert(result, 0, "*");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_ismemberpointer(element)) {
+ String *q;
+ q = SwigType_parm(element);
+ Insert(result, 0, "::*");
+ Insert(result, 0, q);
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ {
+ String *next3elements = NewStringEmpty();
+ int j;
+ for (j = i + 1; j < i + 4 && j < nelements; j++) {
+ Append(next3elements, Getitem(elements, j));
+ }
+ if (SwigType_isfunction(next3elements))
+ member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
+ Delete(next3elements);
+ }
+ Delete(q);
+ } else if (SwigType_isreference(element)) {
+ if (!member_function_qualifiers)
+ Insert(result, 0, "&");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isrvalue_reference(element)) {
+ if (!member_function_qualifiers)
+ Insert(result, 0, "&&");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isvariadic(element)) {
+ Insert(result, 0, "...");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isarray(element)) {
+ DOH *size;
+ Append(result, "[");
+ size = SwigType_parm(element);
+ Append(result, size);
+ Append(result, "]");
+ Delete(size);
+ } else if (SwigType_isfunction(element)) {
+ DOH *parms, *p;
+ int j, plen;
+ Append(result, "(");
+ parms = SwigType_parmlist(element);
+ plen = Len(parms);
+ for (j = 0; j < plen; j++) {
+ p = SwigType_str(Getitem(parms, j), 0);
+ Append(result, p);
+ if (j < (plen - 1))
+ Append(result, ",");
+ }
+ Append(result, ")");
+ if (member_function_qualifiers) {
+ String *p = SwigType_str(member_function_qualifiers, 0);
+ Append(result, " ");
+ Append(result, p);
+ Delete(p);
+ Delete(member_function_qualifiers);
+ member_function_qualifiers = 0;
+ }
+ Delete(parms);
+ } else {
+ if (strcmp(Char(element), "v(...)") == 0) {
+ Insert(result, 0, "...");
+ } else {
+ String *bs = SwigType_namestr(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, bs);
+ Delete(bs);
+ }
+ }
+ element = nextelement;
+ }
+ Delete(elements);
+ Chop(result);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_ltype(const SwigType *ty)
+ *
+ * Create a locally assignable type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_ltype(const SwigType *s) {
+ String *result;
+ String *element;
+ SwigType *td, *tc = 0;
+ List *elements;
+ int nelements, i;
+ int firstarray = 1;
+ int notypeconv = 0;
+ int ignore_member_function_qualifiers = 0;
+
+ result = NewStringEmpty();
+ tc = Copy(s);
+ /* Nuke all leading qualifiers */
+ while (SwigType_isqualifier(tc)) {
+ Delete(SwigType_pop(tc));
+ }
+ if (SwigType_issimple(tc)) {
+ /* Resolve any typedef definitions */
+ SwigType *tt = Copy(tc);
+ td = 0;
+ while ((td = SwigType_typedef_resolve(tt))) {
+ if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td) || SwigType_isrvalue_reference(td))) {
+ /* We need to use the typedef type */
+ Delete(tt);
+ break;
+ } else if (td) {
+ Delete(tt);
+ tt = td;
+ }
+ }
+ if (td) {
+ Delete(tc);
+ tc = td;
+ }
+ }
+
+ elements = SwigType_split(tc);
+ nelements = Len(elements);
+
+ /* Now, walk the type list and start emitting */
+ for (i = 0; i < nelements; i++) {
+ element = Getitem(elements, i);
+ /* when we see a function, we need to preserve the following types */
+ if (SwigType_isfunction(element)) {
+ notypeconv = 1;
+ ignore_member_function_qualifiers = 0;
+ }
+ if (ignore_member_function_qualifiers) {
+ /* cv-qualifiers and ref-qualifiers up until the f() element have already been added */
+ } else if (SwigType_isqualifier(element)) {
+ /* swallow cv-qualifiers */
+ } else if (SwigType_ispointer(element)) {
+ Append(result, element);
+ firstarray = 0;
+ } else if (SwigType_ismemberpointer(element)) {
+ Append(result, element);
+ {
+ String *next3elements = NewStringEmpty();
+ int j;
+ for (j = i + 1; j < i + 4 && j < nelements; j++) {
+ Append(next3elements, Getitem(elements, j));
+ }
+ if (SwigType_isfunction(next3elements)) {
+ SwigType *member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
+ /* compilers won't let us cast from a member function without qualifiers to one with qualifiers, so the qualifiers are kept in the ltype */
+ if (member_function_qualifiers)
+ Append(result, member_function_qualifiers);
+ Delete(member_function_qualifiers);
+ ignore_member_function_qualifiers = 1;
+ }
+ Delete(next3elements);
+ }
+ firstarray = 0;
+ } else if (SwigType_isreference(element)) {
+ if (notypeconv) {
+ Append(result, element);
+ } else {
+ Append(result, "p.");
+ }
+ firstarray = 0;
+ } else if (SwigType_isrvalue_reference(element)) {
+ if (notypeconv) {
+ Append(result, element);
+ } else {
+ Append(result, "p.");
+ }
+ firstarray = 0;
+ } else if (SwigType_isarray(element) && firstarray) {
+ if (notypeconv) {
+ Append(result, element);
+ } else {
+ Append(result, "p.");
+ }
+ firstarray = 0;
+ } else if (SwigType_isenum(element)) {
+ int anonymous_enum = (Cmp(element, "enum ") == 0);
+ if (notypeconv || !anonymous_enum) {
+ Append(result, element);
+ } else {
+ Append(result, "int");
+ }
+ } else {
+ Append(result, element);
+ }
+ }
+ Delete(elements);
+ Delete(tc);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_lstr()
+ *
+ * Produces a type-string that is suitable as a lvalue in an expression.
+ * That is, a type that can be freely assigned a value without violating
+ * any C assignment rules.
+ *
+ * - Qualifiers such as 'const' and 'volatile' are stripped.
+ * Except for member function cv-qualifiers and ref-qualifiers.
+ * - Arrays are converted into a *single* pointer (i.e.,
+ * double [][] becomes double *).
+ * - References are converted into a pointer.
+ * - Typedef names that refer to read-only types will be replaced
+ * with an equivalent assignable version.
+ * -------------------------------------------------------------------- */
+
+String *SwigType_lstr(const SwigType *s, const_String_or_char_ptr id) {
+ String *result;
+ SwigType *tc;
+
+ tc = SwigType_ltype(s);
+ result = SwigType_str(tc, id);
+ Delete(tc);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_rcaststr()
+ *
+ * Produces a casting string that maps the type returned by lstr() to the real
+ * datatype printed by str().
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
+ String *result, *cast;
+ String *element = 0;
+ String *nextelement;
+ String *forwardelement;
+ String *member_function_qualifiers = 0;
+ SwigType *td, *tc = 0;
+ const SwigType *rs;
+ List *elements;
+ int nelements, i;
+ int clear = 1;
+ int firstarray = 1;
+ int isreference = 0;
+ int isfunction = 0;
+
+ result = NewStringEmpty();
+
+ if (SwigType_isconst(s)) {
+ tc = Copy(s);
+ Delete(SwigType_pop(tc));
+ if (SwigType_ismemberpointer(tc))
+ rs = s;
+ else
+ rs = tc;
+ } else {
+ rs = s;
+ }
+
+ if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs) || SwigType_isrvalue_reference(rs))) {
+ td = 0;
+ } else {
+ td = SwigType_typedef_resolve(rs);
+ }
+
+ if (td) {
+ if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td) || SwigType_isrvalue_reference(td))) {
+ elements = SwigType_split(td);
+ } else {
+ elements = SwigType_split(rs);
+ }
+ Delete(td);
+ } else {
+ elements = SwigType_split(rs);
+ }
+ nelements = Len(elements);
+ if (nelements > 0) {
+ element = Getitem(elements, 0);
+ }
+ /* Now, walk the type list and start emitting */
+ for (i = 0; i < nelements; i++) {
+ if (i < (nelements - 1)) {
+ nextelement = Getitem(elements, i + 1);
+ forwardelement = nextelement;
+ if (SwigType_isqualifier(nextelement)) {
+ if (i < (nelements - 2))
+ forwardelement = Getitem(elements, i + 2);
+ }
+ } else {
+ nextelement = 0;
+ forwardelement = 0;
+ }
+ if (SwigType_isqualifier(element)) {
+ if (!member_function_qualifiers) {
+ DOH *q = 0;
+ q = SwigType_parm(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, q);
+ Delete(q);
+ clear = 0;
+ }
+ } else if (SwigType_ispointer(element)) {
+ Insert(result, 0, "*");
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ firstarray = 0;
+ } else if (SwigType_ismemberpointer(element)) {
+ String *q;
+ Insert(result, 0, "::*");
+ q = SwigType_parm(element);
+ Insert(result, 0, q);
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ {
+ String *next3elements = NewStringEmpty();
+ int j;
+ for (j = i + 1; j < i + 4 && j < nelements; j++) {
+ Append(next3elements, Getitem(elements, j));
+ }
+ if (SwigType_isfunction(next3elements))
+ member_function_qualifiers = SwigType_pop_function_qualifiers(next3elements);
+ Delete(next3elements);
+ }
+ firstarray = 0;
+ Delete(q);
+ } else if (SwigType_isreference(element)) {
+ if (!member_function_qualifiers) {
+ Insert(result, 0, "&");
+ if (!isfunction)
+ isreference = 1;
+ }
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ } else if (SwigType_isrvalue_reference(element)) {
+ if (!member_function_qualifiers) {
+ Insert(result, 0, "&&");
+ if (!isfunction)
+ isreference = 1;
+ }
+ if ((forwardelement) && ((SwigType_isfunction(forwardelement) || (SwigType_isarray(forwardelement))))) {
+ Insert(result, 0, "(");
+ Append(result, ")");
+ }
+ clear = 0;
+ } else if (SwigType_isarray(element)) {
+ DOH *size;
+ if (firstarray && !isreference) {
+ Append(result, "(*)");
+ firstarray = 0;
+ } else {
+ Append(result, "[");
+ size = SwigType_parm(element);
+ Append(result, size);
+ Append(result, "]");
+ Delete(size);
+ clear = 0;
+ }
+ } else if (SwigType_isfunction(element)) {
+ DOH *parms, *p;
+ int j, plen;
+ Append(result, "(");
+ parms = SwigType_parmlist(element);
+ plen = Len(parms);
+ for (j = 0; j < plen; j++) {
+ p = SwigType_str(Getitem(parms, j), 0);
+ Append(result, p);
+ Delete(p);
+ if (j < (plen - 1))
+ Append(result, ",");
+ }
+ Append(result, ")");
+ Delete(parms);
+ if (member_function_qualifiers) {
+ String *p = SwigType_str(member_function_qualifiers, 0);
+ Append(result, " ");
+ Append(result, p);
+ Delete(p);
+ Delete(member_function_qualifiers);
+ member_function_qualifiers = 0;
+ clear = 0;
+ }
+ isfunction = 1;
+ } else {
+ String *bs = SwigType_namestr(element);
+ Insert(result, 0, " ");
+ Insert(result, 0, bs);
+ Delete(bs);
+ }
+ element = nextelement;
+ }
+ Delete(elements);
+ if (clear) {
+ cast = NewStringEmpty();
+ } else {
+ cast = NewStringf("(%s)", result);
+ }
+ if (name) {
+ if (isreference) {
+ Append(cast, "*");
+ }
+ Append(cast, name);
+ }
+ Delete(result);
+ Delete(tc);
+ return cast;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_lcaststr()
+ *
+ * Casts a variable from the real type to the local datatype.
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_lcaststr(const SwigType *s, const_String_or_char_ptr name) {
+ String *result;
+
+ result = NewStringEmpty();
+
+ if (SwigType_isarray(s)) {
+ String *lstr = SwigType_lstr(s, 0);
+ Printf(result, "(%s)%s", lstr, name);
+ Delete(lstr);
+ } else if (SwigType_isreference(s)) {
+ String *str = SwigType_str(s, 0);
+ Printf(result, "(%s)", str);
+ Delete(str);
+ if (name)
+ Append(result, name);
+ } else if (SwigType_isrvalue_reference(s)) {
+ String *str = SwigType_str(s, 0);
+ Printf(result, "(%s)", str);
+ Delete(str);
+ if (name)
+ Append(result, name);
+ } else if (SwigType_isqualifier(s)) {
+ String *lstr = SwigType_lstr(s, 0);
+ Printf(result, "(%s)%s", lstr, name);
+ Delete(lstr);
+ } else {
+ if (name)
+ Append(result, name);
+ }
+ return result;
+}
+
+#if 0
+/* Alternative implementation for manglestr_default. Mangling is similar to the original
+ except for a few subtle differences for example in templates:
+ namespace foo {
+ template<class T> class bar {};
+ typedef int Integer;
+ void test2(bar<Integer *> *x);
+ }
+ Mangling is more consistent and changes from
+ _p_foo__barT_int_p_t to
+ _p_foo__barT_p_int_t.
+*/
+static void mangle_stringcopy(String *destination, const char *source, int count) {
+ while (count-- > 0) {
+ char newc = '_';
+ if (!(*source == '.' || *source == ':' || *source == ' '))
+ newc = *source;
+ /* TODO: occasionally '*' or numerics need converting to '_', eg in array dimensions and template expressions */
+ Putc(newc, destination);
+ source++;
+ }
+}
+
+static void mangle_subtype(String *mangled, SwigType *s);
+
+/* -----------------------------------------------------------------------------
+ * mangle_namestr()
+ *
+ * Mangles a type taking care of template expansions. Similar to SwigType_namestr().
+ * The type may include a trailing '.', for example "p."
+ * ----------------------------------------------------------------------------- */
+
+static void mangle_namestr(String *mangled, SwigType *t) {
+ int length = Len(t);
+ if (SwigType_isqualifier(t)) {
+ Append(mangled, "q_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_ismemberpointer(t)) {
+ Append(mangled, "m_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_isarray(t)) {
+ Append(mangled, "a_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_isfunction(t)) {
+ List *p = SwigType_parmlist(t);
+ int sz = Len(p);
+ int i;
+ Append(mangled, "f_");
+ for (i = 0; i < sz; i++) {
+ mangle_subtype(mangled, Getitem(p, i));
+ Putc('_', mangled);
+ }
+ Append(mangled, (sz > 0) ? "_" : "__");
+ } else if (SwigType_isvarargs(t)) {
+ Append(mangled, "___");
+ } else {
+ char *d = Char(t);
+ char *c = strstr(d, "<(");
+ if (!c || !strstr(c + 2, ")>")) {
+ /* not a template type */
+ mangle_stringcopy(mangled, Char(t), Len(t));
+ } else {
+ /* a template type */
+ String *suffix;
+ List *p;
+ int i, sz;
+ mangle_stringcopy(mangled, d, c-d);
+ Putc('T', mangled);
+ Putc('_', mangled);
+
+ p = SwigType_parmlist(c + 1);
+ sz = Len(p);
+ for (i = 0; i < sz; i++) {
+ mangle_subtype(mangled, Getitem(p, i));
+ Putc('_', mangled);
+ }
+ Putc('t', mangled);
+ suffix = SwigType_templatesuffix(t);
+ if (Len(suffix) > 0) {
+ mangle_namestr(mangled, suffix);
+ } else {
+ Append(mangled, suffix);
+ }
+ Delete(suffix);
+ Delete(p);
+ }
+ }
+}
+
+static void mangle_subtype(String *mangled, SwigType *s) {
+ List *elements;
+ int nelements, i;
+
+ assert(s);
+ elements = SwigType_split(s);
+ nelements = Len(elements);
+ for (i = 0; i < nelements; i++) {
+ SwigType *element = Getitem(elements, i);
+ mangle_namestr(mangled, element);
+ }
+ Delete(elements);
+}
+
+static String *manglestr_default(const SwigType *s) {
+ String *mangled = NewString("_");
+ SwigType *sr = SwigType_typedef_resolve_all(s);
+ SwigType *sq = SwigType_typedef_qualified(sr);
+ SwigType *ss = SwigType_remove_global_scope_prefix(sq);
+ SwigType *type = ss;
+ SwigType *lt;
+
+ if (SwigType_istemplate(ss)) {
+ SwigType *ty = Swig_symbol_template_deftype(ss, 0);
+ Delete(ss);
+ ss = ty;
+ type = ss;
+ }
+
+ lt = SwigType_ltype(type);
+
+ Replace(lt, "struct ", "", DOH_REPLACE_ANY);
+ Replace(lt, "class ", "", DOH_REPLACE_ANY);
+ Replace(lt, "union ", "", DOH_REPLACE_ANY);
+ Replace(lt, "enum ", "", DOH_REPLACE_ANY);
+
+ mangle_subtype(mangled, lt);
+
+ Delete(ss);
+ Delete(sq);
+ Delete(sr);
+
+ return mangled;
+}
+
+#else
+
+static String *manglestr_default(const SwigType *s) {
+ char *c;
+ String *result = 0;
+ String *base = 0;
+ SwigType *lt;
+ SwigType *sr = SwigType_typedef_resolve_all(s);
+ SwigType *sq = SwigType_typedef_qualified(sr);
+ SwigType *ss = SwigType_remove_global_scope_prefix(sq);
+ SwigType *type = ss;
+
+ if (SwigType_istemplate(ss)) {
+ SwigType *dt = Swig_symbol_template_deftype(ss, 0);
+ String *ty = Swig_symbol_type_qualify(dt, 0);
+ Delete(dt);
+ Delete(ss);
+ ss = ty;
+ type = ss;
+ }
+
+ lt = SwigType_ltype(type);
+ result = SwigType_prefix(lt);
+ base = SwigType_base(lt);
+
+ c = Char(result);
+ while (*c) {
+ if (!isalnum((int) *c))
+ *c = '_';
+ c++;
+ }
+ if (SwigType_istemplate(base)) {
+ String *b = SwigType_namestr(base);
+ Delete(base);
+ base = b;
+ }
+
+ Replace(base, "struct ", "", DOH_REPLACE_ANY); /* This might be problematic */
+ Replace(base, "class ", "", DOH_REPLACE_ANY);
+ Replace(base, "union ", "", DOH_REPLACE_ANY);
+ Replace(base, "enum ", "", DOH_REPLACE_ANY);
+
+ c = Char(base);
+ while (*c) {
+ if (*c == '<')
+ *c = 'T';
+ else if (*c == '>')
+ *c = 't';
+ else if (*c == '*')
+ *c = 'p';
+ else if (*c == '[')
+ *c = 'a';
+ else if (*c == ']')
+ *c = 'A';
+ else if (*c == '&')
+ *c = 'R';
+ else if (*c == '(')
+ *c = 'f';
+ else if (*c == ')')
+ *c = 'F';
+ else if (!isalnum((int) *c))
+ *c = '_';
+ c++;
+ }
+ Append(result, base);
+ Insert(result, 0, "_");
+ Delete(lt);
+ Delete(base);
+ Delete(ss);
+ Delete(sq);
+ Delete(sr);
+ return result;
+}
+#endif
+
+String *SwigType_manglestr(const SwigType *s) {
+#if 0
+ /* Debugging checks to ensure a proper SwigType is passed in and not a stringified type */
+ String *angle = Strchr(s, '<');
+ if (angle && Strncmp(angle, "<(", 2) != 0)
+ Printf(stderr, "SwigType_manglestr error: %s\n", s);
+ else if (Strchr(s, '*') || Strchr(s, '&') || Strchr(s, '['))
+ Printf(stderr, "SwigType_manglestr error: %s\n", s);
+#endif
+ return manglestr_default(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typename_replace()
+ *
+ * Replaces a typename in a type with something else. Needed for templates.
+ * Collapses duplicate const into a single const.
+ * Reference collapsing probably should be implemented here.
+ * Example:
+ * t=r.q(const).T pat=T rep=int => r.q(const).int
+ * t=r.q(const).T pat=T rep=q(const).int => r.q(const).int (duplicate const removed)
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
+ String *nt;
+ int i, ilen;
+ List *elem;
+
+ if (!Strstr(t, pat))
+ return;
+
+ if (Equal(t, pat)) {
+ Replace(t, pat, rep, DOH_REPLACE_ANY);
+ return;
+ }
+ nt = NewStringEmpty();
+ elem = SwigType_split(t);
+ ilen = Len(elem);
+ for (i = 0; i < ilen; i++) {
+ String *e = Getitem(elem, i);
+ if (SwigType_issimple(e)) {
+ if (Equal(e, pat)) {
+ /* Replaces a type of the form 'pat' with 'rep<args>' */
+ if (SwigType_isconst(rep) && i > 0 && SwigType_isconst(Getitem(elem, i - 1))) {
+ /* Collapse duplicate const into a single const */
+ SwigType *rep_without_const = Copy(rep);
+ Delete(SwigType_pop(rep_without_const));
+ Replace(e, pat, rep_without_const, DOH_REPLACE_ANY);
+ Delete(rep_without_const);
+ } else {
+ Replace(e, pat, rep, DOH_REPLACE_ANY);
+ }
+ } else if (SwigType_istemplate(e)) {
+ /* Replaces a type of the form 'pat<args>' with 'rep' */
+ {
+ /* To match "e=TemplateTemplateT<(float)>"
+ * with "pat=TemplateTemplateT"
+ * we need to compare only the first part of the string e.
+ */
+ int len = Len(pat);
+
+ /* Len(e) > len, not >= (because we expect at least a
+ * character '<' following the template typename)
+ */
+ if (Len(e) > len) {
+ String *firstPartOfType = NewStringWithSize(e, len);
+ const char* e_as_char = Char(e);
+
+ if (Equal(firstPartOfType, pat) && e_as_char[len] == '<') {
+ String *repbase = SwigType_templateprefix(rep);
+ Replace(e, pat, repbase, DOH_REPLACE_ID | DOH_REPLACE_FIRST);
+ Delete(repbase);
+ }
+ Delete(firstPartOfType);
+ }
+ }
+
+ {
+ String *tsuffix;
+ List *tparms = SwigType_parmlist(e);
+ int j, jlen;
+ String *nt = SwigType_templateprefix(e);
+ Append(nt, "<(");
+ jlen = Len(tparms);
+ for (j = 0; j < jlen; j++) {
+ SwigType_typename_replace(Getitem(tparms, j), pat, rep);
+ Append(nt, Getitem(tparms, j));
+ if (j < (jlen - 1))
+ Putc(',', nt);
+ }
+ tsuffix = SwigType_templatesuffix(e);
+ SwigType_typename_replace(tsuffix, pat, rep);
+ Printf(nt, ")>%s", tsuffix);
+ Delete(tsuffix);
+ Clear(e);
+ Append(e, nt);
+ Delete(nt);
+ Delete(tparms);
+ }
+ } else if (Swig_scopename_check(e)) {
+ String *first = 0;
+ String *rest = 0;
+ Swig_scopename_split(e, &first, &rest);
+
+ /* Swig_scopename_split doesn't handle :: prefix very well ... could do with a rework */
+ if (Strncmp(rest, "::", 2) == 0) {
+ String *tmp = NewString(Char(rest) + 2);
+ Clear(rest);
+ Printv(rest, tmp, NIL);
+ Delete(tmp);
+ assert(!first);
+ }
+
+ Clear(e);
+ if (first)
+ SwigType_typename_replace(first, pat, rep);
+ SwigType_typename_replace(rest, pat, rep);
+ Printv(e, first ? first : "", "::", rest, NIL);
+ Delete(first);
+ Delete(rest);
+ }
+ } else if (SwigType_isfunction(e)) {
+ int j, jlen;
+ List *fparms = SwigType_parmlist(e);
+ Clear(e);
+ Append(e, "f(");
+ jlen = Len(fparms);
+ for (j = 0; j < jlen; j++) {
+ SwigType_typename_replace(Getitem(fparms, j), pat, rep);
+ Append(e, Getitem(fparms, j));
+ if (j < (jlen - 1))
+ Putc(',', e);
+ }
+ Append(e, ").");
+ Delete(fparms);
+ } else if (SwigType_isarray(e)) {
+ Replace(e, pat, rep, DOH_REPLACE_ID);
+ }
+ Append(nt, e);
+ }
+ Clear(t);
+ Append(t, nt);
+ Delete(nt);
+ Delete(elem);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_variadic_replace()
+ *
+ * Replaces variadic parameter with a list of (zero or more) parameters.
+ * Needed for variadic templates.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_variadic_replace(SwigType *t, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms) {
+ String *nt;
+ int i, ilen;
+ List *elem;
+ if (!unexpanded_variadic_parm)
+ return;
+
+ if (SwigType_isvariadic(t)) {
+ /* Based on expand_variadic_parms() but input is single SwigType (t) instead of ParmList */
+ String *unexpanded_name = Getattr(unexpanded_variadic_parm, "name");
+ ParmList *expanded = CopyParmList(expanded_variadic_parms);
+ Parm *ep = expanded;
+ SwigType *fparms;
+ while (ep) {
+ SwigType *newtype = Copy(t);
+ SwigType_del_variadic(newtype);
+ Replaceid(newtype, unexpanded_name, Getattr(ep, "type"));
+ Setattr(ep, "type", newtype);
+ ep = nextSibling(ep);
+ }
+ Clear(t);
+ fparms = SwigType_function_parms_only(expanded);
+ Append(t, fparms);
+ Delete(expanded);
+
+ return;
+ }
+ nt = NewStringEmpty();
+ elem = SwigType_split(t);
+ ilen = Len(elem);
+ for (i = 0; i < ilen; i++) {
+ String *e = Getitem(elem, i);
+ if (SwigType_isfunction(e)) {
+ int j, jlen;
+ List *fparms = SwigType_parmlist(e);
+ Clear(e);
+ Append(e, "f(");
+ jlen = Len(fparms);
+ for (j = 0; j < jlen; j++) {
+ SwigType *type = Getitem(fparms, j);
+ SwigType_variadic_replace(type, unexpanded_variadic_parm, expanded_variadic_parms);
+ if (Len(type) > 0) {
+ if (j != 0)
+ Putc(',', e);
+ Append(e, type);
+ } else {
+ assert(j == jlen - 1); /* A variadic parm was replaced with zero parms, variadic parms are only changed at the end of the list */
+ }
+ }
+ Append(e, ").");
+ Delete(fparms);
+ }
+ Append(nt, e);
+ }
+ Clear(t);
+ Append(t, nt);
+ Delete(nt);
+ Delete(elem);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_remove_global_scope_prefix()
+ *
+ * Removes the unary scope operator (::) prefix indicating global scope in all
+ * components of the type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_remove_global_scope_prefix(const SwigType *t) {
+ SwigType *result;
+ const char *type = Char(t);
+ if (strncmp(type, "::", 2) == 0)
+ type += 2;
+ result = NewString(type);
+ Replaceall(result, ".::", ".");
+ Replaceall(result, "(::", "(");
+ Replaceall(result, "enum ::", "enum ");
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_check_decl()
+ *
+ * Checks type declarators for a match
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_check_decl(const SwigType *ty, const SwigType *decl) {
+ SwigType *t, *t1, *t2;
+ int r;
+ t = SwigType_typedef_resolve_all(ty);
+ t1 = SwigType_strip_qualifiers(t);
+ t2 = SwigType_prefix(t1);
+ r = Equal(t2, decl);
+ Delete(t);
+ Delete(t1);
+ Delete(t2);
+ return r == 1;
+}
diff --git a/contrib/tools/swig/Source/Swig/swig.h b/contrib/tools/swig/Source/Swig/swig.h
new file mode 100644
index 00000000000..8156ce454bc
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swig.h
@@ -0,0 +1,456 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swig.h
+ *
+ * Header file for the SWIG core.
+ * ----------------------------------------------------------------------------- */
+
+#ifndef SWIG_SWIG_H
+#define SWIG_SWIG_H
+
+#include "swigconfig.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "doh.h"
+
+/* Status codes */
+
+#define SWIG_OK 1
+#define SWIG_ERROR 0
+#define SWIG_NOWRAP 0
+
+/* Global macros */
+#define NSPACE_SEPARATOR "." /* Namespace separator for the nspace feature - this should be changed to a target language configurable variable */
+#define NSPACE_TODO 0 /* Languages that still need to implement and test the nspace feature use this */
+
+/* Short names for common data types */
+
+ typedef DOH String;
+ typedef DOH Hash;
+ typedef DOH List;
+ typedef DOH String_or_char;
+ typedef DOH File;
+ typedef DOH Parm;
+ typedef DOH ParmList;
+ typedef DOH Node;
+ typedef DOH Symtab;
+ typedef DOH Typetab;
+ typedef DOH SwigType;
+
+/* --- Legacy DataType interface. These type codes are provided solely
+ for backwards compatibility with older modules --- */
+
+/* --- The ordering of type values is used to determine type-promotion
+ in the parser. Do not change */
+
+/* Numeric types */
+
+#define T_BOOL 1
+#define T_SCHAR 2
+#define T_UCHAR 3
+#define T_SHORT 4
+#define T_USHORT 5
+#define T_INT 7
+#define T_UINT 8
+#define T_LONG 9
+#define T_ULONG 10
+#define T_LONGLONG 11
+#define T_ULONGLONG 12
+#define T_FLOAT 20
+#define T_DOUBLE 21
+#define T_LONGDOUBLE 22
+#define T_FLTCPLX 23
+#define T_DBLCPLX 24
+#define T_AUTO 26
+
+#define T_COMPLEX T_DBLCPLX
+
+/* non-numeric */
+
+#define T_CHAR 29
+#define T_WCHAR 30
+#define T_USER 31
+#define T_VOID 32
+#define T_STRING 33
+#define T_POINTER 34
+#define T_REFERENCE 35
+#define T_ARRAY 36
+#define T_FUNCTION 37
+#define T_MPOINTER 38
+#define T_VARARGS 39
+#define T_RVALUE_REFERENCE 40
+#define T_WSTRING 41
+#define T_UNKNOWN 42
+
+/* --- File interface --- */
+
+#include "swigfile.h"
+
+/* --- Command line parsing --- */
+
+#include "swigopt.h"
+
+/* --- Scanner Interface --- */
+
+#include "swigscan.h"
+
+/* --- Functions for manipulating the string-based type encoding --- */
+
+ extern SwigType *NewSwigType(int typecode);
+ extern SwigType *SwigType_del_element(SwigType *t);
+ extern SwigType *SwigType_add_pointer(SwigType *t);
+ extern SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr qual);
+ extern SwigType *SwigType_del_memberpointer(SwigType *t);
+ extern SwigType *SwigType_del_pointer(SwigType *t);
+ extern SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size);
+ extern SwigType *SwigType_del_array(SwigType *t);
+ extern SwigType *SwigType_pop_arrays(SwigType *t);
+ extern SwigType *SwigType_add_reference(SwigType *t);
+ extern SwigType *SwigType_del_reference(SwigType *t);
+ extern SwigType *SwigType_add_rvalue_reference(SwigType *t);
+ extern SwigType *SwigType_del_rvalue_reference(SwigType *t);
+ extern SwigType *SwigType_add_variadic(SwigType *t);
+ extern SwigType *SwigType_del_variadic(SwigType *t);
+ extern SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual);
+ extern SwigType *SwigType_del_qualifier(SwigType *t);
+ extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms);
+ extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms);
+ extern SwigType *SwigType_pop_function(SwigType *t);
+ extern SwigType *SwigType_pop_function_qualifiers(SwigType *t);
+ extern SwigType *SwigType_function_parms_only(ParmList *parms);
+ extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node);
+ extern List *SwigType_split(const SwigType *t);
+ extern String *SwigType_pop(SwigType *t);
+ extern void SwigType_push(SwigType *t, String *s);
+ extern SwigType *SwigType_last(SwigType *t);
+ extern List *SwigType_parmlist(const SwigType *p);
+ extern String *SwigType_parm(const SwigType *p);
+ extern String *SwigType_str(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_lstr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_lcaststr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_manglestr(const SwigType *t);
+ extern SwigType *SwigType_ltype(const SwigType *t);
+ extern int SwigType_ispointer(const SwigType *t);
+ extern int SwigType_ispointer_return(const SwigType *t);
+ extern int SwigType_isfunctionpointer(const SwigType *t);
+ extern int SwigType_ismemberpointer(const SwigType *t);
+ extern int SwigType_isreference(const SwigType *t);
+ extern int SwigType_isreference_return(const SwigType *t);
+ extern int SwigType_isrvalue_reference(const SwigType *t);
+ extern int SwigType_isvariadic(const SwigType *t);
+ extern int SwigType_isarray(const SwigType *t);
+ extern int SwigType_prefix_is_simple_1D_array(const SwigType *t);
+ extern int SwigType_isfunction(const SwigType *t);
+ extern int SwigType_isqualifier(const SwigType *t);
+ extern int SwigType_isconst(const SwigType *t);
+ extern int SwigType_issimple(const SwigType *t);
+ extern int SwigType_ismutable(const SwigType *t);
+ extern int SwigType_isvarargs(const SwigType *t);
+ extern int SwigType_istemplate(const SwigType *t);
+ extern int SwigType_isenum(const SwigType *t);
+ extern int SwigType_check_decl(const SwigType *t, const_String_or_char_ptr decl);
+ extern SwigType *SwigType_strip_qualifiers(const SwigType *t);
+ extern SwigType *SwigType_strip_single_qualifier(const SwigType *t);
+ extern SwigType *SwigType_functionpointer_decompose(SwigType *t);
+ extern String *SwigType_base(const SwigType *t);
+ extern String *SwigType_namestr(const SwigType *t);
+ extern String *SwigType_templateprefix(const SwigType *t);
+ extern String *SwigType_templatesuffix(const SwigType *t);
+ extern String *SwigType_istemplate_templateprefix(const SwigType *t);
+ extern String *SwigType_istemplate_only_templateprefix(const SwigType *t);
+ extern String *SwigType_templateargs(const SwigType *t);
+ extern String *SwigType_prefix(const SwigType *t);
+ extern int SwigType_array_ndim(const SwigType *t);
+ extern String *SwigType_array_getdim(const SwigType *t, int n);
+ extern void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep);
+ extern SwigType *SwigType_array_type(const SwigType *t);
+ extern SwigType *SwigType_default_create(const SwigType *ty);
+ extern SwigType *SwigType_default_deduce(const SwigType *t);
+ extern void SwigType_typename_replace(SwigType *t, String *pat, String *rep);
+ extern void SwigType_variadic_replace(SwigType *t, Parm *unexpanded_variadic_parm, ParmList *expanded_variadic_parms);
+ extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t);
+ extern SwigType *SwigType_alttype(const SwigType *t, int ltmap);
+
+/* --- Type-system management --- */
+ extern void SwigType_typesystem_init(void);
+ extern int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name);
+ extern int SwigType_typedef_class(const_String_or_char_ptr name);
+ extern int SwigType_typedef_using(const_String_or_char_ptr qname);
+ extern void SwigType_inherit(String *subclass, String *baseclass, String *cast, String *conversioncode);
+ extern int SwigType_issubtype(const SwigType *subtype, const SwigType *basetype);
+ extern void SwigType_scope_alias(String *aliasname, Typetab *t);
+ extern void SwigType_using_scope(Typetab *t);
+ extern void SwigType_new_scope(const_String_or_char_ptr name);
+ extern void SwigType_inherit_scope(Typetab *scope);
+ extern Typetab *SwigType_pop_scope(void);
+ extern Typetab *SwigType_set_scope(Typetab *h);
+ extern void SwigType_print_scope(void);
+ extern SwigType *SwigType_typedef_resolve(const SwigType *t);
+ extern SwigType *SwigType_typedef_resolve_all(const SwigType *t);
+ extern SwigType *SwigType_typedef_qualified(const SwigType *t);
+ extern int SwigType_istypedef(const SwigType *t);
+ extern int SwigType_isclass(const SwigType *t);
+ extern void SwigType_attach_symtab(Symtab *syms);
+ extern void SwigType_remember(const SwigType *t);
+ extern void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata);
+ extern void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata);
+ extern void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *);
+ extern void SwigType_emit_type_table(File *f_headers, File *f_table);
+ extern int SwigType_type(const SwigType *t);
+
+/* --- Symbol table module --- */
+
+ extern void Swig_symbol_print_tables(Symtab *symtab);
+ extern void Swig_symbol_print_tables_summary(void);
+ extern void Swig_symbol_print_symbols(void);
+ extern void Swig_symbol_print_csymbols(void);
+ extern void Swig_symbol_init(void);
+ extern void Swig_symbol_setscopename(const_String_or_char_ptr name);
+ extern String *Swig_symbol_getscopename(void);
+ extern String *Swig_symbol_qualifiedscopename(Symtab *symtab);
+ extern String *Swig_symbol_qualified_language_scopename(Symtab *symtab);
+ extern Symtab *Swig_symbol_newscope(void);
+ extern Symtab *Swig_symbol_setscope(Symtab *);
+ extern Symtab *Swig_symbol_getscope(const_String_or_char_ptr symname);
+ extern Symtab *Swig_symbol_global_scope(void);
+ extern Symtab *Swig_symbol_current(void);
+ extern Symtab *Swig_symbol_popscope(void);
+ extern Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n);
+ extern void Swig_symbol_conflict_warn(Node *n, Node *c, const String *symname, int inclass);
+ extern void Swig_symbol_cadd(const_String_or_char_ptr symname, Node *n);
+ extern Node *Swig_symbol_clookup(const_String_or_char_ptr symname, Symtab *tab);
+ extern Node *Swig_symbol_clookup_check(const_String_or_char_ptr symname, Symtab *tab, Node *(*checkfunc) (Node *));
+ extern Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n);
+ extern Symtab *Swig_symbol_cscope(const_String_or_char_ptr symname, Symtab *tab);
+ extern Node *Swig_symbol_clookup_local(const_String_or_char_ptr symname, Symtab *tab);
+ extern Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr symname, Symtab *tab, Node *(*checkfunc) (Node *));
+ extern String *Swig_symbol_qualified(Node *n);
+ extern Node *Swig_symbol_isoverloaded(Node *n);
+ extern void Swig_symbol_remove(Node *n);
+ extern void Swig_symbol_fix_overname(Node *n);
+ extern void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *tab);
+ extern void Swig_symbol_inherit(Symtab *tab);
+ extern SwigType *Swig_symbol_type_qualify(const SwigType *ty, Symtab *tab);
+ extern String *Swig_symbol_string_qualify(String *s, Symtab *tab);
+ extern SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab);
+
+ extern ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl);
+ extern SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope);
+ extern SwigType *Swig_symbol_template_param_eval(const SwigType *p, Symtab *symtab);
+ extern int Swig_symbol_isvalid(const String *s);
+
+/* --- Parameters and Parameter Lists --- */
+
+#include "swigparm.h"
+
+extern String *ParmList_errorstr(ParmList *);
+extern int ParmList_is_compactdefargs(ParmList *p);
+
+/* --- Parse tree support --- */
+
+#include "swigtree.h"
+
+/* -- Wrapper function Object */
+
+#include "swigwrap.h"
+
+/* --- Naming functions --- */
+
+ extern void Swig_name_register(const_String_or_char_ptr method, const_String_or_char_ptr format);
+ extern void Swig_name_unregister(const_String_or_char_ptr method);
+ extern String *Swig_name_type(const_String_or_char_ptr tname);
+ extern String *Swig_name_mangle_string(const String *s);
+ extern String *Swig_name_mangle_type(const SwigType *s);
+ extern String *Swig_name_wrapper(const_String_or_char_ptr fname);
+ extern String *Swig_name_member(const_String_or_char_ptr nspace, const_String_or_char_ptr classname, const_String_or_char_ptr membername);
+ extern String *Swig_name_get(const_String_or_char_ptr nspace, const_String_or_char_ptr vname);
+ extern String *Swig_name_set(const_String_or_char_ptr nspace, const_String_or_char_ptr vname);
+ extern String *Swig_name_construct(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+ extern String *Swig_name_copyconstructor(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+ extern String *Swig_name_destroy(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+ extern String *Swig_name_disown(const_String_or_char_ptr nspace, const_String_or_char_ptr classname);
+
+ extern void Swig_naming_init(void);
+ extern void Swig_name_namewarn_add(String *prefix, String *name, SwigType *decl, Hash *namewrn);
+ 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_redefined_warn(Node *a, Node *b, int InClass);
+
+ extern String *Swig_name_make(Node *n, String *prefix, const_String_or_char_ptr cname, SwigType *decl, String *oldname);
+ extern String *Swig_name_warning(Node *n, String *prefix, String *name, SwigType *decl);
+ extern String *Swig_name_str(Node *n);
+ extern String *Swig_name_decl(Node *n);
+ extern String *Swig_name_fulldecl(Node *n);
+
+/* --- parameterized rename functions --- */
+
+ extern void Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object);
+ 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, const_String_or_char_ptr value, Hash *featureattribs);
+
+/* --- Misc --- */
+ extern char *Swig_copy_string(const char *c);
+ extern void Swig_set_fakeversion(const char *version);
+ extern const char *Swig_package_version(void);
+ extern String *Swig_package_version_hex(void);
+ extern void Swig_obligatory_macros(String *f_runtime, const char *language);
+ extern void Swig_banner(File *f);
+ extern void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar);
+ extern String *Swig_strip_c_comments(const String *s);
+ extern String *Swig_new_subdirectory(String *basedirectory, String *subdirectory);
+ extern void Swig_filename_correct(String *filename);
+ extern String *Swig_filename_escape(String *filename);
+ extern String *Swig_filename_escape_space(String *filename);
+ extern void Swig_filename_unescape(String *filename);
+ extern int Swig_storage_isextern(Node *n);
+ extern int Swig_storage_isexternc(Node *n);
+ extern int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage);
+ extern int Swig_storage_isstatic(Node *n);
+ extern String *Swig_string_escape(String *s);
+ extern void Swig_scopename_split(const String *s, String **prefix, String **last);
+ extern String *Swig_scopename_prefix(const String *s);
+ extern String *Swig_scopename_last(const String *s);
+ extern String *Swig_scopename_first(const String *s);
+ extern String *Swig_scopename_suffix(const String *s);
+ extern List *Swig_scopename_tolist(const String *s);
+ extern int Swig_scopename_check(const String *s);
+ extern int Swig_scopename_isvalid(const String *s);
+ 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);
+ extern int Swig_is_generated_overload(Node *n);
+ extern Node *Swig_item_in_list(List *list, const DOH *item);
+
+ typedef enum { EMF_STANDARD, EMF_MICROSOFT } ErrorMessageFormat;
+
+ extern void Swig_warning(int num, const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern int Swig_error_count(void);
+ extern void Swig_error_silent(int s);
+ extern void Swig_warnfilter(const_String_or_char_ptr wlist, int val);
+ extern void Swig_warnall(void);
+ extern int Swig_warn_count(void);
+ extern void Swig_error_msg_format(ErrorMessageFormat format);
+ extern void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern String *Swig_stringify_with_location(DOH *object);
+
+/* --- C Wrappers --- */
+ extern void Swig_cresult_name_set(const char *new_name);
+ extern const char *Swig_cresult_name(void);
+ extern String *Swig_cparm_name(Parm *p, int i);
+ extern String *Swig_wrapped_var_type(SwigType *t, int varcref);
+ extern int Swig_cargs(Wrapper *w, ParmList *l);
+ extern String *Swig_cresult(SwigType *t, const_String_or_char_ptr name, const_String_or_char_ptr decl);
+
+ extern String *Swig_cfunction_call(const_String_or_char_ptr name, ParmList *parms);
+ extern String *Swig_cconstructor_call(const_String_or_char_ptr name);
+ extern String *Swig_cppconstructor_call(const_String_or_char_ptr name, ParmList *parms);
+ extern String *Swig_unref_call(Node *n);
+ extern String *Swig_ref_call(Node *n, const String *lname);
+ extern String *Swig_cdestructor_call(Node *n);
+ extern String *Swig_cppdestructor_call(Node *n);
+ extern String *Swig_cmemberset_call(const_String_or_char_ptr name, SwigType *type, String *self, int varcref);
+ extern String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String *self, int varcref);
+
+ extern int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self);
+ extern void Swig_replace_special_variables(Node *n, Node *parentnode, String *code);
+
+/* --- Transformations --- */
+
+ extern int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director);
+ extern int Swig_ConstructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, String *none_comparison, String *director_ctor, int cplus, int flags, String *directorname);
+ extern int Swig_DestructorToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int cplus, int flags);
+ extern int Swig_MembersetToFunction(Node *n, String *classname, int flags);
+ extern int Swig_MembergetToFunction(Node *n, String *classname, int flags);
+ extern int Swig_VargetToFunction(Node *n, int flags);
+ extern int Swig_VarsetToFunction(Node *n, int flags);
+
+#define CWRAP_EXTEND 0x01
+#define CWRAP_SMART_POINTER 0x02
+#define CWRAP_NATURAL_VAR 0x04
+#define CWRAP_DIRECTOR_ONE_CALL 0x08
+#define CWRAP_DIRECTOR_TWO_CALLS 0x10
+#define CWRAP_ALL_PROTECTED_ACCESS 0x20
+#define CWRAP_SMART_POINTER_OVERLOAD 0x40
+
+/* --- Director Helpers --- */
+ extern Node *Swig_methodclass(Node *n);
+ extern int Swig_directorclass(Node *n);
+ extern Node *Swig_directormap(Node *n, String *type);
+
+/* --- Legacy Typemap API (somewhat simplified, ha!) --- */
+
+ extern void Swig_typemap_init(void);
+ extern void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *pattern, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs);
+ extern int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcpattern, ParmList *pattern);
+ extern void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *pattern);
+ extern int Swig_typemap_apply(ParmList *srcpat, ParmList *destpat);
+ extern void Swig_typemap_clear_apply(ParmList *pattern);
+ extern void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node);
+ extern void Swig_typemap_debug(void);
+ extern void Swig_typemap_search_debug_set(void);
+ extern void Swig_typemap_used_debug_set(void);
+ extern void Swig_typemap_register_debug_set(void);
+
+ extern String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f);
+ extern String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *n, const_String_or_char_ptr lname, Wrapper *f, String *actioncode);
+
+ extern void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f);
+
+/* --- Code fragment support --- */
+
+ extern void Swig_fragment_register(Node *fragment);
+ extern void Swig_fragment_emit(String *name);
+ extern void Swig_fragment_clear(String *section);
+
+/* --- Extension support --- */
+
+ extern Hash *Swig_extend_hash(void);
+ extern void Swig_extend_merge(Node *cls, Node *am);
+ extern void Swig_extend_append_previous(Node *cls, Node *am);
+ extern void Swig_extend_unused_check(void);
+
+/* hacks defined in C++ ! */
+ extern int Swig_director_mode(void);
+ extern int Swig_director_protected_mode(void);
+ extern int Swig_all_protected_mode(void);
+ extern void Wrapper_director_mode_set(int);
+ extern void Wrapper_director_protected_mode_set(int);
+ extern void Wrapper_all_protected_mode_set(int);
+ extern void Language_replace_special_variables(String *method, String *tm, Parm *parm);
+ extern void Swig_print(DOH *object, int count);
+ extern void Swig_print_with_location(DOH *object, int count);
+
+/* -- template init -- */
+ extern void SwigType_template_init(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/contrib/tools/swig/Source/Swig/swigfile.h b/contrib/tools/swig/Source/Swig/swigfile.h
new file mode 100644
index 00000000000..009599a112e
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigfile.h
@@ -0,0 +1,41 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigfile.h
+ *
+ * File handling functions in the SWIG core
+ * ----------------------------------------------------------------------------- */
+
+extern List *Swig_add_directory(const_String_or_char_ptr dirname);
+extern void Swig_push_directory(const_String_or_char_ptr dirname);
+extern void Swig_pop_directory(void);
+extern String *Swig_last_file(void);
+extern List *Swig_search_path(void);
+extern FILE *Swig_include_open(const_String_or_char_ptr name);
+extern FILE *Swig_open(const_String_or_char_ptr name);
+extern String *Swig_read_file(FILE *f);
+extern String *Swig_include(const_String_or_char_ptr name);
+extern String *Swig_include_sys(const_String_or_char_ptr name);
+extern int Swig_insert_file(const_String_or_char_ptr name, File *outfile);
+extern void Swig_set_push_dir(int dopush);
+extern int Swig_get_push_dir(void);
+extern void Swig_register_filebyname(const_String_or_char_ptr filename, File *outfile);
+extern File *Swig_filebyname(const_String_or_char_ptr filename);
+extern String *Swig_file_extension(const_String_or_char_ptr filename);
+extern String *Swig_file_basename(const_String_or_char_ptr filename);
+extern String *Swig_file_filename(const_String_or_char_ptr filename);
+extern String *Swig_file_dirname(const_String_or_char_ptr filename);
+extern void Swig_file_debug_set(void);
+
+/* Delimiter used in accessing files and directories */
+
+#if defined(_WIN32)
+# define SWIG_FILE_DELIMITER "\\"
+#else
+# define SWIG_FILE_DELIMITER "/"
+#endif
diff --git a/contrib/tools/swig/Source/Swig/swigopt.h b/contrib/tools/swig/Source/Swig/swigopt.h
new file mode 100644
index 00000000000..86a477b8f76
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigopt.h
@@ -0,0 +1,18 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigopt.h
+ *
+ * Header file for the SWIG command line processing functions
+ * ----------------------------------------------------------------------------- */
+
+ extern void Swig_init_args(int argc, char **argv);
+ extern void Swig_mark_arg(int n);
+ extern int Swig_check_marked(int n);
+ extern void Swig_check_options(int check_input);
+ extern void Swig_arg_error(void);
diff --git a/contrib/tools/swig/Source/Swig/swigparm.h b/contrib/tools/swig/Source/Swig/swigparm.h
new file mode 100644
index 00000000000..2d4cfb89d5c
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigparm.h
@@ -0,0 +1,40 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigparm.h
+ *
+ * Functions related to the handling of function/method parameters and
+ * parameter lists.
+ * ----------------------------------------------------------------------------- */
+
+/* Individual parameters */
+extern Parm *NewParm(SwigType *type, const_String_or_char_ptr name, Node *from_node);
+extern Parm *NewParmWithoutFileLineInfo(SwigType *type, const_String_or_char_ptr name);
+extern Parm *NewParmNode(SwigType *type, Node *from_node);
+extern Parm *CopyParm(Parm *p);
+
+/* Parameter lists */
+extern ParmList *CopyParmList(ParmList *p);
+extern ParmList *CopyParmListMax(ParmList *p, int count);
+extern ParmList *ParmList_join(ParmList *p, ParmList *p2);
+extern ParmList *ParmList_replace_last(ParmList *p, ParmList *p2);
+extern Parm *ParmList_nth_parm(ParmList *p, unsigned int n);
+extern Parm *ParmList_variadic_parm(ParmList *p);
+extern Parm *ParmList_add_parm(ParmList *p, Parm *newparm);
+extern int ParmList_numrequired(ParmList *);
+extern int ParmList_len(ParmList *);
+extern int ParmList_has_defaultargs(ParmList *p);
+extern int ParmList_has_varargs(ParmList *p);
+
+/* Output functions */
+extern String *ParmList_str(ParmList *);
+extern String *ParmList_str_defaultargs(ParmList *);
+extern String *ParmList_str_multibrackets(ParmList *);
+extern String *ParmList_protostr(ParmList *);
+
+
diff --git a/contrib/tools/swig/Source/Swig/swigscan.h b/contrib/tools/swig/Source/Swig/swigscan.h
new file mode 100644
index 00000000000..edb7dfb59b3
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigscan.h
@@ -0,0 +1,117 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigscan.h
+ *
+ * C/C++ scanner.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct Scanner Scanner;
+
+extern Scanner *NewScanner(void);
+extern void DelScanner(Scanner *);
+extern void Scanner_clear(Scanner *);
+extern void Scanner_push(Scanner *, String *);
+extern void Scanner_pushtoken(Scanner *, int, const_String_or_char_ptr value);
+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 *);
+extern int Scanner_start_line(Scanner *);
+extern void Scanner_idstart(Scanner *, const char *idchar);
+extern String *Scanner_errmsg(Scanner *);
+extern int Scanner_errline(Scanner *);
+extern int Scanner_isoperator(int tokval);
+extern void Scanner_locator(Scanner *, String *loc);
+
+/* Note: Tokens in range 100+ are for C/C++ operators */
+
+#define SWIG_MAXTOKENS 200
+#define SWIG_TOKEN_LPAREN 1 /* ( */
+#define SWIG_TOKEN_RPAREN 2 /* ) */
+#define SWIG_TOKEN_SEMI 3 /* ; */
+#define SWIG_TOKEN_LBRACE 4 /* { */
+#define SWIG_TOKEN_RBRACE 5 /* } */
+#define SWIG_TOKEN_LBRACKET 6 /* [ */
+#define SWIG_TOKEN_RBRACKET 7 /* ] */
+#define SWIG_TOKEN_BACKSLASH 8 /* \ */
+#define SWIG_TOKEN_ENDLINE 9 /* \n */
+#define SWIG_TOKEN_STRING 10 /* "str" */
+#define SWIG_TOKEN_POUND 11 /* # */
+#define SWIG_TOKEN_COLON 12 /* : */
+#define SWIG_TOKEN_DCOLON 13 /* :: */
+#define SWIG_TOKEN_DCOLONSTAR 14 /* ::* */
+#define SWIG_TOKEN_ID 15 /* identifier */
+#define SWIG_TOKEN_FLOAT 16 /* 3.1415F */
+#define SWIG_TOKEN_DOUBLE 17 /* 3.1415 */
+#define SWIG_TOKEN_LONGDOUBLE 18 /* 3.1415L */
+#define SWIG_TOKEN_INT 19 /* 314 */
+#define SWIG_TOKEN_UINT 20 /* 314U */
+#define SWIG_TOKEN_LONG 21 /* 314L */
+#define SWIG_TOKEN_ULONG 22 /* 314UL */
+#define SWIG_TOKEN_CHAR 23 /* 'charconst' */
+#define SWIG_TOKEN_PERIOD 24 /* . */
+#define SWIG_TOKEN_AT 25 /* @ */
+#define SWIG_TOKEN_DOLLAR 26 /* $ */
+#define SWIG_TOKEN_CODEBLOCK 27 /* %{ ... %} ... */
+#define SWIG_TOKEN_RSTRING 28 /* `charconst` */
+#define SWIG_TOKEN_LONGLONG 29 /* 314LL */
+#define SWIG_TOKEN_ULONGLONG 30 /* 314ULL */
+#define SWIG_TOKEN_QUESTION 31 /* ? */
+#define SWIG_TOKEN_COMMENT 32 /* C or C++ comment */
+#define SWIG_TOKEN_BOOL 33 /* true or false */
+#define SWIG_TOKEN_WSTRING 34 /* L"str" */
+#define SWIG_TOKEN_WCHAR 35 /* L'c' */
+#define SWIG_TOKEN_ELLIPSIS 36 /* ... */
+#define SWIG_TOKEN_LLBRACKET 37 /* [[ */
+#define SWIG_TOKEN_RRBRACKET 38 /* ]] */
+
+#define SWIG_TOKEN_ILLEGAL 99
+#define SWIG_TOKEN_ERROR -1
+
+#define SWIG_TOKEN_COMMA 101 /* , */
+#define SWIG_TOKEN_STAR 102 /* * */
+#define SWIG_TOKEN_EQUAL 103 /* = */
+#define SWIG_TOKEN_EQUALTO 104 /* == */
+#define SWIG_TOKEN_NOTEQUAL 105 /* != */
+#define SWIG_TOKEN_PLUS 106 /* + */
+#define SWIG_TOKEN_MINUS 107 /* - */
+#define SWIG_TOKEN_AND 108 /* & */
+#define SWIG_TOKEN_LAND 109 /* && */
+#define SWIG_TOKEN_OR 110 /* | */
+#define SWIG_TOKEN_LOR 111 /* || */
+#define SWIG_TOKEN_XOR 112 /* ^ */
+#define SWIG_TOKEN_LESSTHAN 113 /* < */
+#define SWIG_TOKEN_GREATERTHAN 114 /* > */
+#define SWIG_TOKEN_LTEQUAL 115 /* <= */
+#define SWIG_TOKEN_GTEQUAL 116 /* >= */
+#define SWIG_TOKEN_NOT 117 /* ~ */
+#define SWIG_TOKEN_LNOT 118 /* ! */
+#define SWIG_TOKEN_SLASH 119 /* / */
+#define SWIG_TOKEN_PERCENT 120 /* % */
+#define SWIG_TOKEN_LSHIFT 121 /* << */
+#define SWIG_TOKEN_RSHIFT 122 /* >> */
+#define SWIG_TOKEN_PLUSPLUS 123 /* ++ */
+#define SWIG_TOKEN_MINUSMINUS 124 /* -- */
+#define SWIG_TOKEN_PLUSEQUAL 125 /* += */
+#define SWIG_TOKEN_MINUSEQUAL 126 /* -= */
+#define SWIG_TOKEN_TIMESEQUAL 127 /* *= */
+#define SWIG_TOKEN_DIVEQUAL 128 /* /= */
+#define SWIG_TOKEN_ANDEQUAL 129 /* &= */
+#define SWIG_TOKEN_OREQUAL 130 /* |= */
+#define SWIG_TOKEN_XOREQUAL 131 /* ^= */
+#define SWIG_TOKEN_LSEQUAL 132 /* <<= */
+#define SWIG_TOKEN_RSEQUAL 133 /* >>= */
+#define SWIG_TOKEN_MODEQUAL 134 /* %= */
+#define SWIG_TOKEN_ARROW 135 /* -> */
+#define SWIG_TOKEN_ARROWSTAR 136 /* ->* */
+#define SWIG_TOKEN_LTEQUALGT 137 /* <=> */
diff --git a/contrib/tools/swig/Source/Swig/swigtree.h b/contrib/tools/swig/Source/Swig/swigtree.h
new file mode 100644
index 00000000000..8d63d8fd33f
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigtree.h
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigtree.h
+ *
+ * These functions are used to access and manipulate the SWIG parse tree.
+ * The structure of this tree is modeled directly after XML-DOM. The attribute
+ * and function names are meant to be similar.
+ * ----------------------------------------------------------------------------- */
+
+/* Macros to traverse the DOM tree */
+
+#define nodeType(x) Getattr(x,"nodeType")
+#define parentNode(x) Getattr(x,"parentNode")
+#define previousSibling(x) Getattr(x,"previousSibling")
+#define nextSibling(x) Getattr(x,"nextSibling")
+#define firstChild(x) Getattr(x,"firstChild")
+#define lastChild(x) Getattr(x,"lastChild")
+
+/* Macros to set up the DOM tree (mostly used by the parser) */
+
+#define set_nodeType(x,v) Setattr(x,"nodeType",v)
+#define set_parentNode(x,v) Setattr(x,"parentNode",v)
+#define set_previousSibling(x,v) Setattr(x,"previousSibling",v)
+#define set_nextSibling(x,v) Setattr(x,"nextSibling",v)
+#define set_firstChild(x,v) Setattr(x,"firstChild",v)
+#define set_lastChild(x,v) Setattr(x,"lastChild",v)
+
+/* Utility functions */
+
+extern int checkAttribute(Node *obj, const_String_or_char_ptr name, const_String_or_char_ptr value);
+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 */
+
+extern void Swig_require(const char *ns, Node *node, ...);
+extern void Swig_save(const char *ns, Node *node, ...);
+extern void Swig_restore(Node *node);
+
+/* Debugging of parse trees */
+
+extern void Swig_print_tags(File *obj, Node *root);
+extern void Swig_print_tree(Node *obj);
+extern void Swig_print_node(Node *obj);
+extern int Swig_print_quiet(int quiet);
diff --git a/contrib/tools/swig/Source/Swig/swigwrap.h b/contrib/tools/swig/Source/Swig/swigwrap.h
new file mode 100644
index 00000000000..b584ca495ba
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/swigwrap.h
@@ -0,0 +1,31 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * swigwrap.h
+ *
+ * Functions related to wrapper objects.
+ * ----------------------------------------------------------------------------- */
+
+typedef struct Wrapper {
+ Hash *localh;
+ String *def;
+ String *locals;
+ String *code;
+} Wrapper;
+
+extern Wrapper *NewWrapper(void);
+extern void DelWrapper(Wrapper *w);
+extern void Wrapper_compact_print_mode_set(int flag);
+extern void Wrapper_pretty_print(String *str, File *f);
+extern void Wrapper_compact_print(String *str, File *f);
+extern void Wrapper_print(Wrapper *w, File *f);
+extern int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl);
+extern int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...);
+extern int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name);
+extern char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl);
+extern char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...);
diff --git a/contrib/tools/swig/Source/Swig/symbol.c b/contrib/tools/swig/Source/Swig/symbol.c
new file mode 100644
index 00000000000..e4041a26bcb
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/symbol.c
@@ -0,0 +1,2243 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * symbol.c
+ *
+ * This file implements the SWIG symbol table. See details below.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+/* #define SWIG_DEBUG*/
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * This module provides symbol table management for all of SWIG. In previous
+ * releases, the management of symbols was rather haphazard. This module tries
+ * to correct that.
+ *
+ * All symbols are associated with simple identifiers. For example, here are some
+ * declarations that generate symbol table entries:
+ *
+ * decl symbol
+ * -------------- ------------
+ * void foo(int); foo
+ * int x; x
+ * typedef int *blah; blah
+ *
+ * Associated with each symbol is a Hash table that can contain any set of
+ * attributes that make sense for that object. For example:
+ *
+ * typedef int *blah; ----> "name" : 'blah'
+ * "type" : 'int'
+ * "decl" : 'p.'
+ * "storage" : 'typedef'
+ *
+ * In some cases, the symbol table needs to manage overloaded entries. For instance,
+ * overloaded functions. In this case, a linked list is built. The "sym:nextSibling"
+ * attribute is reserved to hold a link to the next entry. For example:
+ *
+ * int foo(int); --> "name" : "foo" "name" : "foo"
+ * int foo(int,double); "type" : "int" "type" : "int"
+ * "decl" : "f(int)." "decl" : "f(int,double)."
+ * ... ...
+ * "sym:nextSibling" : --------> "sym:nextSibling": --------> ...
+ *
+ * When more than one symbol has the same name, the symbol declarator is
+ * used to detect duplicates. For example, in the above case, foo(int) and
+ * foo(int,double) are different because their "decl" attribute is different.
+ * However, if a third declaration "foo(int)" was made, it would generate a
+ * conflict (due to having a declarator that matches a previous entry).
+ *
+ * Structures and classes:
+ *
+ * C/C++ symbol tables are normally managed in a few different spaces. The
+ * most visible namespace is reserved for functions, variables, typedef, enum values
+ * and such. In C, a separate tag-space is reserved for 'struct name', 'class name',
+ * and 'union name' declarations. In SWIG, a single namespace is used for everything
+ * this means that certain incompatibilities will arise with some C programs. For instance:
+ *
+ * struct Foo {
+ * ...
+ * }
+ *
+ * int Foo(); // Error. Name clash. Works in C though
+ *
+ * Due to the unified namespace for structures, special handling is performed for
+ * the following:
+ *
+ * typedef struct Foo {
+ *
+ * } Foo;
+ *
+ * In this case, the symbol table contains an entry for the structure itself. The
+ * typedef is left out of the symbol table.
+ *
+ * Target language vs C:
+ *
+ * The symbol tables are normally managed *in the namespace of the target language*.
+ * This means that name-collisions can be resolved using %rename and related
+ * directives. A quirk of this is that sometimes the symbol tables need to
+ * be used for C type resolution as well. To handle this, each symbol table
+ * also has a C-symbol table lurking behind the scenes. This is used to locate
+ * symbols in the C namespace. However, this symbol table is not used for error
+ * reporting nor is it used for anything else during code generation.
+ *
+ * Symbol table structure:
+ *
+ * Symbol tables themselves are a special kind of node that is organized just like
+ * a normal parse tree node. Symbol tables are organized in a tree that can be
+ * traversed using the SWIG-DOM API. The following attributes names are reserved.
+ *
+ * name -- Name of the scope defined by the symbol table (if any)
+ * This name is the C-scope name and is not affected by
+ * %renaming operations
+ * symtab -- Hash table mapping identifiers to nodes.
+ * csymtab -- Hash table mapping C identifiers to nodes.
+ *
+ * Reserved attributes on symbol objects:
+ *
+ * When a symbol is placed in the symbol table, the following attributes
+ * are set:
+ *
+ * sym:name -- Symbol name
+ * sym:nextSibling -- Next symbol (if overloaded)
+ * sym:previousSibling -- Previous symbol (if overloaded)
+ * sym:symtab -- Symbol table object holding the symbol
+ * sym:overloaded -- Set to the first symbol if overloaded
+ *
+ * These names are modeled after XML namespaces. In particular, every attribute
+ * pertaining to symbol table management is prefaced by the "sym:" prefix.
+ *
+ * An example dump of the parse tree showing symbol table entries for the
+ * following code should clarify this:
+ *
+ * namespace OuterNamespace {
+ * namespace InnerNamespace {
+ * class Class {
+ * };
+ * struct Struct {
+ * int Var;
+ * };
+ * }
+ * }
+ *
+ * +++ namespace ----------------------------------------
+ * | sym:name - "OuterNamespace"
+ * | symtab - 0xa064bf0
+ * | sym:symtab - 0xa041690
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ namespace ----------------------------------------
+ * | sym:name - "InnerNamespace"
+ * | symtab - 0xa064cc0
+ * | sym:symtab - 0xa064bf0
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ class ----------------------------------------
+ * | sym:name - "Class"
+ * | symtab - 0xa064d80
+ * | sym:symtab - 0xa064cc0
+ * | sym:overname - "__SWIG_0"
+ * |
+ * +++ class ----------------------------------------
+ * | sym:name - "Struct"
+ * | symtab - 0xa064f00
+ * | sym:symtab - 0xa064cc0
+ * | sym:overname - "__SWIG_0"
+ *
+ * +++ cdecl ----------------------------------------
+ * | sym:name - "Var"
+ * | sym:symtab - 0xa064f00
+ * | sym:overname - "__SWIG_0"
+ * |
+ *
+ *
+ * Each class and namespace has its own scope and thus a new symbol table (sym)
+ * is created. The sym attribute is only set for the first entry in the symbol
+ * table. The sym:symtab entry points to the symbol table in which the symbol
+ * exists, so for example, Struct is in the scope OuterNamespace::InnerNamespace
+ * so sym:symtab points to this symbol table (0xa064cc0).
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *current = 0; /* The current symbol table hash */
+static Hash *ccurrent = 0; /* The current c symbol table hash */
+static Hash *current_symtab = 0; /* Current symbol table node */
+static Hash *symtabs = 0; /* Hash of all symbol tables by fully-qualified name */
+static Hash *global_scope = 0; /* Global scope */
+
+static int use_inherit = 1;
+
+/* common attribute keys, to avoid calling find_key all the times */
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_tables()
+ *
+ * Debug display of symbol tables
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_tables(Symtab *symtab) {
+ if (!symtab)
+ symtab = current_symtab;
+
+ Printf(stdout, "SYMBOL TABLES start =======================================\n");
+ Swig_print_tree(symtab);
+ Printf(stdout, "SYMBOL TABLES finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_tables_summary()
+ *
+ * Debug summary display of all symbol tables by fully-qualified name
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_tables_summary(void) {
+ Printf(stdout, "SYMBOL TABLES SUMMARY start =======================================\n");
+ Swig_print_node(symtabs);
+ Printf(stdout, "SYMBOL TABLES SUMMARY finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_print_symbols()
+ * ----------------------------------------------------------------------------- */
+
+static void symbol_print_symbols(const char *symboltabletype, const char *nextSibling) {
+ Node *table = symtabs;
+ Iterator ki = First(table);
+ int show_pointers = 0;
+ while (ki.key) {
+ String *k = ki.key;
+ Printf(stdout, "===================================================\n");
+ Printf(stdout, "%s -\n", k);
+ {
+ Symtab *symtab = Getattr(Getattr(table, k), symboltabletype);
+ Iterator it = First(symtab);
+ while (it.key) {
+ String *symname = it.key;
+ Printf(stdout, " %s (%s)", symname, nodeType(it.item));
+ if (show_pointers)
+ Printf(stdout, " %p", it.item);
+ Printf(stdout, "\n");
+ {
+ Node *sibling = Getattr(it.item, nextSibling);
+ while (sibling) {
+ Printf(stdout, " %s (%s)", symname, nodeType(sibling));
+ if (show_pointers)
+ Printf(stdout, " %p", sibling);
+ Printf(stdout, "\n");
+ sibling = Getattr(sibling, nextSibling);
+ }
+ }
+ it = Next(it);
+ }
+ }
+ ki = Next(ki);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_symbols()
+ *
+ * Debug display of all the target language symbols
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_symbols(void) {
+ Printf(stdout, "SYMBOLS start =======================================\n");
+ symbol_print_symbols("symtab", "sym:nextSibling");
+ Printf(stdout, "SYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_print_csymbols()
+ *
+ * Debug display of all the C symbols
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_print_csymbols(void) {
+ Printf(stdout, "CSYMBOLS start =======================================\n");
+ symbol_print_symbols("csymtab", "csym:nextSibling");
+ Printf(stdout, "CSYMBOLS finish =======================================\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_init()
+ *
+ * Create a new symbol table object
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_init(void) {
+
+ current = NewHash();
+ current_symtab = NewHash();
+ ccurrent = NewHash();
+ set_nodeType(current_symtab, "symboltable");
+ Setattr(current_symtab, "symtab", current);
+ Delete(current);
+ Setattr(current_symtab, "csymtab", ccurrent);
+ Delete(ccurrent);
+
+ /* Set the global scope */
+ symtabs = NewHash();
+ Setattr(symtabs, "", current_symtab);
+ Delete(current_symtab);
+ global_scope = current_symtab;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_setscopename()
+ *
+ * Set the C scopename of the current symbol table.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_setscopename(const_String_or_char_ptr name) {
+ String *qname;
+ /* assert(!Getattr(current_symtab,"name")); */
+ Setattr(current_symtab, "name", name);
+
+ /* Set nested scope in parent */
+
+ qname = Swig_symbol_qualifiedscopename(current_symtab);
+
+ /* Save a reference to this scope */
+ Setattr(symtabs, qname, current_symtab);
+ Delete(qname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_getscopename()
+ *
+ * Get the C scopename of the current symbol table
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_getscopename(void) {
+ return Getattr(current_symtab, "name");
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_getscope()
+ *
+ * Given a fully qualified C scopename, this function returns a symbol table
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_getscope(const_String_or_char_ptr name) {
+ if (!symtabs)
+ return 0;
+ if (Equal("::", (const_String_or_char_ptr ) name))
+ name = "";
+ return Getattr(symtabs, name);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualifiedscopename()
+ *
+ * Get the fully qualified C scopename of a symbol table. Note, this only pertains
+ * to the C/C++ scope name. It is not affected by renaming.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualifiedscopename(Symtab *symtab) {
+ String *result = 0;
+ Hash *parent;
+ String *name;
+ if (!symtab)
+ symtab = current_symtab;
+ parent = Getattr(symtab, "parentNode");
+ if (parent) {
+ result = Swig_symbol_qualifiedscopename(parent);
+ }
+ name = Getattr(symtab, "name");
+ if (name) {
+ if (!result) {
+ result = NewStringEmpty();
+ }
+ if (Len(result)) {
+ Printv(result, "::", name, NIL);
+ } else {
+ Append(result, name);
+ }
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualified_language_scopename()
+ *
+ * Get the fully qualified C scopename of a symbol table but using a language
+ * specific separator for the scopenames. Basically the same as
+ * Swig_symbol_qualifiedscopename() but using the different separator.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualified_language_scopename(Symtab *n) {
+ /* TODO: fix for %rename to work */
+ String *result = Swig_symbol_qualifiedscopename(n);
+ Replaceall(result, "::", NSPACE_SEPARATOR);
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_newscope()
+ *
+ * Create a new scope. Returns the newly created scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_newscope(void) {
+ Hash *n;
+ Hash *hsyms, *h;
+
+ hsyms = NewHash();
+ h = NewHash();
+
+ set_nodeType(h, "symboltable");
+ Setattr(h, "symtab", hsyms);
+ Delete(hsyms);
+ set_parentNode(h, current_symtab);
+
+ n = lastChild(current_symtab);
+ if (!n) {
+ set_firstChild(current_symtab, h);
+ } else {
+ set_nextSibling(n, h);
+ Delete(h);
+ }
+ set_lastChild(current_symtab, h);
+ current = hsyms;
+ ccurrent = NewHash();
+ Setattr(h, "csymtab", ccurrent);
+ Delete(ccurrent);
+ current_symtab = h;
+ return h;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_setscope()
+ *
+ * Set the current scope. Returns the previous current scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_setscope(Symtab *sym) {
+ Symtab *ret = current_symtab;
+ current_symtab = sym;
+ current = Getattr(sym, "symtab");
+ assert(current);
+ ccurrent = Getattr(sym, "csymtab");
+ assert(ccurrent);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_popscope()
+ *
+ * Pop out of the current scope. Returns the popped scope and sets the
+ * scope to the parent scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_popscope(void) {
+ Hash *h = current_symtab;
+ current_symtab = Getattr(current_symtab, "parentNode");
+ assert(current_symtab);
+ current = Getattr(current_symtab, "symtab");
+ assert(current);
+ ccurrent = Getattr(current_symtab, "csymtab");
+ assert(ccurrent);
+ return h;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_global_scope()
+ *
+ * Return the symbol table for the global scope.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_global_scope(void) {
+ return global_scope;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_current()
+ *
+ * Return the current symbol table.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_current(void) {
+ return current_symtab;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_alias()
+ *
+ * Makes an alias for a symbol in the global symbol table.
+ * Primarily for namespace aliases such as 'namespace X = Y;'.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_alias(const_String_or_char_ptr aliasname, Symtab *s) {
+ String *qname = Swig_symbol_qualifiedscopename(current_symtab);
+ if (qname) {
+ Printf(qname, "::%s", aliasname);
+ } else {
+ qname = NewString(aliasname);
+ }
+ if (!Getattr(symtabs, qname)) {
+ Setattr(symtabs, qname, s);
+ }
+ Delete(qname);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_inherit()
+ *
+ * Inherit symbols from another scope. Primarily for C++ inheritance and
+ * for using directives, such as 'using namespace X;'
+ * but not for using declarations, such as 'using X::A;'.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_inherit(Symtab *s) {
+ int i, ilen;
+ List *inherit = Getattr(current_symtab, "inherit");
+ if (!inherit) {
+ inherit = NewList();
+ Setattr(current_symtab, "inherit", inherit);
+ Delete(inherit);
+ }
+
+ if (s == current_symtab) {
+ Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(s), Getline(s), "Recursive scope inheritance of '%s'.\n", Getattr(s, "name"));
+ return;
+ }
+ assert(s != current_symtab);
+ ilen = Len(inherit);
+ for (i = 0; i < ilen; i++) {
+ Node *n = Getitem(inherit, i);
+ if (n == s)
+ return; /* Already inherited */
+ }
+ Append(inherit, s);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_cadd()
+ *
+ * Adds a node to the C symbol table only.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_cadd(const_String_or_char_ptr name, Node *n) {
+ Node *append = 0;
+ Node *cn;
+ /* There are a few options for weak symbols. A "weak" symbol
+ is any symbol that can be replaced by another symbol in the C symbol
+ table. An example would be a forward class declaration. A forward
+ class sits in the symbol table until a real class declaration comes along.
+
+ Certain symbols are marked as "sym:typename". These are important
+ symbols related to the C++ type-system and take precedence in the C
+ symbol table. An example might be code like this:
+
+ template<class T> T foo(T x);
+ int foo(int);
+
+ In this case, the template is marked with "sym:typename" so that it
+ stays in the C symbol table (so that it can be expanded using %template).
+ */
+
+ if (!name)
+ return;
+
+ if (SwigType_istemplate(name)) {
+ String *cname = NewString(name);
+ String *dname = Swig_symbol_template_deftype(cname, 0);
+ if (!Equal(dname, name)) {
+ /* Add another symbol with all template default arguments expanded, eg
+ *
+ * template <typename T1, typename T2 = short> struct X {};
+ * %template(XInt) X<int>;
+ *
+ * then name=X<int>, and dname=X<int,short> so add X<int,short> here too. */
+ Swig_symbol_cadd(dname, n);
+ }
+ Delete(dname);
+ Delete(cname);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_cadd %s %p\n", name, n);
+#endif
+ cn = Getattr(ccurrent, name);
+
+ if (cn && (Getattr(cn, "sym:typename"))) {
+ /* The node in the C symbol table is a typename. Do nothing */
+ /* We might append the symbol at the end */
+ append = n;
+ } else if (cn && (Getattr(cn, "sym:weak"))) {
+ /* The node in the symbol table is weak. Replace it */
+ if (checkAttribute(cn, "nodeType", "template")
+ && checkAttribute(cn, "templatetype", "classforward")) {
+ /* The node is a template classforward declaration, and the
+ default template parameters here take precedence. */
+ ParmList *pc = Getattr(cn, "templateparms");
+ ParmList *pn = Getattr(n, "templateparms");
+#ifdef SWIG_DEBUG
+ Printf(stderr, "found template classforward %s\n", Getattr(cn, "name"));
+#endif
+ while (pc && pn) {
+ String *value = Getattr(pc, "value");
+ if (value) {
+#ifdef SWIG_DEBUG
+ Printf(stderr, "add default template value %s %s\n", Getattr(pc, "name"), value);
+#endif
+ Setattr(pn, "value", value);
+ }
+ pc = nextSibling(pc);
+ pn = nextSibling(pn);
+ }
+ Setattr(n, "templateparms", Getattr(cn, "templateparms"));
+ }
+ Setattr(ccurrent, name, n);
+
+ } else if (cn && (Getattr(n, "sym:weak"))) {
+ /* The node being added is weak. Don't worry about it */
+ } else if (cn && (Getattr(n, "sym:typename"))) {
+ /* The node being added is a typename. We definitely add it */
+ Setattr(ccurrent, name, n);
+ append = cn;
+ } else if (cn && (Checkattr(cn, "nodeType", "templateparm"))) {
+ Swig_error(Getfile(n), Getline(n), "Declaration of '%s' shadows template parameter,\n", name);
+ Swig_error(Getfile(cn), Getline(cn), "previous template parameter declaration '%s'.\n", name);
+ return;
+ } else if (cn) {
+ append = n;
+ } else if (!cn) {
+ /* No conflict. Add the symbol */
+ Setattr(ccurrent, name, n);
+ }
+
+ /* Multiple entries in the C symbol table. We append to the symbol table */
+ if (append) {
+ Node *fn, *pn = 0;
+ cn = Getattr(ccurrent, name);
+ fn = cn;
+ while (fn) {
+ pn = fn;
+ if (fn == append) {
+ /* already added. Bail */
+ return;
+ }
+ fn = Getattr(fn, "csym:nextSibling");
+ }
+ if (pn) {
+ Setattr(pn, "csym:nextSibling", append);
+ }
+ }
+
+ /* Special typedef handling. When a typedef node is added to the symbol table, we
+ might have to add a type alias. This would occur if the typedef mapped to another
+ scope in the system. For example:
+
+ class Foo {
+ };
+
+ typedef Foo OtherFoo;
+
+ In this case, OtherFoo becomes an alias for Foo. */
+
+ {
+ Node *td = n;
+ while (td && ((Equal(nodeType(td), "cdecl") && Checkattr(td, "storage", "typedef")) || (Equal(nodeType(td), "using") && !Getattr(n, "namespace")))) {
+ SwigType *type;
+ Node *td1;
+ int using_not_typedef = Equal(nodeType(td), "using");
+ type = Copy(Getattr(td, using_not_typedef ? "uname" : "type"));
+ SwigType_push(type, Getattr(td, "decl"));
+ td1 = Swig_symbol_clookup(type, 0);
+
+ /* Fix pathetic case #1214313:
+
+ class Foo
+ {
+ };
+
+ typedef Foo FooBar;
+
+ class CBaz
+ {
+ public:
+ typedef FooBar Foo;
+ };
+
+ ie, when Foo -> FooBar -> Foo, jump one scope up when possible.
+
+ */
+ if (td1) {
+ String *st = 0;
+ String *sn = Getattr(td, "name");
+ if (Equal(nodeType(td1), "cdecl") && Checkattr(td1, "storage", "typedef"))
+ st = Getattr(td1, "type");
+ else if (Equal(nodeType(td1), "using") && !Getattr(td1, "namespace"))
+ st = Getattr(td1, "uname");
+ if (st && sn && Equal(st, sn)) {
+ Symtab *sc = Getattr(current_symtab, "parentNode");
+ if (sc)
+ td1 = Swig_symbol_clookup(type, sc);
+ }
+ }
+
+ Delete(type);
+ if (td1 == td)
+ break;
+ td = td1;
+ if (td) {
+ Symtab *st = Getattr(td, "symtab");
+ if (st) {
+ Swig_symbol_alias(Getattr(n, "name"), st);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_add()
+ *
+ * Adds a node to the symbol table. Returns the node itself if successfully
+ * added. Otherwise, it returns the symbol table entry of the conflicting node.
+ *
+ * Also places the symbol in a behind-the-scenes C symbol table. This is needed
+ * for namespace support, type resolution, and other issues.
+ * ----------------------------------------------------------------------------- */
+
+static Node *symbol_add(const_String_or_char_ptr symname, Node *n) {
+ Hash *c, *cl = 0;
+ SwigType *decl, *ndecl;
+ String *cstorage, *nstorage;
+ int nt = 0, ct = 0;
+ int pn = 0;
+ int u1 = 0, u2 = 0;
+ String *name, *overname;
+
+ /* See if the node has a name. If so, we place in the C symbol table for this
+ scope. We don't worry about overloading here---the primary purpose of this
+ is to record information for type/name resolution for later. Conflicts
+ in C namespaces are errors, but these will be caught by the C++ compiler
+ when compiling the wrapper code */
+
+
+ /* There are a few options for weak symbols. A "weak" symbol
+ is any symbol that can be replaced by another symbol in the C symbol
+ table. An example would be a forward class declaration. A forward
+ class sits in the symbol table until a real class declaration comes along.
+
+ Certain symbols are marked as "sym:typename". These are important
+ symbols related to the C++ type-system and take precedence in the C
+ symbol table. An example might be code like this:
+
+ template<class T> T foo(T x);
+ int foo(int);
+
+ In this case, the template is marked with "sym:typename" so that it
+ stays in the C symbol table (so that it can be expanded using %template).
+ */
+
+ name = Getattr(n, "name");
+ if (name && Len(name)) {
+ Swig_symbol_cadd(name, n);
+ }
+
+ /* No symbol name defined. We return. */
+ if (!symname) {
+ return n;
+ }
+
+ /* If node is ignored. We don't proceed any further */
+ if (GetFlag(n, "feature:ignore"))
+ return n;
+
+ /* See if the symbol already exists in the table */
+ c = Getattr(current, symname);
+
+ /* Check for a weak symbol. A weak symbol is allowed to be in the
+ symbol table, but is silently overwritten by other symbols. An example
+ would be a forward class declaration. For instance:
+
+ class Foo;
+
+ In this case, "Foo" sits in the symbol table. However, the
+ definition of Foo would replace the entry if it appeared later. */
+
+ if (c && Getattr(c, "sym:weak")) {
+ c = 0;
+ }
+ if (c) {
+ /* There is a symbol table conflict. There are a few cases to consider here:
+ (1) A conflict between a class/enum and a typedef declaration is okay.
+ In this case, the symbol table entry is set to the class/enum declaration
+ itself, not the typedef.
+ (2) A conflict between namespaces is okay--namespaces are open
+ (3) Otherwise, overloading is only allowed for functions
+ (4) This special case is okay: a class template instantiated with same name as the template's name
+ */
+
+ /* Check for namespaces */
+ String *ntype = Getattr(n, "nodeType");
+ if ((Equal(ntype, Getattr(c, "nodeType"))) && ((Equal(ntype, "namespace")))) {
+ Node *cl, *pcl = 0;
+ cl = c;
+ while (cl) {
+ pcl = cl;
+ cl = Getattr(cl, "sym:nextSibling");
+ }
+ Setattr(pcl, "sym:nextSibling", n);
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "sym:previousSibling", pcl);
+ return n;
+ }
+
+ /* Special case: class template instantiated with same name as the template's name eg: %template(X) X<int>; */
+ if (Equal(nodeType(c), "template")) {
+ String *nt1 = Getattr(c, "templatetype");
+ String *nt2 = nodeType(n);
+ if (Equal(nt1, "class") && Equal(nt1, nt2)) {
+ if (Getattr(n, "template")) {
+ /* Finally check that another %template with same name doesn't already exist */
+ if (!Getattr(c, "sym:nextSibling")) {
+ Setattr(c, "sym:nextSibling", n);
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ Setattr(n, "sym:previousSibling", c);
+ return n;
+ }
+ }
+ }
+ }
+
+ if (Getattr(n, "allows_typedef"))
+ nt = 1;
+ if (Getattr(c, "allows_typedef"))
+ ct = 1;
+ if (nt || ct) {
+ Node *td, *other;
+ String *s;
+ /* At least one of the nodes allows typedef overloading. Make sure that
+ both don't--this would be a conflict */
+
+ if (nt && ct)
+ return c;
+
+ /* Figure out which node allows the typedef */
+ if (nt) {
+ td = n;
+ other = c;
+ } else {
+ td = c;
+ other = n;
+ }
+ /* Make sure the other node is a typedef */
+ s = Getattr(other, "storage");
+ if (!s || (!Equal(s, "typedef")))
+ return c; /* No. This is a conflict */
+
+ /* Hmmm. This appears to be okay. Make sure the symbol table refers to the allow_type node */
+
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ if (td == n) {
+ Setattr(current, symname, td);
+ }
+ return n;
+ }
+
+ decl = Getattr(c, "decl");
+ ndecl = Getattr(n, "decl");
+
+ {
+ String *nt1, *nt2;
+ nt1 = Getattr(n, "nodeType");
+ if (Equal(nt1, "template"))
+ nt1 = Getattr(n, "templatetype");
+ nt2 = Getattr(c, "nodeType");
+ if (Equal(nt2, "template"))
+ nt2 = Getattr(c, "templatetype");
+ if (Equal(nt1, "using"))
+ u1 = 1;
+ if (Equal(nt2, "using"))
+ u2 = 1;
+
+ if ((!Equal(nt1, nt2)) && !(u1 || u2))
+ return c;
+ }
+ if (!(u1 || u2)) {
+ if ((!SwigType_isfunction(decl)) || (!SwigType_isfunction(ndecl))) {
+ /* Symbol table conflict */
+ return c;
+ }
+ }
+
+ /* Hmmm. Declarator seems to indicate that this is a function */
+ /* Look at storage class to see if compatible */
+ cstorage = Getattr(c, "storage");
+ nstorage = Getattr(n, "storage");
+
+ /* If either one is declared as typedef, forget it. We're hosed */
+ if (Cmp(cstorage, "typedef") == 0) {
+ return c;
+ }
+ if (Cmp(nstorage, "typedef") == 0) {
+ return c;
+ }
+
+ /* Okay. Walk down the list of symbols and see if we get a declarator match */
+ {
+ String *nt = Getattr(n, "nodeType");
+ int n_template = Equal(nt, "template") && Checkattr(n, "templatetype", "cdecl");
+ int n_plain_cdecl = Equal(nt, "cdecl");
+ Node *cn = c;
+ pn = 0;
+ while (cn) {
+ decl = Getattr(cn, "decl");
+ if (!(u1 || u2)) {
+ if (Cmp(ndecl, decl) == 0) {
+ /* Declarator conflict */
+ /* Now check we don't have a non-templated function overloaded by a templated function with same params,
+ * eg void foo(); template<typename> void foo(); */
+ String *cnt = Getattr(cn, "nodeType");
+ int cn_template = Equal(cnt, "template") && Checkattr(cn, "templatetype", "cdecl");
+ int cn_plain_cdecl = Equal(cnt, "cdecl");
+ if (!((n_template && cn_plain_cdecl) || (cn_template && n_plain_cdecl))) {
+ /* found a conflict */
+ return cn;
+ }
+ }
+ }
+ cl = cn;
+ cn = Getattr(cn, "sym:nextSibling");
+ pn++;
+ }
+ }
+ /* Well, we made it this far. Guess we can drop the symbol in place */
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ /* Printf(stdout,"%s %p\n", Getattr(n,"sym:overname"), current_symtab); */
+ assert(!Getattr(n, "sym:overname"));
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(n, "sym:overname", overname);
+ /*Printf(stdout,"%s %s %s\n", symname, Getattr(n,"decl"), Getattr(n,"sym:overname")); */
+ Setattr(cl, "sym:nextSibling", n);
+ Setattr(n, "sym:previousSibling", cl);
+ Setattr(cl, "sym:overloaded", c);
+ Setattr(n, "sym:overloaded", c);
+ Delete(overname);
+ return n;
+ }
+
+ /* No conflict. Just add it */
+ Setattr(n, "sym:symtab", current_symtab);
+ Setattr(n, "sym:name", symname);
+ /* Printf(stdout,"%s\n", Getattr(n,"sym:overname")); */
+ overname = NewStringf("__SWIG_%d", pn);
+ Setattr(n, "sym:overname", overname);
+ Delete(overname);
+ /* Printf(stdout,"%s %s %s\n", symname, Getattr(n,"decl"), Getattr(n,"sym:overname")); */
+ Setattr(current, symname, n);
+ return n;
+}
+
+Node *Swig_symbol_add(const_String_or_char_ptr symname, Node *n) {
+ Node *nn = symbol_add(symname, n);
+ /* Always set the symtab to have correct scope in case of error reporting */
+ if (!Getattr(n, "sym:symtab"))
+ Setattr(n, "sym:symtab", current_symtab);
+ return nn;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_conflict_warn()
+ *
+ * Issue warnings for node n if it conflicts with node c after calling
+ * Swig_symbol_add().
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_conflict_warn(Node *n, Node *c, const String *symname, int inclass) {
+ String *e = NewStringEmpty();
+ String *en = NewStringEmpty();
+ String *ec = NewStringEmpty();
+ String *symname_stripped = SwigType_templateprefix(symname);
+ String *n_name_stripped = SwigType_templateprefix(Getattr(n, "name"));
+ String *c_name_stripped = SwigType_templateprefix(Getattr(c, "name"));
+ int redefined = Swig_need_redefined_warn(n, c, inclass);
+ String *n_name_decl = Swig_name_decl(n);
+ String *c_name_decl = Swig_name_decl(c);
+ if (redefined) {
+ Printf(en, "Redefinition of identifier '%s'", symname_stripped);
+ Printf(ec, "previous definition of '%s'", symname_stripped);
+ } else {
+ Printf(en, "Redundant redeclaration of identifier '%s'", symname_stripped);
+ Printf(ec, "previous declaration of '%s'", symname_stripped);
+ }
+ if (!Equal(symname_stripped, n_name_stripped))
+ Printf(en, " (Renamed from '%s')", SwigType_namestr(n_name_stripped));
+ if (!Equal(symname_stripped, c_name_stripped))
+ Printf(ec, " (Renamed from '%s')", SwigType_namestr(c_name_stripped));
+ if (!Equal(n_name_stripped, n_name_decl))
+ Printf(en, " as %s", n_name_decl);
+ if (!Equal(c_name_stripped, c_name_decl))
+ Printf(ec, " as %s", c_name_decl);
+ Printf(en, " ignored,");
+ 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 if (!Strstr(Getattr(n, "storage"), "friend") && !Strstr(Getattr(c, "storage"), "friend")) {
+ 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(c_name_decl);
+ Delete(n_name_decl);
+ Delete(symname_stripped);
+ Delete(c_name_stripped);
+ Delete(n_name_stripped);
+ Delete(e);
+ Delete(en);
+ Delete(ec);
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_lookup()
+ *
+ * Internal function to handle fully qualified symbol table lookups. This
+ * works from the symbol table supplied in symtab and unwinds its way out
+ * towards the global scope.
+ *
+ * This function operates in the C namespace, not the target namespace.
+ *
+ * The checkfunc function is an optional callback that can be used to verify a particular
+ * symbol match. This is only used in some of the more exotic parts of SWIG. For instance,
+ * verifying that a class hierarchy implements all pure virtual methods.
+ * ----------------------------------------------------------------------------- */
+
+static Node *_symbol_lookup(const String *name, Symtab *symtab, Node *(*checkfunc) (Node *n)) {
+ Node *n;
+ List *inherit;
+ Hash *sym = Getattr(symtab, "csymtab");
+ if (Getmark(symtab))
+ return 0;
+ Setmark(symtab, 1);
+
+ n = Getattr(sym, name);
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_look %s %p %p %s\n", name, n, symtab, Getattr(symtab, "name"));
+#endif
+
+ if (n) {
+ /* if checkfunc is defined. Call it to determine a match */
+ if (checkfunc) {
+ Node *cn = checkfunc(n);
+ if (cn) {
+ Setmark(symtab, 0);
+ /* Note that checkfunc can return n != cn, where cn could be a node further down the csym linked list starting at n */
+ return cn;
+ }
+ } else {
+ Setmark(symtab, 0);
+ return n;
+ }
+ }
+
+ if (!n && SwigType_istemplate(name)) {
+ String *dname = 0;
+ Setmark(symtab, 0);
+ dname = Swig_symbol_template_deftype(name, symtab);
+ if (!Equal(dname, name)) {
+ n = _symbol_lookup(dname, symtab, checkfunc);
+ }
+ Delete(dname);
+ if (n)
+ return n;
+ Setmark(symtab, 1);
+ }
+
+ inherit = Getattr(symtab, "inherit");
+ if (inherit && use_inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ n = _symbol_lookup(name, Getitem(inherit, i), checkfunc);
+ if (n) {
+ Setmark(symtab, 0);
+ return n;
+ }
+ }
+ }
+
+ Setmark(symtab, 0);
+ return 0;
+}
+
+static Node *symbol_lookup(const_String_or_char_ptr name, Symtab *symtab, Node *(*checkfunc) (Node *n)) {
+ Node *n = 0;
+ if (DohCheck(name)) {
+ n = _symbol_lookup(name, symtab, checkfunc);
+ } else {
+ String *sname = NewString(name);
+ n = _symbol_lookup(sname, symtab, checkfunc);
+ Delete(sname);
+ }
+ return n;
+}
+
+
+
+/* -----------------------------------------------------------------------------
+ * symbol_lookup_qualified()
+ * ----------------------------------------------------------------------------- */
+
+static Node *symbol_lookup_qualified(const_String_or_char_ptr name, Symtab *symtab, const String *prefix, int local, Node *(*checkfunc) (Node *n)) {
+ /* This is a little funky, we search by fully qualified names */
+
+ if (!symtab)
+ return 0;
+ if (!prefix) {
+ Node *n;
+ String *bname = 0;
+ String *prefix = 0;
+ Swig_scopename_split(name, &prefix, &bname);
+ n = symbol_lookup_qualified(bname, symtab, prefix, local, checkfunc);
+ Delete(bname);
+ Delete(prefix);
+ return n;
+ } else {
+ Symtab *st;
+ Node *n = 0;
+ /* Make qualified name of current scope */
+ String *qalloc = 0;
+ String *qname = Swig_symbol_qualifiedscopename(symtab);
+ const String *cqname;
+ if (qname) {
+ if (Len(qname)) {
+ if (prefix && Len(prefix)) {
+ Printv(qname, "::", prefix, NIL);
+ }
+ } else {
+ Append(qname, prefix);
+ }
+ qalloc = qname;
+ cqname = qname;
+ } else {
+ cqname = prefix;
+ }
+ st = Getattr(symtabs, cqname);
+ /* Found a scope match */
+ if (st) {
+ if (!name) {
+ if (qalloc)
+ Delete(qalloc);
+ return st;
+ }
+ n = symbol_lookup(name, st, checkfunc);
+ }
+ if (qalloc)
+ Delete(qalloc);
+
+ if (!n) {
+ if (!local) {
+ Node *pn = Getattr(symtab, "parentNode");
+ if (pn)
+ n = symbol_lookup_qualified(name, pn, prefix, local, checkfunc);
+
+ /* Check inherited scopes */
+ if (!n) {
+ List *inherit = Getattr(symtab, "inherit");
+ if (inherit && use_inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ Node *prefix_node = symbol_lookup(prefix, Getitem(inherit, i), checkfunc);
+ if (prefix_node) {
+ Node *prefix_symtab = Getattr(prefix_node, "symtab");
+ if (prefix_symtab) {
+ n = symbol_lookup(name, prefix_symtab, checkfunc);
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ n = 0;
+ }
+ }
+ return n;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup()
+ *
+ * Look up a symbol in the symbol table. This uses the C name, not scripting
+ * names. Note: If we come across a using declaration, we follow it to
+ * to get the real node. Any using directives are also followed (but this is
+ * implemented in symbol_lookup()).
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup(const_String_or_char_ptr name, Symtab *n) {
+ Hash *hsym = 0;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ if (n) {
+ hsym = n;
+ }
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0);
+ } else {
+ s = symbol_lookup(nname, global_scope, 0);
+ }
+ Delete(nname);
+ } else {
+ String *prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, 0);
+ Delete(prefix);
+ if (!s) {
+ return 0;
+ }
+ }
+ }
+ }
+ if (!s) {
+ while (hsym) {
+ s = symbol_lookup(name, hsym, 0);
+ if (s)
+ break;
+ hsym = Getattr(hsym, "parentNode");
+ if (!hsym)
+ break;
+ }
+ }
+
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ if (Getattr(s, "csym:nextSibling")) {
+ /* overloaded using declarations and method declarations - don't chase the using declarations up the inheritance hierarchy */
+ break;
+ } else {
+ String *uname = Getattr(s, "uname");
+ Symtab *un = Getattr(s, "sym:symtab");
+ Node *ss = (!Equal(name, uname) || (un != n)) ? Swig_symbol_clookup(uname, un) : 0; /* avoid infinity loop */
+ if (!ss) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(uname));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_check()
+ *
+ * This function is identical to Swig_symbol_clookup() except that it
+ * accepts a callback function that is invoked to determine a symbol match.
+ * The purpose of this function is to support complicated algorithms that need
+ * to examine multiple definitions of the same symbol that might appear in an
+ * inheritance hierarchy.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_check(const_String_or_char_ptr name, Symtab *n, Node *(*checkfunc) (Node *n)) {
+ Hash *hsym = 0;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ if (n) {
+ hsym = n;
+ }
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc);
+ } else {
+ s = symbol_lookup(nname, global_scope, checkfunc);
+ }
+ Delete(nname);
+ } else {
+ String *prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, checkfunc);
+ Delete(prefix);
+ if (!s) {
+ return 0;
+ }
+ }
+ }
+ }
+ if (!s) {
+ while (hsym) {
+ s = symbol_lookup(name, hsym, checkfunc);
+ if (s)
+ break;
+ hsym = Getattr(hsym, "parentNode");
+ if (!hsym)
+ break;
+ }
+ }
+
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ if (Getattr(s, "csym:nextSibling")) {
+ /* overloaded using declarations and method declarations - don't chase the using declarations up the inheritance hierarchy */
+ break;
+ } else {
+ String *uname = Getattr(s, "uname");
+ Symtab *un = Getattr(s, "sym:symtab");
+ Node *ss = Swig_symbol_clookup_check(uname, un, checkfunc);
+ if (!ss && !checkfunc) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(uname));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_local()
+ *
+ * Same as Swig_symbol_clookup but parent nodes are not searched, that is, just
+ * this symbol table is searched.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_local(const_String_or_char_ptr name, Symtab *n) {
+ Hash *hsym;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ hsym = n;
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, 0);
+ } else {
+ s = symbol_lookup(nname, global_scope, 0);
+ }
+ Delete(nname);
+ } else {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, 0);
+ }
+ }
+ if (!s) {
+ s = symbol_lookup(name, hsym, 0);
+ }
+
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ if (Getattr(s, "csym:nextSibling")) {
+ /* overloaded using declarations and method declarations - don't chase the using declarations up the inheritance hierarchy */
+ break;
+ } else {
+ String *uname = Getattr(s, "uname");
+ Symtab *un = Getattr(s, "sym:symtab");
+ Node *ss = Swig_symbol_clookup_local(uname, un);
+ if (!ss) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(uname));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_local_check()
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_local_check(const_String_or_char_ptr name, Symtab *n, Node *(*checkfunc) (Node *)) {
+ Hash *hsym;
+ Node *s = 0;
+
+ if (!n) {
+ hsym = current_symtab;
+ } else {
+ if (!Checkattr(n, "nodeType", "symboltable")) {
+ n = Getattr(n, "sym:symtab");
+ }
+ assert(n);
+ hsym = n;
+ }
+
+ if (Swig_scopename_check(name)) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0) {
+ String *nname = NewString(cname + 2);
+ if (Swig_scopename_check(nname)) {
+ s = symbol_lookup_qualified(nname, global_scope, 0, 0, checkfunc);
+ } else {
+ s = symbol_lookup(nname, global_scope, checkfunc);
+ }
+ Delete(nname);
+ } else {
+ s = symbol_lookup_qualified(name, hsym, 0, 0, checkfunc);
+ }
+ }
+ if (!s) {
+ s = symbol_lookup(name, hsym, checkfunc);
+ }
+
+ /* Check if s is a 'using' node */
+ while (s && Checkattr(s, "nodeType", "using")) {
+ if (Getattr(s, "csym:nextSibling")) {
+ /* overloaded using declarations and method declarations - don't chase the using declarations up the inheritance hierarchy */
+ break;
+ } else {
+ String *uname = Getattr(s, "uname");
+ Symtab *un = Getattr(s, "sym:symtab");
+ Node *ss = Swig_symbol_clookup_local_check(uname, un, checkfunc);
+ if (!ss && !checkfunc) {
+ SWIG_WARN_NODE_BEGIN(s);
+ Swig_warning(WARN_PARSE_USING_UNDEF, Getfile(s), Getline(s), "Nothing known about '%s'.\n", SwigType_namestr(uname));
+ SWIG_WARN_NODE_END(s);
+ }
+ s = ss;
+ }
+ }
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_clookup_no_inherit()
+ *
+ * Symbol lookup like Swig_symbol_clookup but does not follow using directives.
+ * Using declarations are followed.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_clookup_no_inherit(const_String_or_char_ptr name, Symtab *n) {
+ Node *s = 0;
+ assert(use_inherit==1);
+ use_inherit = 0;
+ s = Swig_symbol_clookup(name, n);
+ use_inherit = 1;
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_cscope()
+ *
+ * Look up a scope name.
+ * ----------------------------------------------------------------------------- */
+
+Symtab *Swig_symbol_cscope(const_String_or_char_ptr name, Symtab *symtab) {
+ char *cname = Char(name);
+ if (strncmp(cname, "::", 2) == 0)
+ return symbol_lookup_qualified(0, global_scope, name, 0, 0);
+ return symbol_lookup_qualified(0, symtab, name, 0, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_remove()
+ *
+ * Remove a symbol. If the symbol is an overloaded function and the symbol removed
+ * is not the last in the list of overloaded functions, then the overloaded
+ * names (sym:overname attribute) are changed to start from zero, eg __SWIG_0.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_remove(Node *n) {
+ Symtab *symtab;
+ String *symname;
+ Node *symprev;
+ Node *symnext;
+ Node *fixovername = 0;
+ symtab = Getattr(n, "sym:symtab"); /* Get symbol table object */
+ symtab = Getattr(symtab, "symtab"); /* Get actual hash table of symbols */
+ symname = Getattr(n, "sym:name");
+ symprev = Getattr(n, "sym:previousSibling");
+ symnext = Getattr(n, "sym:nextSibling");
+
+ /* If previous symbol, just fix the links */
+ if (symprev) {
+ if (symnext) {
+ Setattr(symprev, "sym:nextSibling", symnext);
+ fixovername = symprev; /* fix as symbol to remove is somewhere in the middle of the linked list */
+ } else {
+ Delattr(symprev, "sym:nextSibling");
+ }
+ } else {
+ /* If no previous symbol, see if there is a next symbol */
+ if (symnext) {
+ Setattr(symtab, symname, symnext);
+ fixovername = symnext; /* fix as symbol to remove is at head of linked list */
+ } else {
+ if (symname)
+ Delattr(symtab, symname);
+ }
+ }
+ if (symnext) {
+ if (symprev) {
+ Setattr(symnext, "sym:previousSibling", symprev);
+ } else {
+ Delattr(symnext, "sym:previousSibling");
+ }
+ }
+ Delattr(n, "sym:symtab");
+ Delattr(n, "sym:previousSibling");
+ Delattr(n, "sym:nextSibling");
+ Delattr(n, "csym:nextSibling");
+ Delattr(n, "sym:overname");
+ Delattr(n, "csym:previousSibling");
+ Delattr(n, "sym:overloaded");
+
+ Swig_symbol_fix_overname(fixovername);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_fix_overname()
+ *
+ * Fix/update the sym:overname attribute for all the overloaded names.
+ * The sym:overname attributes are changed to start from zero, eg __SWIG_0.
+ * Call this when the linked lists for overloaded methods are modified.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_symbol_fix_overname(Node *n) {
+ if (n) {
+ Node *nn = n;
+ Node *head = n;
+ int pn = 0;
+
+ /* find head of linked list */
+ while (nn) {
+ head = nn;
+ nn = Getattr(nn, "sym:previousSibling");
+ }
+
+ /* adjust all the sym:overname strings to start from 0 and increment by one */
+ nn = head;
+ while (nn) {
+ String *overname = NewStringf("__SWIG_%d", pn);
+ Delattr(nn, "sym:overname");
+ Setattr(nn, "sym:overname", overname);
+ Delete(overname);
+ pn++;
+ nn = Getattr(nn, "sym:nextSibling");
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_qualified()
+ *
+ * Return the qualified name of a symbol
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_qualified(Node *n) {
+ Hash *symtab;
+ if (Checkattr(n, "nodeType", "symboltable")) {
+ symtab = n;
+ } else {
+ symtab = Getattr(n, "sym:symtab");
+ }
+ if (!symtab)
+ return NewStringEmpty();
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qscope %s %p %s\n", Getattr(n, "name"), symtab, Getattr(symtab, "name"));
+#endif
+ return Swig_symbol_qualifiedscopename(symtab);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_isoverloaded()
+ *
+ * Check if a symbol is overloaded. Returns the first symbol if so.
+ * ----------------------------------------------------------------------------- */
+
+Node *Swig_symbol_isoverloaded(Node *n) {
+ return Getattr(n, "sym:overloaded");
+}
+
+/* -----------------------------------------------------------------------------
+ * symbol_template_qualify()
+ *
+ * Internal function to create a fully qualified type name for templates
+ * ----------------------------------------------------------------------------- */
+
+/* This cache produces problems with OSS, don't active it */
+/* #define SWIG_TEMPLATE_QUALIFY_CACHE */
+static SwigType *symbol_template_qualify(const SwigType *e, Symtab *st) {
+ String *tprefix, *tsuffix;
+ SwigType *qprefix;
+ String *targs;
+ List *targslist;
+ Node *tempn;
+ Symtab *tscope;
+ Iterator ti;
+#ifdef SWIG_TEMPLATE_QUALIFY_CACHE
+ static Hash *qualify_cache = 0;
+ String *scopetype = st ? NewStringf("%s::%s", Getattr(st, "name"), e)
+ : NewStringf("%s::%s", Swig_symbol_getscopename(), e);
+ if (!qualify_cache) {
+ qualify_cache = NewHash();
+ }
+ if (scopetype) {
+ String *cres = Getattr(qualify_cache, scopetype);
+ if (cres) {
+ Delete(scopetype);
+ return Copy(cres);
+ }
+ }
+#endif
+
+ tprefix = SwigType_templateprefix(e);
+ tsuffix = SwigType_templatesuffix(e);
+ qprefix = Swig_symbol_type_qualify(tprefix, st);
+ targs = SwigType_templateargs(e);
+ targslist = SwigType_parmlist(targs);
+ tempn = Swig_symbol_clookup_local(tprefix, st);
+ tscope = tempn ? Getattr(tempn, "sym:symtab") : 0;
+ Append(qprefix, "<(");
+ for (ti = First(targslist); ti.item;) {
+ String *vparm;
+ /* TODO: the logic here should be synchronised with that in SwigType_typedef_qualified() */
+ /* TODO: ti.item might be a non-type parameter possibly within (), eg: (std::is_integral_v<(A)>||std::is_same_v<(A,node_t)>) */
+ String *qparm = Swig_symbol_type_qualify(ti.item, st);
+ if (tscope && (tscope != st)) {
+ String *ty = Swig_symbol_type_qualify(qparm, tscope);
+ Delete(qparm);
+ qparm = ty;
+ }
+
+ vparm = Swig_symbol_template_param_eval(qparm, st);
+ Append(qprefix, vparm);
+ ti = Next(ti);
+ if (ti.item) {
+ Putc(',', qprefix);
+ }
+ Delete(qparm);
+ Delete(vparm);
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(targs);
+ Delete(targslist);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_temp_qual %s %s\n", e, qprefix);
+#endif
+#ifdef SWIG_TEMPLATE_QUALIFY_CACHE
+ Setattr(qualify_cache, scopetype, qprefix);
+ Delete(scopetype);
+#endif
+
+ return qprefix;
+}
+
+
+static Node *symbol_no_constructor(Node *n) {
+ return Checkattr(n, "nodeType", "constructor") ? 0 : n;
+}
+
+static Node *symbol_is_template(Node *n) {
+ return Checkattr(n, "nodeType", "template") ? n : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_type_qualify()
+ *
+ * Create a fully qualified type name
+ * Note: Does not resolve a constructor if passed in as the 'type'.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_symbol_type_qualify(const SwigType *t, Symtab *st) {
+ List *elements;
+ String *result = NewStringEmpty();
+ int i, len;
+ char *c = Char(t);
+ if (strncmp(c, "::", 2) == 0) {
+ Append(result, t);
+ return result;
+ }
+
+ elements = SwigType_split(t);
+
+ len = Len(elements);
+ for (i = 0; i < len; i++) {
+ String *e = Getitem(elements, i);
+ if (SwigType_issimple(e)) {
+ /* Note: the unary scope operator (::) is being removed from the template parameters here. */
+ Node *n = Swig_symbol_clookup_check(e, st, symbol_no_constructor);
+ if (n) {
+ String *name = Getattr(n, "name");
+ Clear(e);
+ Append(e, name);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qual_ei %d %s %s %p\n", i, name, e, st);
+#endif
+ if (!Swig_scopename_check(name)) {
+ String *qname = Swig_symbol_qualified(n);
+ if (qname && Len(qname)) {
+ Insert(e, 0, "::");
+ Insert(e, 0, qname);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qual_sc %d %s %s %p\n", i, qname, e, st);
+#endif
+ Delete(qname);
+ }
+ } else if (SwigType_istemplate(e)) {
+ SwigType *ty = symbol_template_qualify(e, st);
+ Clear(e);
+ Append(e, ty);
+ Delete(ty);
+ }
+ if (strncmp(Char(e), "::", 2) == 0) {
+ Delitem(e, 0);
+ Delitem(e, 0);
+ }
+ Append(result, e);
+ } else if (SwigType_isfunction(e)) {
+ List *parms = SwigType_parmlist(e);
+ String *s = NewString("f(");
+ Iterator pi = First(parms);
+ while (pi.item) {
+ String *pf = Swig_symbol_type_qualify(pi.item, st);
+ Append(s, pf);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ Delete(pf);
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(parms);
+ Delete(s);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_qualify %s %s %p %s\n", t, result, st, st ? Getattr(st, "name") : 0);
+#endif
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_reduce()
+ * Resolves template parameter types
+ * For example:
+ * typedef int Int;
+ * typedef Int Integer;
+ * with input:
+ * Foo<(Int,Integer)>
+ * returns:
+ * Foo<(int,int)>
+ * ----------------------------------------------------------------------------- */
+
+static
+SwigType *Swig_symbol_template_reduce(SwigType *qt, Symtab *ntab) {
+ Parm *p;
+ String *templateargs = SwigType_templateargs(qt);
+ List *parms = SwigType_parmlist(templateargs);
+ Iterator pi = First(parms);
+ String *tprefix = SwigType_templateprefix(qt);
+ String *tsuffix = SwigType_templatesuffix(qt);
+ String *qprefix = SwigType_typedef_qualified(tprefix);
+ Append(qprefix, "<(");
+ while ((p = pi.item)) {
+ String *np;
+ String *tp = Swig_symbol_typedef_reduce(p, ntab);
+ String *qp = Swig_symbol_type_qualify(tp, ntab);
+ Node *n = Swig_symbol_clookup(qp, ntab);
+ if (n) {
+ String *qual = Swig_symbol_qualified(n);
+ np = Copy(Getattr(n, "name"));
+ Delete(tp);
+ tp = np;
+ if (qual && Len(qual)) {
+ Insert(np, 0, "::");
+ Insert(np, 0, qual);
+ }
+ Delete(qual);
+ } else {
+ np = qp;
+ }
+ Append(qprefix, np);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(qprefix, ",");
+ }
+ Delete(qp);
+ Delete(tp);
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(parms);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(templateargs);
+ return qprefix;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_typedef_reduce()
+ *
+ * Chase a typedef through symbol tables looking for a match.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab) {
+ SwigType *prefix, *base;
+ Node *n;
+ String *nt;
+
+ base = SwigType_base(ty);
+ prefix = SwigType_prefix(ty);
+
+ n = Swig_symbol_clookup(base, tab);
+ if (!n) {
+ if (SwigType_istemplate(base)) {
+ SwigType *qt = Swig_symbol_template_reduce(base, tab);
+ Append(prefix, qt);
+ Delete(qt);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (a) %s %s\n", ty, prefix);
+#endif
+ Delete(base);
+ return prefix;
+ } else {
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (b) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+ }
+ }
+ nt = Getattr(n, "nodeType");
+ if (Equal(nt, "using")) {
+ String *uname = Getattr(n, "uname");
+ if (uname) {
+ n = Swig_symbol_clookup(base, Getattr(n, "sym:symtab"));
+ if (!n) {
+ Delete(base);
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (c) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+ }
+ }
+ }
+ if (Equal(nt, "cdecl")) {
+ String *storage = Getattr(n, "storage");
+ if (storage && (Equal(storage, "typedef"))) {
+ SwigType *decl;
+ SwigType *rt;
+ SwigType *qt;
+ Symtab *ntab;
+ SwigType *nt = Copy(Getattr(n, "type"));
+
+ /* Fix for case 'typedef struct Hello hello;' */
+ {
+ const char *dclass[3] = { "struct ", "union ", "class " };
+ int i;
+ char *c = Char(nt);
+ for (i = 0; i < 3; i++) {
+ if (strstr(c, dclass[i]) == c) {
+ Replace(nt, dclass[i], "", DOH_REPLACE_FIRST);
+ }
+ }
+ }
+ decl = Getattr(n, "decl");
+ if (decl) {
+ SwigType_push(nt, decl);
+ }
+ SwigType_push(nt, prefix);
+ Delete(base);
+ Delete(prefix);
+ ntab = Getattr(n, "sym:symtab");
+ rt = Swig_symbol_typedef_reduce(nt, ntab);
+ qt = Swig_symbol_type_qualify(rt, ntab);
+ if (SwigType_istemplate(qt)) {
+ SwigType *qtr = Swig_symbol_template_reduce(qt, ntab);
+ Delete(qt);
+ qt = qtr;
+ }
+ Delete(nt);
+ Delete(rt);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (d) %s %s\n", qt, ty);
+#endif
+ return qt;
+ }
+ }
+ Delete(base);
+ Delete(prefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "symbol_reduce (e) %s %s\n", ty, ty);
+#endif
+ return Copy(ty);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_string_qualify()
+ *
+ * This function takes a string and looks for identifiers. Identifiers are
+ * then qualified according to scope rules. This function is used in a number
+ * of settings including expression evaluation, scoping of conversion operators,
+ * and so forth.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_symbol_string_qualify(String *s, Symtab *st) {
+ int have_id = 0;
+ String *id = NewStringEmpty();
+ String *r = NewStringEmpty();
+ char *c = Char(s);
+ int first_char = 1;
+ while (*c) {
+ if (isalpha((int) *c) || (*c == '_') || (*c == ':') || (*c == '~' && first_char) || (isdigit((int) *c) && !first_char)) {
+ Putc(*c, id);
+ have_id = 1;
+ } else {
+ if (have_id) {
+ String *qid = Swig_symbol_type_qualify(id, st);
+ Append(r, qid);
+ Clear(id);
+ Delete(qid);
+ have_id = 0;
+ }
+ Putc(*c, r);
+ }
+ first_char = (*c == ':');
+ c++;
+ }
+ if (have_id) {
+ String *qid = Swig_symbol_type_qualify(id, st);
+ Append(r, qid);
+ Delete(qid);
+ }
+ Delete(id);
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_defargs()
+ *
+ * Apply default arg from generic template default args
+ * Returns a parameter list which contains missing default arguments (if any)
+ * Note side effects: parms will also contain the extra parameters in its list
+ * (but only if non-zero).
+ * ----------------------------------------------------------------------------- */
+
+
+ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl) {
+ ParmList *expandedparms = parms;
+ if (Len(parms) < Len(targs)) {
+ Parm *lp = parms;
+ Parm *p = lp;
+ Parm *tp = targs;
+ while (p && tp) {
+ p = nextSibling(p);
+ tp = nextSibling(tp);
+ if (p)
+ lp = p;
+ }
+ while (tp) {
+ String *value = Getattr(tp, "value");
+ if (value) {
+ Parm *cp;
+ Parm *ta = targs;
+ Parm *p = parms;
+ SwigType *nt = Swig_symbol_string_qualify(value, tsdecl);
+ SwigType *ntq = 0;
+#ifdef SWIG_DEBUG
+ Printf(stderr, "value %s %s %s\n", value, nt, tsdecl ? Getattr(tsdecl, "name") : tsdecl);
+#endif
+ while (p && ta) {
+ String *name = Getattr(ta, "name");
+ String *pvalue = Getattr(p, "value");
+ String *value = pvalue ? pvalue : Getattr(p, "type");
+ String *ttq = Swig_symbol_type_qualify(value, tscope);
+ /* value = SwigType_typedef_resolve_all(value); */
+ Replaceid(nt, name, ttq);
+ p = nextSibling(p);
+ ta = nextSibling(ta);
+ Delete(ttq);
+ }
+ ntq = Swig_symbol_type_qualify(nt, tsdecl);
+ if (SwigType_istemplate(ntq)) {
+ String *ty = Swig_symbol_template_deftype(ntq, tscope);
+ Delete(ntq);
+ ntq = ty;
+ }
+ cp = NewParmWithoutFileLineInfo(ntq, 0);
+ if (lp) {
+ set_nextSibling(lp, cp);
+ Delete(cp);
+ } else {
+ expandedparms = cp;
+ }
+ lp = cp;
+ tp = nextSibling(tp);
+ Delete(nt);
+ Delete(ntq);
+ } else {
+ tp = 0;
+ }
+ }
+ }
+ return expandedparms;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_template_deftype()
+ *
+ * Apply default args to generic template type
+ * Return input type with template args expanded to include default template args
+ * ----------------------------------------------------------------------------- */
+
+#define SWIG_TEMPLATE_DEFTYPE_CACHE
+SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope) {
+ String *result = NewStringEmpty();
+ List *elements = SwigType_split(type);
+ int len = Len(elements);
+ int i;
+#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
+ static Hash *s_cache = 0;
+ Hash *scope_cache;
+ /* The lookup depends on the current scope and potential namespace qualification.
+ Looking up x in namespace y is not the same as looking up x::y in outer scope.
+ -> we use a 2-level hash: first scope and then symbol. */
+ String *scope_name = tscope
+ ? Swig_symbol_qualifiedscopename(tscope)
+ : Swig_symbol_qualifiedscopename(current_symtab);
+ String *type_name = tscope
+ ? NewStringf("%s::%s", Getattr(tscope, "name"), type)
+ : NewStringf("%s::%s", Swig_symbol_getscopename(), type);
+ if (!scope_name) scope_name = NewString("::");
+ if (!s_cache) {
+ s_cache = NewHash();
+ }
+ scope_cache = Getattr(s_cache, scope_name);
+ if (scope_cache) {
+ String *cres = Getattr(scope_cache, type_name);
+ if (cres) {
+ Append(result, cres);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "cached deftype %s(%s) -> %s\n", type, scope_name, result);
+#endif
+ Delete(type_name);
+ Delete(scope_name);
+ return result;
+ }
+ } else {
+ scope_cache = NewHash();
+ Setattr(s_cache, scope_name, scope_cache);
+ Delete(scope_name);
+ }
+#endif
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "finding deftype %s\n", type);
+#endif
+
+ for (i = 0; i < len; i++) {
+ String *e = Getitem(elements, i);
+ if (SwigType_isfunction(e)) {
+ String *s = NewString("f(");
+ List *parms = SwigType_parmlist(e);
+ Iterator pi = First(parms);
+ while (pi.item) {
+ String *pf = SwigType_istemplate(e) ? Swig_symbol_template_deftype(pi.item, tscope)
+ : Swig_symbol_type_qualify(pi.item, tscope);
+ Append(s, pf);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ Delete(pf);
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(s);
+ Delete(parms);
+ } else if (SwigType_istemplate(e)) {
+ String *prefix = SwigType_prefix(e);
+ String *base = SwigType_base(e);
+ String *tprefix = SwigType_templateprefix(base);
+ String *targs = SwigType_templateargs(base);
+ String *tsuffix = SwigType_templatesuffix(base);
+ ParmList *tparms = SwigType_function_parms(targs, 0);
+ Node *tempn = Swig_symbol_clookup_local_check(tprefix, tscope, symbol_is_template);
+ if (!tempn && tsuffix && Len(tsuffix)) {
+ tempn = Swig_symbol_clookup_check(tprefix, 0, symbol_is_template);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype type %s %s %d\n", e, tprefix, (long) tempn);
+#endif
+ if (tempn) {
+ ParmList *tnargs = Getattr(tempn, "templateparms");
+ ParmList *expandedparms;
+ Parm *p;
+ Symtab *tsdecl = Getattr(tempn, "sym:symtab");
+
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype type %s %s %s\n", tprefix, targs, tsuffix);
+#endif
+ Append(tprefix, "<(");
+ expandedparms = Swig_symbol_template_defargs(tparms, tnargs, tscope, tsdecl);
+ p = expandedparms;
+ tscope = tsdecl;
+ while (p) {
+ SwigType *ptype = Getattr(p, "type");
+ SwigType *ttr = ptype ? ptype : Getattr(p, "value");
+ SwigType *ttf = Swig_symbol_type_qualify(ttr, tscope);
+ SwigType *ttq = Swig_symbol_template_param_eval(ttf, tscope);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "arg type %s\n", ttq);
+#endif
+ if (SwigType_istemplate(ttq)) {
+ SwigType *ttd = Swig_symbol_template_deftype(ttq, tscope);
+ Delete(ttq);
+ ttq = ttd;
+#ifdef SWIG_DEBUG
+ Printf(stderr, "arg deftype %s\n", ttq);
+#endif
+ }
+ Append(tprefix, ttq);
+ p = nextSibling(p);
+ if (p)
+ Putc(',', tprefix);
+ Delete(ttf);
+ Delete(ttq);
+ }
+ Append(tprefix, ")>");
+ Append(tprefix, tsuffix);
+ Append(prefix, tprefix);
+#ifdef SWIG_DEBUG
+ Printf(stderr, "deftype %s %s \n", type, tprefix);
+#endif
+ Append(result, prefix);
+ } else {
+ Append(result, e);
+ }
+ Delete(prefix);
+ Delete(base);
+ Delete(tprefix);
+ Delete(tsuffix);
+ Delete(targs);
+ Delete(tparms);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+#ifdef SWIG_TEMPLATE_DEFTYPE_CACHE
+ Setattr(scope_cache, type_name, result);
+ Delete(type_name);
+#endif
+
+ return result;
+}
+
+SwigType *Swig_symbol_template_param_eval(const SwigType *p, Symtab *symtab) {
+ String *value = Copy(p);
+ Node *lastnode = 0;
+ while (1) {
+ Node *n = Swig_symbol_clookup(value, symtab);
+ if (n == lastnode)
+ break;
+ lastnode = n;
+ if (n) {
+ String *nt = Getattr(n, "nodeType");
+ if (Equal(nt, "enumitem")) {
+ /* An enum item. Generate a fully qualified name */
+ String *qn = Swig_symbol_qualified(n);
+ if (qn && Len(qn)) {
+ Append(qn, "::");
+ Append(qn, Getattr(n, "name"));
+ Delete(value);
+ value = qn;
+ continue;
+ } else {
+ Delete(qn);
+ break;
+ }
+ } else if ((Equal(nt, "cdecl"))) {
+ String *nv = Getattr(n, "value");
+ if (nv) {
+ Delete(value);
+ value = Copy(nv);
+ continue;
+ }
+ }
+ }
+ break;
+ }
+ return value;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_symbol_isvalid()
+ *
+ * Checks that s is a valid C symbol
+ * ----------------------------------------------------------------------------- */
+
+int Swig_symbol_isvalid(const String *s) {
+ int valid = 0;
+ const char *c = Char(s);
+ if (c) {
+ valid = isalpha((int)*c) || (*c == '_');
+ while (valid && *++c) {
+ valid = isalnum((int)*c) || (*c == '_');
+ }
+ }
+ return valid;
+}
diff --git a/contrib/tools/swig/Source/Swig/tree.c b/contrib/tools/swig/Source/Swig/tree.c
new file mode 100644
index 00000000000..e0cf1a58f41
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/tree.c
@@ -0,0 +1,430 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * tree.c
+ *
+ * This file provides some general purpose functions for manipulating
+ * parse trees.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <stdarg.h>
+#include <assert.h>
+
+static int debug_quiet = 0;
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_quiet()
+ *
+ * Set quiet mode when printing a parse tree node
+ * ----------------------------------------------------------------------------- */
+
+int Swig_print_quiet(int quiet) {
+ int previous_quiet = debug_quiet;
+ debug_quiet = quiet;
+ return previous_quiet;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_tags()
+ *
+ * Dump the tag structure of a parse tree to standard output
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_tags(DOH *obj, DOH *root) {
+ DOH *croot, *newroot;
+ DOH *cobj;
+
+ if (!root)
+ croot = NewStringEmpty();
+ else
+ croot = root;
+
+ while (obj) {
+ Swig_diagnostic(Getfile(obj), Getline(obj), "%s . %s\n", croot, nodeType(obj));
+ cobj = firstChild(obj);
+ if (cobj) {
+ newroot = NewStringf("%s . %s", croot, nodeType(obj));
+ Swig_print_tags(cobj, newroot);
+ Delete(newroot);
+ }
+ obj = nextSibling(obj);
+ }
+ if (!root)
+ Delete(croot);
+}
+
+static int indent_level = 0;
+
+static void print_indent(int l) {
+ int i;
+ for (i = 0; i < indent_level; i++) {
+ fputc(' ', stdout);
+ }
+ if (l) {
+ fputc('|', stdout);
+ fputc(' ', stdout);
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_node(Node *n)
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_node(Node *obj) {
+ Iterator ki;
+ Node *cobj;
+ List *keys = Keys(obj);
+
+ print_indent(0);
+ if (debug_quiet)
+ Printf(stdout, "+++ %s ----------------------------------------\n", nodeType(obj));
+ else
+ Printf(stdout, "+++ %s - %p ----------------------------------------\n", nodeType(obj), obj);
+
+ SortList(keys, 0);
+ ki = First(keys);
+ while (ki.item) {
+ String *k = ki.item;
+ DOH *value = Getattr(obj, k);
+ if (Equal(k, "nodeType") || (*(Char(k)) == '$')) {
+ /* Do nothing */
+ } else if (debug_quiet && (Equal(k, "firstChild") || Equal(k, "lastChild") || Equal(k, "parentNode") || Equal(k, "nextSibling") ||
+ Equal(k, "previousSibling") || Equal(k, "symtab") || Equal(k, "csymtab") || Equal(k, "sym:symtab") || Equal(k, "sym:nextSibling") ||
+ Equal(k, "sym:previousSibling") || Equal(k, "csym:nextSibling") || Equal(k, "csym:previousSibling"))) {
+ /* Do nothing */
+ } else if (Equal(k, "kwargs") || Equal(k, "parms") || Equal(k, "wrap:parms") || Equal(k, "pattern") || Equal(k, "templateparms") || Equal(k, "templateparmsraw") || Equal(k, "template_parameters") || Equal(k, "throws")) {
+ print_indent(2);
+ /* Differentiate parameter lists by displaying within single quotes */
+ Printf(stdout, "%-12s - \'%s\'\n", k, ParmList_str_defaultargs(value));
+ } else {
+ DOH *o;
+ const char *trunc = "";
+ print_indent(2);
+ if (DohIsString(value)) {
+ o = Str(value);
+ if (Len(o) > 80) {
+ trunc = "...";
+ }
+ Printf(stdout, "%-12s - \"%(escape)-0.80s%s\"\n", k, o, trunc);
+ Delete(o);
+/*
+ } else if (DohIsSequence(value)) {
+ Printf(stdout, "%-12s - %s\n", k, value);
+*/
+ } else {
+ Printf(stdout, "%-12s - %p\n", k, value);
+ }
+ }
+ ki = Next(ki);
+ }
+ cobj = firstChild(obj);
+ if (cobj) {
+ indent_level += 6;
+ Printf(stdout, "\n");
+ Swig_print_tree(cobj);
+ indent_level -= 6;
+ } else {
+ print_indent(1);
+ Printf(stdout, "\n");
+ }
+ Delete(keys);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print_tree()
+ *
+ * Dump the tree structure of a parse tree to standard output
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_tree(DOH *obj) {
+ while (obj) {
+ Swig_print_node(obj);
+ obj = nextSibling(obj);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * appendChild()
+ *
+ * Appends a new child to a node
+ * ----------------------------------------------------------------------------- */
+
+void appendChild(Node *node, Node *chd) {
+ Node *lc;
+
+ if (!chd)
+ return;
+
+ lc = lastChild(node);
+ if (!lc) {
+ set_firstChild(node, chd);
+ } else {
+ set_nextSibling(lc, chd);
+ set_previousSibling(chd, lc);
+ }
+ while (chd) {
+ lc = chd;
+ set_parentNode(chd, node);
+ chd = nextSibling(chd);
+ }
+ set_lastChild(node, lc);
+}
+
+/* -----------------------------------------------------------------------------
+ * prependChild()
+ *
+ * Prepends a new child to a node
+ * ----------------------------------------------------------------------------- */
+
+void prependChild(Node *node, Node *chd) {
+ Node *fc;
+
+ if (!chd)
+ return;
+
+ fc = firstChild(node);
+ if (fc) {
+ set_nextSibling(chd, fc);
+ set_previousSibling(fc, chd);
+ }
+ set_firstChild(node, chd);
+ while (chd) {
+ set_parentNode(chd, node);
+ chd = nextSibling(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()
+ *
+ * Removes a node from the parse tree. Detaches it from its parent's child list.
+ * ----------------------------------------------------------------------------- */
+
+void removeNode(Node *n) {
+ Node *parent;
+ Node *prev;
+ Node *next;
+
+ parent = parentNode(n);
+ if (!parent) return;
+
+ prev = previousSibling(n);
+ next = nextSibling(n);
+ if (prev) {
+ set_nextSibling(prev, next);
+ } else {
+ if (parent) {
+ set_firstChild(parent, next);
+ }
+ }
+ if (next) {
+ set_previousSibling(next, prev);
+ } else {
+ if (parent) {
+ set_lastChild(parent, prev);
+ }
+ }
+
+ /* Delete attributes */
+ Delattr(n,"parentNode");
+ Delattr(n,"nextSibling");
+ Delattr(n,"previousSibling");
+}
+
+/* -----------------------------------------------------------------------------
+ * copyNode()
+ *
+ * Copies a node, but only copies simple attributes (no lists, hashes).
+ * ----------------------------------------------------------------------------- */
+
+Node *copyNode(Node *n) {
+ Iterator ki;
+ Node *c = NewHash();
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (DohIsString(ki.item)) {
+ Setattr(c, ki.key, Copy(ki.item));
+ }
+ }
+ Setfile(c, Getfile(n));
+ Setline(c, Getline(n));
+ return c;
+}
+
+/* -----------------------------------------------------------------------------
+ * checkAttribute()
+ * ----------------------------------------------------------------------------- */
+
+int checkAttribute(Node *n, const_String_or_char_ptr name, const_String_or_char_ptr value) {
+ String *v = Getattr(n, name);
+ return v ? Equal(v, value) : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_require()
+ * ns - namespace for the view name for saving any attributes under
+ * n - node
+ * ... - list of attribute names of type char*
+ *
+ * An attribute is optional if it is prefixed by ?, eg "?value". All
+ * non-optional attributes are checked for on node n and if any do not exist
+ * SWIG exits with a fatal error.
+ *
+ * If the attribute name is prefixed by * or ?, eg "*value" then a copy of the
+ * attribute is saved. The saved attributes will be restored on a subsequent
+ * call to Swig_restore(). All the saved attributes are saved in the view
+ * namespace (prefixed by ns).
+ *
+ * This function can be called more than once with different namespaces.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_require(const char *ns, Node *n, ...) {
+ va_list ap;
+ char *name;
+ DOH *obj;
+
+ va_start(ap, n);
+ name = va_arg(ap, char *);
+ while (name) {
+ int newref = 0;
+ int opt = 0;
+ if (*name == '*') {
+ newref = 1;
+ name++;
+ } else if (*name == '?') {
+ newref = 1;
+ opt = 1;
+ name++;
+ }
+ obj = Getattr(n, name);
+ if (!opt && !obj) {
+ Swig_error(Getfile(n), Getline(n), "Fatal error (Swig_require). Missing attribute '%s' in node '%s'.\n", name, nodeType(n));
+ Exit(EXIT_FAILURE);
+ }
+ if (!obj)
+ obj = None;
+ if (newref) {
+ /* Save a copy of the attribute */
+ Setattr(n, NewStringf("%s:%s", ns, name), obj);
+ }
+ name = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ /* Save the view */
+ {
+ String *view = Getattr(n, "view");
+ if (view) {
+ if (Strcmp(view, ns) != 0) {
+ Setattr(n, NewStringf("%s:view", ns), view);
+ Setattr(n, "view", NewString(ns));
+ }
+ } else {
+ Setattr(n, "view", NewString(ns));
+ }
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_save()
+ * Same as Swig_require(), but all attribute names are optional and all attributes
+ * are saved, ie behaves as if all the attribute names were prefixed by ?.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_save(const char *ns, Node *n, ...) {
+ va_list ap;
+ char *name;
+ DOH *obj;
+
+ va_start(ap, n);
+ name = va_arg(ap, char *);
+ while (name) {
+ if (*name == '*') {
+ name++;
+ } else if (*name == '?') {
+ name++;
+ }
+ obj = Getattr(n, name);
+ if (!obj)
+ obj = None;
+
+ /* Save a copy of the attribute */
+ if (Setattr(n, NewStringf("%s:%s", ns, name), obj)) {
+ Printf(stderr, "Swig_save('%s','%s'): Warning, attribute '%s' was already saved.\n", ns, nodeType(n), name);
+ }
+ name = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ /* Save the view */
+ {
+ String *view = Getattr(n, "view");
+ if (view) {
+ if (Strcmp(view, ns) != 0) {
+ Setattr(n, NewStringf("%s:view", ns), view);
+ Setattr(n, "view", NewString(ns));
+ }
+ } else {
+ Setattr(n, "view", NewString(ns));
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_restore()
+ * Restores attributes saved by a previous call to Swig_require() or Swig_save().
+ * ----------------------------------------------------------------------------- */
+
+void Swig_restore(Node *n) {
+ String *temp;
+ int len;
+ List *l;
+ String *ns;
+ Iterator ki;
+
+ ns = Getattr(n, "view");
+ assert(ns);
+
+ l = NewList();
+
+ temp = NewStringf("%s:", ns);
+ len = Len(temp);
+
+ for (ki = First(n); ki.key; ki = Next(ki)) {
+ if (Strncmp(temp, ki.key, len) == 0) {
+ Append(l, ki.key);
+ }
+ }
+ for (ki = First(l); ki.item; ki = Next(ki)) {
+ DOH *obj = Getattr(n, ki.item);
+ Setattr(n, Char(ki.item) + len, obj);
+ Delattr(n, ki.item);
+ }
+ Delete(l);
+ Delete(temp);
+}
diff --git a/contrib/tools/swig/Source/Swig/typemap.c b/contrib/tools/swig/Source/Swig/typemap.c
new file mode 100644
index 00000000000..3294bdf778f
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/typemap.c
@@ -0,0 +1,2227 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * typemap.c
+ *
+ * A somewhat generalized implementation of SWIG1.1 typemaps.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+#include <ctype.h>
+
+#if 0
+#define SWIG_DEBUG
+#endif
+
+static int typemap_search_debug = 0;
+static int typemaps_used_debug = 0;
+static int typemap_register_debug = 0;
+static int in_typemap_search_multi = 0;
+
+static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f, Node *file_line_node);
+
+/* -----------------------------------------------------------------------------
+ * Typemaps are stored in a collection of nested hash tables. Something like
+ * this:
+ *
+ * [ type ]
+ * +-------- [ name ]
+ * +-------- [ name ]
+ *
+ * Each hash table [ type ] or [ name ] then contains references to the
+ * different typemap methods. These are referenced by names such as
+ * "tmap:in", "tmap:out", "tmap:argout", and so forth.
+ *
+ * The object corresponding to a specific typemap method has the following attributes:
+ *
+ * "type" - Typemap type
+ * "pname" - Parameter name
+ * "code" - Typemap code
+ * "source" - Source directive (%apply or %typemap) for the typemap
+ * "locals" - Local variables (if any)
+ * "kwargs" - Typemap attributes
+ *
+ * Example for a typemap method named "in":
+ * %typemap(in, warning="987:my warning", noblock=1) int &my_int (int tmp) "$1 = $input;"
+ *
+ * "type" - r.int
+ * "pname" - my_int
+ * "code" - $1 = $input;
+ * "source" - typemap(in) int &my_int
+ * "locals" - int tmp
+ * "kwargs" - warning="987:my typemap warning", foo=123
+ *
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemaps;
+
+/* -----------------------------------------------------------------------------
+ * typemap_identifier_fix()
+ *
+ * Create a type that can be used as a hash key lookup independent of the various
+ * ways a template parameter list can be defined. This is achieved by fully
+ * resolving the template parameters.
+ *
+ * This is a copy and modification of feature_identifier_fix in parser.y.
+ * ----------------------------------------------------------------------------- */
+
+static SwigType *typemap_identifier_fix(const SwigType *s) {
+ String *tp = SwigType_istemplate_templateprefix(s);
+ if (tp) {
+ String *ts, *ta, *tq, *tr;
+ ts = SwigType_templatesuffix(s);
+ ta = SwigType_templateargs(s);
+ tq = Swig_symbol_type_qualify(ta, 0);
+ tr = SwigType_typedef_resolve_all(ta);
+ Append(tp,tr);
+ Append(tp,ts);
+ Delete(ts);
+ Delete(ta);
+ Delete(tq);
+ Delete(tr);
+ return tp;
+ } else {
+ return NewString(s);
+ }
+}
+
+static Hash *get_typemap(const SwigType *type) {
+ Hash *tm = 0;
+ SwigType *dtype = 0;
+ SwigType *hashtype;
+
+ if (SwigType_istemplate(type)) {
+ SwigType *rty = typemap_identifier_fix(type);
+ String *ty = Swig_symbol_template_deftype(rty, 0);
+ dtype = Swig_symbol_type_qualify(ty, 0);
+ type = dtype;
+ Delete(ty);
+ Delete(rty);
+ }
+
+ /* remove unary scope operator (::) prefix indicating global scope for looking up in the hashmap */
+ hashtype = SwigType_remove_global_scope_prefix(type);
+ tm = Getattr(typemaps, hashtype);
+
+ Delete(dtype);
+ Delete(hashtype);
+
+ return tm;
+}
+
+static void set_typemap(const SwigType *type, Hash **tmhash) {
+ SwigType *hashtype = 0;
+ Hash *new_tm = 0;
+ assert(*tmhash == 0);
+ if (SwigType_istemplate(type)) {
+ SwigType *rty = typemap_identifier_fix(type);
+ String *ty = Swig_symbol_template_deftype(rty, 0);
+ String *tyq = Swig_symbol_type_qualify(ty, 0);
+ hashtype = SwigType_remove_global_scope_prefix(tyq);
+ *tmhash = Getattr(typemaps, hashtype);
+ Delete(rty);
+ Delete(tyq);
+ Delete(ty);
+ } else {
+ hashtype = SwigType_remove_global_scope_prefix(type);
+ }
+
+ if (!*tmhash) {
+ /* this type has not been seen before even after resolving template parameter types */
+ new_tm = NewHash();
+ *tmhash = new_tm;
+ }
+
+ /* note that the unary scope operator (::) prefix indicating global scope has been removed from the type */
+ Setattr(typemaps, hashtype, *tmhash);
+
+ Delete(hashtype);
+ Delete(new_tm);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_init()
+ *
+ * Initialize the typemap system
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_init(void) {
+ typemaps = NewHash();
+}
+
+static String *typemap_method_name(const_String_or_char_ptr tmap_method) {
+ static Hash *names = 0;
+ String *s;
+ /* Due to "interesting" object-identity semantics of DOH,
+ we have to make sure that we only intern strings without object
+ identity into the hash table.
+
+ (typemap_attach_kwargs calls typemap_method_name several times with
+ the "same" String *tmap_method (i.e., same object identity) but differing
+ string values.)
+
+ Most other callers work around this by using char* rather than
+ String *.
+ -- mkoeppe, Jun 17, 2003
+ */
+ const char *method_without_object_identity = Char(tmap_method);
+ if (!names)
+ names = NewHash();
+ s = Getattr(names, method_without_object_identity);
+ if (s)
+ return s;
+ s = NewStringf("tmap:%s", tmap_method);
+ Setattr(names, method_without_object_identity, s);
+ Delete(s);
+ return s;
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_register()
+ *
+ * Internal implementation for Swig_typemap_register()
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs, String *source_directive) {
+ Hash *tm;
+ Hash *tm1;
+ Hash *tm2;
+ Parm *np;
+ String *tm_method;
+ SwigType *type;
+ String *pname;
+ if (!parms)
+ return;
+
+ if (typemap_register_debug) {
+ Printf(stdout, "Registering - %s\n", tmap_method);
+ Swig_print_node(parms);
+ }
+
+ tm_method = typemap_method_name(tmap_method);
+
+ /* Register the first type in the parameter list */
+
+ type = Getattr(parms, "type");
+ pname = Getattr(parms, "name");
+
+ /* See if this type has been seen before */
+ tm = get_typemap(type);
+ if (!tm) {
+ set_typemap(type, &tm);
+ }
+ if (pname) {
+ /* See if parameter has been seen before */
+ tm1 = Getattr(tm, pname);
+ if (!tm1) {
+ tm1 = NewHash();
+ Setattr(tm, pname, tm1);
+ Delete(tm1);
+ }
+ tm = tm1;
+ }
+
+ /* Now see if this typemap method has been seen before */
+ tm2 = Getattr(tm, tm_method);
+ if (!tm2) {
+ tm2 = NewHash();
+ Setattr(tm, tm_method, tm2);
+ Delete(tm2);
+ }
+
+ /* For a multi-argument typemap, the typemap code and information
+ is really only stored in the last argument. However, to
+ make this work, we perform a really neat trick using
+ the typemap method name.
+
+ For example, consider this typemap
+
+ %typemap(in) (int foo, int *bar, char *blah[]) {
+ ...
+ }
+
+ To store it, we look at typemaps for the following:
+
+ typemap method type-name
+ ----------------------------------------------
+ "in" int foo
+ "in-int+foo:" int *bar
+ "in-int+foo:-p.int+bar: char *blah[]
+
+ Notice how the typemap method name expands to encode information about
+ previous arguments.
+
+ */
+
+ np = nextSibling(parms);
+ if (np) {
+ /* Make an entirely new typemap method key */
+ String *multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, pname);
+
+ /* Now reregister on the remaining arguments */
+ typemap_register(multi_tmap_method, np, code, locals, kwargs, source_directive);
+
+ Delete(multi_tmap_method);
+ } else {
+ ParmList *clocals = CopyParmList(locals);
+ ParmList *ckwargs = CopyParmList(kwargs);
+
+ Setfile(tm2, Getfile(code));
+ Setline(tm2, Getline(code));
+ Setattr(tm2, "code", code);
+ Setattr(tm2, "type", type);
+ Setattr(tm2, "source", source_directive);
+ if (pname) {
+ Setattr(tm2, "pname", pname);
+ }
+ Setattr(tm2, "locals", clocals);
+ Setattr(tm2, "kwargs", ckwargs);
+
+ Delete(clocals);
+ Delete(ckwargs);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_register()
+ *
+ * Add a new, possibly multi-argument, typemap
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) {
+ String *parms_str = ParmList_str_multibrackets(parms);
+ String *source_directive = NewStringf("typemap(%s) %s", tmap_method, parms_str);
+
+ typemap_register(tmap_method, parms, code, locals, kwargs, source_directive);
+
+ Delete(source_directive);
+ Delete(parms_str);
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_get()
+ *
+ * Retrieve typemap information.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_get(SwigType *type, const_String_or_char_ptr name) {
+ Hash *tm, *tm1;
+ tm = get_typemap(type);
+ if (!tm) {
+ return 0;
+ }
+ if ((name) && Len(name)) {
+ tm1 = Getattr(tm, name);
+ return tm1;
+ }
+ return tm;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_copy()
+ *
+ * Copy a typemap
+ * ----------------------------------------------------------------------------- */
+
+int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, ParmList *parms) {
+ Hash *tm = 0;
+ String *tm_method;
+ Parm *p;
+ String *pname;
+ SwigType *ptype;
+ String *tm_methods, *multi_tmap_method;
+ if (ParmList_len(parms) != ParmList_len(srcparms))
+ return -1;
+
+ tm_method = typemap_method_name(tmap_method);
+ p = srcparms;
+ tm_methods = NewString(tm_method);
+ while (p) {
+ ptype = Getattr(p, "type");
+ pname = Getattr(p, "name");
+
+ /* Lookup the type */
+ tm = typemap_get(ptype, pname);
+ if (!tm)
+ break;
+
+ tm = Getattr(tm, tm_methods);
+ if (!tm)
+ break;
+
+ /* Got a match. Look for next typemap */
+ multi_tmap_method = NewStringf("%s-%s+%s:", tm_methods, ptype, pname);
+ Delete(tm_methods);
+ tm_methods = multi_tmap_method;
+ p = nextSibling(p);
+ }
+ Delete(tm_methods);
+
+ if (!p && tm) {
+ /* Got some kind of match */
+ String *parms_str = ParmList_str_multibrackets(parms);
+ String *srcparms_str = ParmList_str_multibrackets(srcparms);
+ String *source_directive = NewStringf("typemap(%s) %s = %s", tmap_method, parms_str, srcparms_str);
+
+ typemap_register(tmap_method, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"), source_directive);
+
+ Delete(source_directive);
+ Delete(srcparms_str);
+ Delete(parms_str);
+ return 0;
+ }
+
+ /* Not found */
+ return -1;
+
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_clear()
+ *
+ * Delete a multi-argument typemap
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *parms) {
+ SwigType *type;
+ String *name;
+ Parm *p;
+ String *multi_tmap_method;
+ Hash *tm = 0;
+
+ /* This might not work */
+ multi_tmap_method = NewString(tmap_method);
+ p = parms;
+ while (p) {
+ type = Getattr(p, "type");
+ name = Getattr(p, "name");
+ tm = typemap_get(type, name);
+ if (!tm)
+ return;
+ p = nextSibling(p);
+ if (p)
+ Printf(multi_tmap_method, "-%s+%s:", type, name);
+ }
+ if (tm) {
+ tm = Getattr(tm, typemap_method_name(multi_tmap_method));
+ if (tm) {
+ Delattr(tm, "code");
+ Delattr(tm, "locals");
+ Delattr(tm, "kwargs");
+ }
+ }
+ Delete(multi_tmap_method);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_apply()
+ *
+ * Multi-argument %apply directive. This is pretty horrible so I sure hope
+ * it works.
+ * ----------------------------------------------------------------------------- */
+
+static int count_args(String *s) {
+ /* Count up number of arguments */
+ int na = 0;
+ char *c = Char(s);
+ while (*c) {
+ if (*c == '+')
+ na++;
+ c++;
+ }
+ return na;
+}
+
+int Swig_typemap_apply(ParmList *src, ParmList *dest) {
+ String *ssig, *dsig;
+ Parm *p, *np, *lastp, *dp, *lastdp = 0;
+ int narg = 0;
+ SwigType *type = 0, *name;
+ Hash *tm, *sm;
+ int match = 0;
+
+ /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */
+
+ /* Create type signature of source */
+ ssig = NewStringEmpty();
+ dsig = NewStringEmpty();
+ p = src;
+ dp = dest;
+ lastp = 0;
+ while (p) {
+ lastp = p;
+ lastdp = dp;
+ np = nextSibling(p);
+ if (np) {
+ Printf(ssig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
+ Printf(dsig, "-%s+%s:", Getattr(dp, "type"), Getattr(dp, "name"));
+ narg++;
+ }
+ p = np;
+ dp = nextSibling(dp);
+ }
+
+ /* make sure a typemap node exists for the last destination node */
+ type = Getattr(lastdp, "type");
+ tm = get_typemap(type);
+ if (!tm) {
+ set_typemap(type, &tm);
+ }
+ name = Getattr(lastdp, "name");
+ if (name) {
+ Hash *tm1 = Getattr(tm, name);
+ if (!tm1) {
+ tm1 = NewHash();
+ Setattr(tm, NewString(name), tm1);
+ Delete(tm1);
+ }
+ tm = tm1;
+ }
+
+ /* This is a little nasty. We need to go searching for all possible typemaps in the
+ source and apply them to the target */
+
+ type = Getattr(lastp, "type");
+ name = Getattr(lastp, "name");
+
+ /* See if there is a matching typemap in this scope */
+ sm = typemap_get(type, name);
+
+ /* if there is not matching, look for a typemap in the
+ original typedef, if any, like in:
+
+ typedef unsigned long size_t;
+ ...
+ %apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size};
+ */
+ if (!sm) {
+ SwigType *ntype = SwigType_typedef_resolve(type);
+ if (ntype && (Cmp(ntype, type) != 0)) {
+ sm = typemap_get(ntype, name);
+ }
+ Delete(ntype);
+ }
+
+ if (sm) {
+ /* Got a typemap. Need to only merge attributes for methods that match our signature */
+ Iterator ki;
+ Hash *deferred_add;
+ match = 1;
+
+ /* Since typemap_register can modify the `sm` hash, we *cannot* call typemap_register while iterating over sm.
+ * Create a temporary hash of typemaps to add immediately after. */
+ deferred_add = NewHash();
+ for (ki = First(sm); ki.key; ki = Next(ki)) {
+ /* Check for a signature match with the source signature */
+ if ((count_args(ki.key) == narg) && (Strstr(ki.key, ssig))) {
+ String *oldm;
+ /* A typemap we have to copy */
+ String *nkey = Copy(ki.key);
+ Replace(nkey, ssig, dsig, DOH_REPLACE_ANY);
+
+ /* Make sure the typemap doesn't already exist in the target map */
+ oldm = Getattr(tm, nkey);
+ if (!oldm || (!Getattr(tm, "code"))) {
+ String *code;
+ Hash *sm1 = ki.item;
+
+ code = Getattr(sm1, "code");
+ if (code) {
+ Replace(nkey, dsig, "", DOH_REPLACE_ANY);
+ Replace(nkey, "tmap:", "", DOH_REPLACE_ANY);
+ Setattr(deferred_add, nkey, sm1);
+ }
+ }
+ Delete(nkey);
+ }
+ }
+
+ /* After assembling the key/item pairs, add the resulting typemaps */
+ for (ki = First(deferred_add); ki.key; ki = Next(ki)) {
+ Hash *sm1 = ki.item;
+ String *src_str = ParmList_str_multibrackets(src);
+ String *dest_str = ParmList_str_multibrackets(dest);
+ String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str);
+
+ typemap_register(ki.key, dest, Getattr(sm1, "code"), Getattr(sm1, "locals"), Getattr(sm1, "kwargs"), source_directive);
+
+ Delete(source_directive);
+ Delete(dest_str);
+ Delete(src_str);
+ }
+ Delete(deferred_add);
+ }
+ Delete(ssig);
+ Delete(dsig);
+ return match;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_clear_apply()
+ *
+ * %clear directive. Clears all typemaps for a type (in the current scope only).
+ * ----------------------------------------------------------------------------- */
+
+/* Multi-argument %clear directive */
+void Swig_typemap_clear_apply(Parm *parms) {
+ String *tsig;
+ Parm *p, *np, *lastp;
+ int narg = 0;
+ Hash *tm;
+ String *name;
+
+ /* Create a type signature of the parameters */
+ tsig = NewStringEmpty();
+ p = parms;
+ lastp = 0;
+ while (p) {
+ lastp = p;
+ np = nextSibling(p);
+ if (np) {
+ Printf(tsig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
+ narg++;
+ }
+ p = np;
+ }
+ tm = get_typemap(Getattr(lastp, "type"));
+ if (!tm) {
+ Delete(tsig);
+ return;
+ }
+ name = Getattr(lastp, "name");
+ if (name) {
+ tm = Getattr(tm, name);
+ }
+ if (tm) {
+ /* Clear typemaps that match our signature */
+ Iterator ki, ki2;
+ char *ctsig = Char(tsig);
+ for (ki = First(tm); ki.key; ki = Next(ki)) {
+ char *ckey = Char(ki.key);
+ if (strncmp(ckey, "tmap:", 5) == 0) {
+ int na = count_args(ki.key);
+ if ((na == narg) && strstr(ckey, ctsig)) {
+ Hash *h = ki.item;
+ for (ki2 = First(h); ki2.key; ki2 = Next(ki2)) {
+ Delattr(h, ki2.key);
+ }
+ }
+ }
+ }
+ }
+ Delete(tsig);
+}
+
+/* Internal function to strip array dimensions. */
+static SwigType *strip_arrays(SwigType *type) {
+ SwigType *t;
+ int ndim;
+ int i;
+ t = Copy(type);
+ ndim = SwigType_array_ndim(t);
+ for (i = 0; i < ndim; i++) {
+ SwigType_array_setdim(t, i, "ANY");
+ }
+ return t;
+}
+
+static void debug_search_result_display(Node *tm) {
+ if (tm)
+ Printf(stdout, " Using: %%%s\n", Getattr(tm, "source"));
+ else
+ Printf(stdout, " None found\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_search_helper()
+ *
+ * Helper function for typemap_search to see if there is a type match in the typemap
+ * tm. A match is sought in this order:
+ * %typemap(tm_method) ctype cqualifiedname
+ * %typemap(tm_method) ctype cname
+ * %typemap(tm_method) ctype
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_search_helper(int debug_display, Hash *tm, const String *tm_method, SwigType *ctype, const String *cqualifiedname, const String *cname, Hash **backup) {
+ Hash *result = 0;
+ Hash *tm1;
+ if (debug_display && cqualifiedname)
+ Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cqualifiedname));
+ if (tm && cqualifiedname) {
+ tm1 = Getattr(tm, cqualifiedname);
+ if (tm1) {
+ result = Getattr(tm1, tm_method); /* See if there is a type - qualified name match */
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ if (result)
+ *backup = result;
+ }
+ }
+ if (debug_display && cname)
+ Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, cname));
+ if (tm && cname) {
+ tm1 = Getattr(tm, cname);
+ if (tm1) {
+ result = Getattr(tm1, tm_method); /* See if there is a type - name match */
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ if (result)
+ *backup = result;
+ }
+ }
+ if (debug_display)
+ Printf(stdout, " Looking for: %s\n", SwigType_str(ctype, 0));
+ if (tm) {
+ result = Getattr(tm, tm_method); /* See if there is simply a type without name match */
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ if (result)
+ *backup = result;
+ }
+ret_result:
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_search()
+ *
+ * Search for a typemap match. This is where the typemap pattern matching rules
+ * are implemented... tries to find the most specific typemap that includes a
+ * 'code' attribute.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, const_String_or_char_ptr qualifiedname, SwigType **matchtype, Node *node) {
+ Hash *result = 0;
+ Hash *tm;
+ Hash *backup = 0;
+ SwigType *primitive = 0;
+ SwigType *ctype = 0;
+ SwigType *ctype_unstripped = 0;
+ int isarray;
+ const String *cname = 0;
+ const String *cqualifiedname = 0;
+ String *tm_method = typemap_method_name(tmap_method);
+ int debug_display = (in_typemap_search_multi == 0) && typemap_search_debug;
+
+ if ((name) && Len(name))
+ cname = name;
+ if ((qualifiedname) && Len(qualifiedname))
+ cqualifiedname = qualifiedname;
+
+ if (debug_display) {
+ String *typestr = SwigType_str(type, cqualifiedname ? cqualifiedname : cname);
+ Swig_diagnostic(Getfile(node), Getline(node), "Searching for a suitable '%s' typemap for: %s\n", tmap_method, typestr);
+ Delete(typestr);
+ }
+ ctype = Copy(type);
+ ctype_unstripped = Copy(ctype);
+ while (ctype) {
+ /* Try to get an exact type-match */
+ tm = get_typemap(ctype);
+ result = typemap_search_helper(debug_display, tm, tm_method, ctype, cqualifiedname, cname, &backup);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+
+ {
+ /* Look for the type reduced to just the template prefix - for templated types without the template parameter list being specified */
+ SwigType *template_prefix = SwigType_istemplate_only_templateprefix(ctype);
+ if (template_prefix) {
+ tm = get_typemap(template_prefix);
+ result = typemap_search_helper(debug_display, tm, tm_method, template_prefix, cqualifiedname, cname, &backup);
+ Delete(template_prefix);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ }
+ }
+
+ /* look for [ANY] arrays */
+ isarray = SwigType_isarray(ctype);
+ if (isarray) {
+ /* If working with arrays, strip away all of the dimensions and replace with "ANY".
+ See if that generates a match */
+ SwigType *noarrays = strip_arrays(ctype);
+ tm = get_typemap(noarrays);
+ result = typemap_search_helper(debug_display, tm, tm_method, noarrays, cqualifiedname, cname, &backup);
+ Delete(noarrays);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+ }
+
+ /* No match so far - try with a qualifier stripped (strip one qualifier at a time until none remain)
+ * The order of stripping in SwigType_strip_single_qualifier is used to provide some sort of consistency
+ * with the default (SWIGTYPE) typemap matching rules for the first qualifier to be stripped. */
+ {
+ SwigType *oldctype = ctype;
+ ctype = SwigType_strip_single_qualifier(oldctype);
+ if (!Equal(ctype, oldctype)) {
+ Delete(oldctype);
+ continue;
+ }
+ Delete(oldctype);
+ }
+
+ /* Once all qualifiers are stripped try resolve a typedef */
+ {
+ SwigType *oldctype = ctype;
+ ctype = SwigType_typedef_resolve(ctype_unstripped);
+ Delete(oldctype);
+ Delete(ctype_unstripped);
+ ctype_unstripped = Copy(ctype);
+ }
+ }
+
+ /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default (SWIGTYPE) mapping */
+
+ primitive = SwigType_default_create(type);
+ while (primitive) {
+ tm = get_typemap(primitive);
+ result = typemap_search_helper(debug_display, tm, tm_method, primitive, cqualifiedname, cname, &backup);
+ if (result && Getattr(result, "code"))
+ goto ret_result;
+
+ {
+ SwigType *nprim = SwigType_default_deduce(primitive);
+ Delete(primitive);
+ primitive = nprim;
+ }
+ }
+ if (ctype != type) {
+ Delete(ctype);
+ ctype = 0;
+ }
+ result = backup;
+
+ret_result:
+ Delete(primitive);
+ if (matchtype)
+ *matchtype = Copy(ctype);
+ Delete(ctype);
+ Delete(ctype_unstripped);
+ return result;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * typemap_search_multi()
+ *
+ * Search for a multi-argument typemap.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList *parms, int *nmatch) {
+ SwigType *type;
+ SwigType *mtype = 0;
+ String *name;
+ String *multi_tmap_method;
+ Hash *tm;
+ Hash *tm1 = 0;
+
+ if (!parms) {
+ *nmatch = 0;
+ return 0;
+ }
+ type = Getattr(parms, "type");
+ name = Getattr(parms, "name");
+
+ /* Try to find a match on the first type */
+ tm = typemap_search(tmap_method, type, name, 0, &mtype, parms);
+ if (tm) {
+ if (mtype && SwigType_isarray(mtype)) {
+ Setattr(parms, "tmap:match", mtype);
+ }
+ Delete(mtype);
+ multi_tmap_method = NewStringf("%s-%s+%s:", tmap_method, type, name);
+ in_typemap_search_multi++;
+ tm1 = typemap_search_multi(multi_tmap_method, nextSibling(parms), nmatch);
+ in_typemap_search_multi--;
+ if (tm1)
+ tm = tm1;
+ if (Getattr(tm, "code")) {
+ *(nmatch) = *nmatch + 1;
+ if (typemap_search_debug && tm1 && (in_typemap_search_multi == 0)) {
+ Printf(stdout, " Multi-argument typemap found...\n");
+ }
+ } else {
+ tm = 0;
+ }
+ Delete(multi_tmap_method);
+ }
+
+ if (typemap_search_debug && (in_typemap_search_multi == 0))
+ debug_search_result_display(tm);
+ if (typemaps_used_debug && (in_typemap_search_multi == 0) && tm) {
+ String *typestr = SwigType_str(type, name);
+ Swig_diagnostic(Getfile(parms), Getline(parms), "Typemap for %s (%s) : %%%s\n", typestr, tmap_method, Getattr(tm, "source"));
+ assert(Getfile(parms) && Len(Getfile(parms)) > 0); /* Missing file and line numbering information */
+ Delete(typestr);
+ }
+
+ return tm;
+}
+
+
+static void replace_local_types(ParmList *p, const String *name, const String *rep) {
+ SwigType *t;
+ while (p) {
+ t = Getattr(p, "type");
+ Replace(t, name, rep, DOH_REPLACE_ANY);
+ p = nextSibling(p);
+ }
+}
+
+static int check_locals(ParmList *p, const char *s) {
+ while (p) {
+ char *c = GetChar(p, "type");
+ if (strstr(c, s))
+ return 1;
+ p = nextSibling(p);
+ }
+ return 0;
+}
+
+static int replace_with_override(String *src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags, Hash *override_vars) {
+ String *override_replace = override_vars ? Getattr(override_vars, token) : NULL;
+ if (override_replace)
+ return Replace(src, token, override_replace, flags);
+ return Replace(src, token, rep, flags);
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_replace_vars()
+ *
+ * Replaces typemap variables in a string. index is the $n variable.
+ * type and pname are the type and parameter name.
+ * override_vars are only used to replace variable names (NOT types), so is only
+ * used for $n, but not the various ways of representing types: $n_ltype, $n_type etc
+ * ----------------------------------------------------------------------------- */
+
+static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index, Hash *override_vars) {
+ char var[512];
+ char *varname;
+ SwigType *ftype;
+ int bare_substitution_count = 0;
+
+ Replaceall(s, "$typemap", "$TYPEMAP"); /* workaround for $type substitution below */
+
+ ftype = SwigType_typedef_resolve_all(type);
+
+ if (!pname)
+ pname = lname;
+ {
+ Parm *p;
+ int rep = 0;
+ p = locals;
+ while (p) {
+ if (Strchr(Getattr(p, "type"), '$'))
+ rep = 1;
+ p = nextSibling(p);
+ }
+ if (!rep)
+ locals = 0;
+ }
+
+ sprintf(var, "$%d_", index);
+ varname = &var[strlen(var)];
+
+ /* If the original datatype was an array. We're going to go through and substitute
+ its array dimensions */
+
+ if (SwigType_isarray(type) || SwigType_isarray(ftype)) {
+ String *size;
+ int ndim;
+ int i;
+ if (SwigType_array_ndim(type) != SwigType_array_ndim(ftype))
+ type = ftype;
+ ndim = SwigType_array_ndim(type);
+ size = NewStringEmpty();
+ for (i = 0; i < ndim; i++) {
+ String *dim = SwigType_array_getdim(type, i);
+ if (index == 1) {
+ char t[32];
+ sprintf(t, "$dim%d", i);
+ Replace(s, t, dim, DOH_REPLACE_ANY);
+ replace_local_types(locals, t, dim);
+ }
+ sprintf(varname, "dim%d", i);
+ Replace(s, var, dim, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, dim);
+ if (Len(size))
+ Putc('*', size);
+ Append(size, dim);
+ Delete(dim);
+ }
+ sprintf(varname, "size");
+ Replace(s, var, size, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, size);
+ Delete(size);
+ }
+
+ /* Parameter name substitution */
+ if (index == 1) {
+ Replace(s, "$parmname", pname, DOH_REPLACE_ANY);
+ }
+ strcpy(varname, "name");
+ Replace(s, var, pname, DOH_REPLACE_ANY);
+
+ /* Type-related stuff */
+ {
+ SwigType *star_type, *amp_type, *base_type, *lex_type;
+ SwigType *ltype, *star_ltype, *amp_ltype;
+ String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name, *base_type_str;
+ String *descriptor, *star_descriptor, *amp_descriptor;
+ String *ts;
+ char *sc;
+
+ sc = Char(s);
+
+ if (strstr(sc, "type") || check_locals(locals, "type")) {
+ /* Given type : $type */
+ ts = SwigType_str(type, 0);
+ if (index == 1) {
+ Replace(s, "$type", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$type", type);
+ }
+ strcpy(varname, "type");
+ Replace(s, var, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, type);
+ Delete(ts);
+ sc = Char(s);
+ }
+ if (strstr(sc, "ltype") || check_locals(locals, "ltype")) {
+ /* Local type: $ltype */
+ ltype = SwigType_ltype(type);
+ ts = SwigType_str(ltype, 0);
+ if (index == 1) {
+ Replace(s, "$ltype", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$ltype", ltype);
+ }
+ strcpy(varname, "ltype");
+ Replace(s, var, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, ltype);
+ Delete(ts);
+ Delete(ltype);
+ sc = Char(s);
+ }
+ if (strstr(sc, "mangle") || strstr(sc, "descriptor")) {
+ /* Mangled type */
+
+ mangle = SwigType_manglestr(type);
+ if (index == 1)
+ Replace(s, "$mangle", mangle, DOH_REPLACE_ANY);
+ strcpy(varname, "mangle");
+ Replace(s, var, mangle, DOH_REPLACE_ANY);
+
+ descriptor = NewStringf("SWIGTYPE%s", mangle);
+
+ if (index == 1)
+ if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(type);
+
+ strcpy(varname, "descriptor");
+ if (Replace(s, var, descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(type);
+
+ Delete(descriptor);
+ Delete(mangle);
+ }
+
+ /* One pointer level removed */
+ /* This creates variables of the form
+ $*n_type
+ $*n_ltype
+ */
+
+ if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype)) || (SwigType_isrvalue_reference(ftype))) {
+ if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type) || SwigType_isrvalue_reference(type))) {
+ star_type = Copy(ftype);
+ } else {
+ star_type = Copy(type);
+ }
+ if (!(SwigType_isreference(star_type) || SwigType_isrvalue_reference(star_type))) {
+ if (SwigType_isarray(star_type)) {
+ SwigType_del_element(star_type);
+ } else {
+ SwigType_del_pointer(star_type);
+ }
+ ts = SwigType_str(star_type, 0);
+ if (index == 1) {
+ Replace(s, "$*type", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$*type", star_type);
+ }
+ sprintf(varname, "$*%d_type", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, star_type);
+ Delete(ts);
+ } else {
+ SwigType_del_element(star_type);
+ }
+ star_ltype = SwigType_ltype(star_type);
+ ts = SwigType_str(star_ltype, 0);
+ if (index == 1) {
+ Replace(s, "$*ltype", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$*ltype", star_ltype);
+ }
+ sprintf(varname, "$*%d_ltype", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, star_ltype);
+ Delete(ts);
+ Delete(star_ltype);
+
+ star_mangle = SwigType_manglestr(star_type);
+ if (index == 1)
+ Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY);
+
+ sprintf(varname, "$*%d_mangle", index);
+ Replace(s, varname, star_mangle, DOH_REPLACE_ANY);
+
+ star_descriptor = NewStringf("SWIGTYPE%s", star_mangle);
+ if (index == 1)
+ if (Replace(s, "$*descriptor", star_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(star_type);
+ sprintf(varname, "$*%d_descriptor", index);
+ if (Replace(s, varname, star_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(star_type);
+
+ Delete(star_descriptor);
+ Delete(star_mangle);
+ Delete(star_type);
+ } else {
+ /* TODO: Signal error if one of the $* substitutions is
+ requested */
+ }
+ /* One pointer level added */
+ amp_type = Copy(type);
+ SwigType_add_pointer(amp_type);
+ ts = SwigType_str(amp_type, 0);
+ if (index == 1) {
+ Replace(s, "$&type", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$&type", amp_type);
+ }
+ sprintf(varname, "$&%d_type", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, amp_type);
+ Delete(ts);
+
+ amp_ltype = SwigType_ltype(type);
+ SwigType_add_pointer(amp_ltype);
+ ts = SwigType_str(amp_ltype, 0);
+
+ if (index == 1) {
+ Replace(s, "$&ltype", ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$&ltype", amp_ltype);
+ }
+ sprintf(varname, "$&%d_ltype", index);
+ Replace(s, varname, ts, DOH_REPLACE_ANY);
+ replace_local_types(locals, varname, amp_ltype);
+ Delete(ts);
+ Delete(amp_ltype);
+
+ amp_mangle = SwigType_manglestr(amp_type);
+ if (index == 1)
+ Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY);
+ sprintf(varname, "$&%d_mangle", index);
+ Replace(s, varname, amp_mangle, DOH_REPLACE_ANY);
+
+ amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle);
+ if (index == 1)
+ if (Replace(s, "$&descriptor", amp_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(amp_type);
+ sprintf(varname, "$&%d_descriptor", index);
+ if (Replace(s, varname, amp_descriptor, DOH_REPLACE_ANY))
+ SwigType_remember(amp_type);
+
+ Delete(amp_descriptor);
+ Delete(amp_mangle);
+ Delete(amp_type);
+
+ /* Base type */
+ if (SwigType_isarray(type)) {
+ base_type = Copy(type);
+ Delete(SwigType_pop_arrays(base_type));
+ } else {
+ base_type = SwigType_base(type);
+ }
+
+ base_type_str = SwigType_str(base_type, 0);
+ base_name = SwigType_namestr(base_type_str);
+ if (index == 1) {
+ Replace(s, "$basetype", base_name, DOH_REPLACE_ANY);
+ replace_local_types(locals, "$basetype", base_name);
+ }
+ strcpy(varname, "basetype");
+ Replace(s, var, base_type_str, DOH_REPLACE_ANY);
+ replace_local_types(locals, var, base_name);
+
+ base_mangle = SwigType_manglestr(base_type);
+ if (index == 1)
+ Replace(s, "$basemangle", base_mangle, DOH_REPLACE_ANY);
+ strcpy(varname, "basemangle");
+ Replace(s, var, base_mangle, DOH_REPLACE_ANY);
+ Delete(base_mangle);
+ Delete(base_name);
+ Delete(base_type_str);
+ Delete(base_type);
+
+ lex_type = SwigType_base(rtype);
+ if (index == 1)
+ Replace(s, "$lextype", lex_type, DOH_REPLACE_ANY);
+ strcpy(varname, "lextype");
+ Replace(s, var, lex_type, DOH_REPLACE_ANY);
+ Delete(lex_type);
+ }
+
+ /* Replace variable usage $n. with (&$n)-> */
+ {
+ char temp[64];
+ sprintf(var, "$%d.", index);
+ sprintf(temp, "(&$%d)->", index);
+ Replace(s, var, temp, DOH_REPLACE_ANY);
+ }
+
+ /* Replace the bare $n variable */
+ sprintf(var, "$%d", index);
+ bare_substitution_count = replace_with_override(s, var, lname, DOH_REPLACE_NUMBER_END, override_vars);
+ Delete(ftype);
+ return bare_substitution_count;
+}
+
+/* ------------------------------------------------------------------------
+ * static typemap_locals()
+ *
+ * Takes a string, a parameter list and a wrapper function argument and
+ * creates the local variables.
+ * ------------------------------------------------------------------------ */
+
+static void typemap_locals(String *s, ParmList *l, Wrapper *f, int argnum) {
+ Parm *p;
+ char *new_name;
+
+ p = l;
+ while (p) {
+ SwigType *pt = Getattr(p, "type");
+ SwigType *at = SwigType_alttype(pt, 1);
+ String *pn = Getattr(p, "name");
+ String *value = Getattr(p, "value");
+ if (at)
+ pt = at;
+ if (pn) {
+ if (Len(pn) > 0) {
+ String *str;
+ int isglobal = 0;
+
+ str = NewStringEmpty();
+
+ if (strncmp(Char(pn), "_global_", 8) == 0) {
+ isglobal = 1;
+ }
+
+ /* If the user gave us $type as the name of the local variable, we'll use
+ the passed datatype instead */
+
+ if ((argnum >= 0) && (!isglobal)) {
+ Printf(str, "%s%d", pn, argnum);
+ } else {
+ Append(str, pn);
+ }
+ if (isglobal && Wrapper_check_local(f, str)) {
+ p = nextSibling(p);
+ Delete(str);
+ if (at)
+ Delete(at);
+ continue;
+ }
+ if (value) {
+ String *pstr = SwigType_str(pt, str);
+ new_name = Wrapper_new_localv(f, str, pstr, "=", value, NIL);
+ Delete(pstr);
+ } else {
+ String *pstr = SwigType_str(pt, str);
+ new_name = Wrapper_new_localv(f, str, pstr, NIL);
+ Delete(pstr);
+ }
+ if (!isglobal) {
+ /* Substitute */
+ Replace(s, pn, new_name, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
+ }
+ Delete(str);
+ }
+ }
+ p = nextSibling(p);
+ if (at)
+ Delete(at);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_warn()
+ *
+ * If any warning message is attached to this parameter's "tmap:<method>:warning"
+ * attribute, return the warning message (special variables will need expanding
+ * before displaying the warning).
+ * ----------------------------------------------------------------------------- */
+
+static String *typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) {
+ String *temp = NewStringf("%s:warning", tmap_method);
+ String *w = Getattr(p, typemap_method_name(temp));
+ Delete(temp);
+ return w ? Copy(w) : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_merge_fragment_kwargs()
+ *
+ * If multiple 'fragment' attributes are provided to a typemap, combine them by
+ * concatenating with commas.
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_merge_fragment_kwargs(Parm *kw) {
+ Parm *reattach_kw = NULL;
+ Parm *prev_kw = NULL;
+ Parm *next_kw = NULL;
+ String *fragment = NULL;
+ while (kw) {
+ next_kw = nextSibling(kw);
+ if (Strcmp(Getattr(kw, "name"), "fragment") == 0) {
+ String *thisfragment = Getattr(kw, "value");
+ String *kwtype = Getattr(kw, "type");
+ if (!fragment) {
+ /* First fragment found; it should remain in the list */
+ fragment = thisfragment;
+ prev_kw = kw;
+ } else {
+ /* Concatenate to previously found fragment */
+ Printv(fragment, ",", thisfragment, NULL);
+ reattach_kw = prev_kw;
+ }
+ if (kwtype) {
+ String *mangle = Swig_name_mangle_type(kwtype);
+ Append(fragment, mangle);
+ Delete(mangle);
+ /* Remove 'type' from kwargs so it's not duplicated later */
+ Setattr(kw, "type", NULL);
+ }
+ } else {
+ /* Not a fragment */
+ if (reattach_kw) {
+ /* Update linked list to remove duplicate fragment */
+ DohIncref(kw);
+ set_nextSibling(reattach_kw, kw);
+ set_previousSibling(kw, reattach_kw);
+ Delete(reattach_kw);
+ reattach_kw = NULL;
+ }
+ prev_kw = kw;
+ }
+ kw = next_kw;
+ }
+ if (reattach_kw) {
+ /* Update linked list to remove duplicate fragment */
+ set_nextSibling(reattach_kw, kw);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_lookup()
+ *
+ * Attach one or more typemaps to a node and optionally generate the typemap contents
+ * into the wrapper.
+ *
+ * Looks for a typemap matching the given type and name and attaches the typemap code
+ * and any typemap attributes to the provided node.
+ *
+ * The node should contain the "type" and "name" attributes for the typemap match on.
+ * input. The typemap code and typemap attribute values are attached onto the node
+ * prefixed with "tmap:". For example with tmap_method="in", the typemap code can be retrieved
+ * with a call to Getattr(node, "tmap:in") (this is also the string returned) and the
+ * "noblock" attribute can be retrieved with a call to Getattr(node, "tmap:in:noblock").
+ *
+ * tmap_method - typemap method, eg "in", "out", "newfree"
+ * node - the node to attach the typemap and typemap attributes to
+ * lname - name of variable to substitute $1, $2 etc for
+ * f - wrapper code to generate into if non null
+ * actioncode - code to generate into f before the out typemap code, unless
+ * the optimal attribute is set in the out typemap in which case
+ * $1 in the out typemap will be replaced by the code in actioncode.
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
+ SwigType *type;
+ SwigType *mtype = 0;
+ String *pname;
+ String *qpname = 0;
+ String *noscope_pname = 0;
+ Hash *tm = 0;
+ String *s = 0;
+ String *sdef = 0;
+ String *warning = 0;
+ ParmList *locals;
+ ParmList *kw;
+ char temp[256];
+ String *symname;
+ String *cname = 0;
+ String *clname = 0;
+ char *cmethod = Char(tmap_method);
+ int optimal_attribute = 0;
+ int optimal_substitution = 0;
+ int delete_optimal_attribute = 0;
+ int num_substitutions = 0;
+ SwigType *matchtype = 0;
+
+ type = Getattr(node, "type");
+ if (!type)
+ return sdef;
+
+ /* Special hook (hack!). Check for the 'ref' feature and add code it contains to any 'newfree' typemap code.
+ * We could choose to put this hook into a number of different typemaps, not necessarily 'newfree'...
+ * Rather confusingly 'newfree' is used to release memory and the 'ref' feature is used to add in memory references - yuck! */
+ if (Cmp(tmap_method, "newfree") == 0) {
+ String *base = SwigType_base(type);
+ Node *typenode = Swig_symbol_clookup(base, 0);
+ if (typenode)
+ sdef = Swig_ref_call(typenode, lname);
+ Delete(base);
+ }
+
+ pname = Getattr(node, "name");
+ noscope_pname = Copy(pname);
+
+ if (pname && Getattr(node, "sym:symtab")) {
+ /* Add on a qualified name search for any symbol in the symbol table, for example:
+ * struct Foo {
+ * int *foo(int bar) -> Foo::foo
+ * };
+ * Note that if node is a parameter (Parm *) then there will be no symbol table attached to the Parm *.
+ */
+ String *qsn;
+ if (Swig_scopename_check(pname)) {
+ /* sometimes pname is qualified, so we remove all the scope for the lookup */
+ Delete(noscope_pname);
+ noscope_pname = Swig_scopename_last(pname);
+ /*
+ Printf(stdout, "Removed scope: %s => %s\n", pname, noscope_pname);
+ */
+ }
+ qsn = Swig_symbol_qualified(node);
+ if (qsn && Len(qsn)) {
+ qpname = NewStringf("%s::%s", qsn, noscope_pname);
+ Delete(qsn);
+ }
+ }
+
+ tm = typemap_search(tmap_method, type, noscope_pname, qpname, &mtype, node);
+ if (typemap_search_debug)
+ debug_search_result_display(tm);
+ if (typemaps_used_debug && tm) {
+ String *typestr = SwigType_str(type, qpname ? qpname : pname);
+ Swig_diagnostic(Getfile(node), Getline(node), "Typemap for %s (%s) : %%%s\n", typestr, tmap_method, Getattr(tm, "source"));
+ assert(Getfile(node) && Len(Getfile(node)) > 0); /* Missing file and line numbering information */
+ Delete(typestr);
+ }
+
+ Delete(qpname);
+ qpname = 0;
+ Delete(noscope_pname);
+ noscope_pname = 0;
+
+ if (!tm)
+ return sdef;
+
+ s = Getattr(tm, "code");
+ if (!s)
+ return sdef;
+
+ /* Empty typemap. No match */
+ if (Cmp(s, "pass") == 0)
+ return sdef;
+
+ s = Copy(s); /* Make a local copy of the typemap code */
+
+ /* Look in the "out" typemap for the "optimal" attribute */
+ if (Cmp(cmethod, "out") == 0) {
+ kw = Getattr(tm, "kwargs");
+ while (kw) {
+ if (Cmp(Getattr(kw, "name"), "optimal") == 0) {
+ optimal_attribute = GetFlag(kw, "value");
+ break;
+ }
+ kw = nextSibling(kw);
+ }
+ }
+
+ if (optimal_attribute) {
+ /* Note: "out" typemap is the only typemap that will have the "optimal" attribute set.
+ * If f and actioncode are NULL, then the caller is just looking to attach the "out" attributes
+ * ie, not use the typemap code, otherwise both f and actioncode must be non null. */
+ if (actioncode) {
+ const String *result_equals = NewStringf("%s = ", Swig_cresult_name());
+ /* check that the code in the typemap can be used in this optimal way.
+ * The code should be in the form "result = ...;\n". We need to extract
+ * the "..." part. This may not be possible for various reasons, eg
+ * code added by %exception. This optimal code generation is bit of a
+ * hack and circumvents the normal requirement for a temporary variable
+ * to hold the result returned from a wrapped function call.
+ */
+ if (Strncmp(actioncode, result_equals, Len(result_equals)) == 0 &&
+ Strchr(actioncode, ';') == Char(actioncode) + Len(actioncode) - 2 &&
+ Char(actioncode)[Len(actioncode) - 1] == '\n') {
+ clname = NewStringWithSize(Char(actioncode) + Len(result_equals),
+ Len(actioncode) - Len(result_equals) - 2);
+ lname = clname;
+ actioncode = 0;
+ optimal_substitution = 1;
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute ignored\n", Swig_name_decl(node));
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(s), Getline(s), "in the out typemap as the following cannot be used to generate optimal code: %s\n", actioncode);
+ delete_optimal_attribute = 1;
+ }
+ } else {
+ assert(!f);
+ }
+ }
+
+ if (actioncode) {
+ assert(f);
+ Append(f->code, actioncode);
+ }
+
+ /* emit local variables declared in typemap, eg emit declarations for aa and bb in:
+ * %typemap(in) foo (int aa, int bb) "..." */
+ locals = Getattr(tm, "locals");
+ if (locals)
+ locals = CopyParmList(locals);
+
+ if (pname) {
+ if (SwigType_istemplate(pname)) {
+ cname = SwigType_namestr(pname);
+ pname = cname;
+ }
+ }
+ if (SwigType_istemplate((char *) lname)) {
+ clname = SwigType_namestr((char *) lname);
+ lname = clname;
+ }
+
+ matchtype = mtype && SwigType_isarray(mtype) ? mtype : type;
+ num_substitutions = typemap_replace_vars(s, locals, matchtype, type, pname, (char *) lname, 1, NULL);
+ if (optimal_substitution && num_substitutions > 1) {
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to\n", Swig_name_decl(node));
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(s), Getline(s), "optimal attribute usage in the out typemap.\n");
+ }
+
+ if (locals && f) {
+ typemap_locals(s, locals, f, -1);
+ }
+
+ {
+ ParmList *parm_sublist = NewParmWithoutFileLineInfo(type, pname);
+ Setattr(parm_sublist, "lname", lname);
+ replace_embedded_typemap(s, parm_sublist, f, tm);
+ Delete(parm_sublist);
+ }
+
+ /* Attach kwargs - ie the typemap attributes */
+ kw = Getattr(tm, "kwargs");
+ typemap_merge_fragment_kwargs(kw);
+ while (kw) {
+ String *value = Copy(Getattr(kw, "value"));
+ String *kwtype = Getattr(kw, "type");
+ char *ckwname = Char(Getattr(kw, "name"));
+ {
+ /* Expand special variables in typemap attributes. */
+ SwigType *ptype = Getattr(node, "type");
+ String *pname = Getattr(node, "name");
+ SwigType *mtype = Getattr(node, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : ptype;
+ ParmList *parm_sublist;
+ typemap_replace_vars(value, NULL, matchtype, ptype, pname, (char *)lname, 1, NULL);
+
+ /* Expand special variable macros (embedded typemaps) in typemap attributes. */
+ parm_sublist = NewParmWithoutFileLineInfo(ptype, pname);
+ Setattr(parm_sublist, "lname", lname);
+ replace_embedded_typemap(value, parm_sublist, NULL, tm);
+ Delete(parm_sublist);
+ }
+ if (kwtype) {
+ String *mangle = Swig_name_mangle_type(kwtype);
+ Append(value, mangle);
+ Delete(mangle);
+ }
+ sprintf(temp, "%s:%s", cmethod, ckwname);
+ Setattr(node, typemap_method_name(temp), value);
+ Delete(value);
+ kw = nextSibling(kw);
+ }
+
+ if (delete_optimal_attribute)
+ Delattr(node, "tmap:out:optimal");
+
+ Replace(s, "$name", pname, DOH_REPLACE_ANY);
+
+ symname = Getattr(node, "sym:name");
+ if (symname)
+ Replace(s, "$symname", symname, DOH_REPLACE_ANY);
+
+ Setattr(node, typemap_method_name(tmap_method), s);
+ if (locals) {
+ sprintf(temp, "%s:locals", cmethod);
+ Setattr(node, typemap_method_name(temp), locals);
+ Delete(locals);
+ }
+
+ if (Checkattr(tm, "type", "SWIGTYPE")) {
+ sprintf(temp, "%s:SWIGTYPE", cmethod);
+ Setattr(node, typemap_method_name(temp), "1");
+ }
+
+ /* Print warnings, if any */
+ warning = typemap_warn(cmethod, node);
+ if (warning) {
+ typemap_replace_vars(warning, 0, matchtype, type, pname, (char *) lname, 1, NULL);
+ Replace(warning, "$name", pname, DOH_REPLACE_ANY);
+ if (symname)
+ Replace(warning, "$symname", symname, DOH_REPLACE_ANY);
+ Swig_warning(0, Getfile(node), Getline(node), "%s\n", warning);
+ Delete(warning);
+ }
+
+ /* Look for code fragments */
+ {
+ String *fragment;
+ sprintf(temp, "%s:fragment", cmethod);
+ fragment = Getattr(node, typemap_method_name(temp));
+ if (fragment) {
+ String *fname = Copy(fragment);
+ Setfile(fname, Getfile(node));
+ Setline(fname, Getline(node));
+ Swig_fragment_emit(fname);
+ Delete(fname);
+ }
+ }
+
+ Delete(cname);
+ Delete(clname);
+ Delete(mtype);
+ if (sdef) { /* put 'ref' and 'newfree' codes together */
+ String *p = NewStringf("%s\n%s", sdef, s);
+ Delete(s);
+ Delete(sdef);
+ s = p;
+ }
+ Delete(actioncode);
+ return s;
+}
+
+String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
+ assert(actioncode);
+ assert(Cmp(tmap_method, "out") == 0);
+ return Swig_typemap_lookup_impl(tmap_method, node, lname, f, actioncode);
+}
+
+String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f) {
+ return Swig_typemap_lookup_impl(tmap_method, node, lname, f, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * typemap_attach_kwargs()
+ *
+ * If this hash (tm) contains a linked list of parameters under its "kwargs"
+ * attribute, add keys for each of those named keyword arguments to this
+ * parameter for later use.
+ * For example, attach the typemap attributes to firstp (first parameter in parameter list):
+ * %typemap(in, foo="xyz") ...
+ * A new attribute called "tmap:in:foo" with value "xyz" is attached to firstp.
+ * Also expands special variables and special variable macros in the typemap attributes.
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *firstp, int nmatch) {
+ String *temp = NewStringEmpty();
+ Parm *kw = Getattr(tm, "kwargs");
+ typemap_merge_fragment_kwargs(kw);
+ while (kw) {
+ String *value = Copy(Getattr(kw, "value"));
+ String *type = Getattr(kw, "type");
+ int i;
+ Parm *p = firstp;
+ /* Expand special variables */
+ for (i = 0; i < nmatch; i++) {
+ SwigType *type = Getattr(p, "type");
+ String *pname = Getattr(p, "name");
+ String *lname = Getattr(p, "lname");
+ SwigType *mtype = Getattr(p, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : type;
+ typemap_replace_vars(value, NULL, matchtype, type, pname, lname, i + 1, NULL);
+ p = nextSibling(p);
+ }
+
+ /* Expand special variable macros (embedded typemaps).
+ * Special variable are expanded first above as they might be used in the special variable macros.
+ * For example: $typemap(imtype, $2_type). */
+ p = firstp;
+ for (i = 0; i < nmatch; i++) {
+ SwigType *type = Getattr(p, "type");
+ String *pname = Getattr(p, "name");
+ String *lname = Getattr(p, "lname");
+ ParmList *parm_sublist = NewParmWithoutFileLineInfo(type, pname);
+ Setattr(parm_sublist, "lname", lname);
+ replace_embedded_typemap(value, parm_sublist, NULL, tm);
+ p = nextSibling(p);
+ }
+ if (type) {
+ Hash *v = NewHash();
+ Setattr(v, "type", type);
+ Setattr(v, "value", value);
+ Delete(value);
+ value = v;
+ }
+ Clear(temp);
+ Printf(temp, "%s:%s", tmap_method, Getattr(kw, "name"));
+ Setattr(firstp, typemap_method_name(temp), value);
+ Delete(value);
+ kw = nextSibling(kw);
+ }
+ Clear(temp);
+ Printf(temp, "%s:match_type", tmap_method);
+ Setattr(firstp, typemap_method_name(temp), Getattr(tm, "type"));
+ Delete(temp);
+}
+
+static void typemap_emit_code_fragments(const_String_or_char_ptr tmap_method, Parm *p) {
+ String *temp = NewStringf("%s:fragment", tmap_method);
+ String *f = Getattr(p, typemap_method_name(temp));
+ if (f) {
+ String *fname = Copy(f);
+ Setfile(fname, Getfile(p));
+ Setline(fname, Getline(p));
+ Swig_fragment_emit(fname);
+ Delete(fname);
+ }
+ Delete(temp);
+}
+
+static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
+ Parm *kw = Getattr(tm, "kwargs");
+ while (kw) {
+ String *kname = Getattr(kw, "name");
+ if (Equal(kname, name)) {
+ return Getattr(kw, "value");
+ }
+ kw = nextSibling(kw);
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_attach_parms()
+ *
+ * Given a parameter list, this function attaches all of the typemaps and typemap
+ * attributes to the parameter for each type in the parameter list.
+ *
+ * This function basically provides the typemap code and typemap attribute values as
+ * attributes on each parameter prefixed with "tmap:". For example with tmap_method="in", the typemap
+ * code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in")
+ * and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs").
+ *
+ * tmap_method - typemap method, eg "in", "out", "newfree"
+ * parms - parameter list to attach each typemap and all typemap attributes
+ * f - wrapper code to generate into if non null
+ * override_vars - Hash of variables from $typemap(...) that will override special variable replacements
+ * ----------------------------------------------------------------------------- */
+
+static void typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f, Hash *override_vars) {
+ Parm *p, *firstp;
+ Hash *tm;
+ int nmatch = 0;
+ int i;
+ String *s;
+ String *warning = 0;
+ ParmList *locals;
+ int argnum = 0;
+ char temp[256];
+ char *cmethod = Char(tmap_method);
+ String *kwmatch = 0;
+ p = parms;
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_typemap_attach_parms: %s\n", tmap_method);
+#endif
+
+ while (p) {
+ argnum++;
+ nmatch = 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "parms: %s %s %s\n", tmap_method, Getattr(p, "name"), Getattr(p, "type"));
+#endif
+ tm = typemap_search_multi(tmap_method, p, &nmatch);
+#ifdef SWIG_DEBUG
+ if (tm)
+ Printf(stdout, "found: %s\n", tm);
+#endif
+ if (!tm) {
+ p = nextSibling(p);
+ continue;
+ }
+ /*
+ Check if the typemap requires to match the type of another
+ typemap, for example:
+
+ %typemap(in) SWIGTYPE * (int var) {...}
+ %typemap(freearg,match="in") SWIGTYPE * {if (var$argnum) ...}
+
+ here, the freearg typemap requires the "in" typemap to match,
+ or the 'var$argnum' variable will not exist.
+ */
+ kwmatch = typemap_get_option(tm, "match");
+ if (kwmatch) {
+ String *tmname = NewStringf("tmap:%s", kwmatch);
+ String *tmin = Getattr(p, tmname);
+ Delete(tmname);
+#ifdef SWIG_DEBUG
+ if (tm)
+ Printf(stdout, "matching: %s\n", kwmatch);
+#endif
+ if (tmin) {
+ String *tmninp = NewStringf("tmap:%s:numinputs", kwmatch);
+ String *ninp = Getattr(p, tmninp);
+ Delete(tmninp);
+ if (ninp && Equal(ninp, "0")) {
+ p = nextSibling(p);
+ continue;
+ } else {
+ SwigType *typetm = Getattr(tm, "type");
+ String *temp = NewStringf("tmap:%s:match_type", kwmatch);
+ SwigType *typein = Getattr(p, temp);
+ Delete(temp);
+ if (!Equal(typein, typetm)) {
+ p = nextSibling(p);
+ continue;
+ } else {
+ int nnmatch;
+ Hash *tmapin = typemap_search_multi(kwmatch, p, &nnmatch);
+ String *tmname = Getattr(tm, "pname");
+ String *tnname = Getattr(tmapin, "pname");
+ if (!(tmname && tnname && Equal(tmname, tnname)) && !(!tmname && !tnname)) {
+ p = nextSibling(p);
+ continue;
+ }
+ }
+
+ }
+ } else {
+ p = nextSibling(p);
+ continue;
+ }
+ }
+
+ s = Getattr(tm, "code");
+ if (!s) {
+ p = nextSibling(p);
+ continue;
+ }
+#ifdef SWIG_DEBUG
+ if (s)
+ Printf(stdout, "code: %s\n", s);
+#endif
+
+ /* Empty typemap. No match */
+ if (Cmp(s, "pass") == 0) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ s = Copy(s);
+ locals = Getattr(tm, "locals");
+ if (locals)
+ locals = CopyParmList(locals);
+ firstp = p;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "nmatch: %d\n", nmatch);
+#endif
+ for (i = 0; i < nmatch; i++) {
+ SwigType *type = Getattr(p, "type");
+ String *pname = Getattr(p, "name");
+ String *lname = Getattr(p, "lname");
+ SwigType *mtype = Getattr(p, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : type;
+
+ typemap_replace_vars(s, locals, matchtype, type, pname, lname, i + 1, override_vars);
+ if (mtype)
+ Delattr(p, "tmap:match");
+
+ if (Checkattr(tm, "type", "SWIGTYPE")) {
+ sprintf(temp, "%s:SWIGTYPE", cmethod);
+ Setattr(p, typemap_method_name(temp), "1");
+ }
+ p = nextSibling(p);
+ }
+
+ if (locals && f) {
+ typemap_locals(s, locals, f, argnum);
+ }
+
+ replace_embedded_typemap(s, firstp, f, tm);
+
+ /* Attach attributes to object */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), s);
+#endif
+ Setattr(firstp, typemap_method_name(tmap_method), s); /* Code object */
+
+ if (locals) {
+ sprintf(temp, "%s:locals", cmethod);
+ Setattr(firstp, typemap_method_name(temp), locals);
+ Delete(locals);
+ }
+
+ /* Attach a link to the next parameter. Needed for multimaps */
+ sprintf(temp, "%s:next", cmethod);
+ Setattr(firstp, typemap_method_name(temp), p);
+
+ /* Attach kwargs */
+ typemap_attach_kwargs(tm, tmap_method, firstp, nmatch);
+
+ /* Replace the argument number */
+ sprintf(temp, "%d", argnum);
+ Replace(s, "$argnum", temp, DOH_REPLACE_ANY);
+
+ /* Print warnings, if any */
+ warning = typemap_warn(tmap_method, firstp);
+ if (warning) {
+ SwigType *type = Getattr(firstp, "type");
+ String *pname = Getattr(firstp, "name");
+ String *lname = Getattr(firstp, "lname");
+ SwigType *mtype = Getattr(firstp, "tmap:match");
+ SwigType *matchtype = mtype ? mtype : type;
+ typemap_replace_vars(warning, 0, matchtype, type, pname, lname, 1, override_vars);
+ Replace(warning, "$argnum", temp, DOH_REPLACE_ANY);
+ Swig_warning(0, Getfile(firstp), Getline(firstp), "%s\n", warning);
+ Delete(warning);
+ }
+
+ /* Look for code fragments */
+ typemap_emit_code_fragments(tmap_method, firstp);
+
+ /* increase argnum to consider numinputs */
+ argnum += nmatch - 1;
+ Delete(s);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), Getattr(firstp, typemap_method_name(tmap_method)));
+#endif
+
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_typemap_attach_parms: end\n");
+#endif
+
+}
+
+void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) {
+ typemap_attach_parms(tmap_method, parms, f, NULL);
+}
+
+/* Splits the arguments of an embedded typemap */
+static List *split_embedded_typemap(String *s) {
+ List *args = 0;
+ char *c, *start;
+ int level = 0;
+ int angle_level = 0;
+ int leading = 1;
+
+ args = NewList();
+ c = strchr(Char(s), '(');
+ assert(c);
+ c++;
+
+ start = c;
+ while (*c) {
+ if (*c == '\"') {
+ c++;
+ while (*c) {
+ if (*c == '\\') {
+ c++;
+ } else {
+ if (*c == '\"')
+ break;
+ }
+ c++;
+ }
+ }
+ if ((level == 0) && angle_level == 0 && ((*c == ',') || (*c == ')'))) {
+ String *tmp = NewStringWithSize(start, (int)(c - start));
+ Append(args, tmp);
+ Delete(tmp);
+ start = c + 1;
+ leading = 1;
+ if (*c == ')')
+ break;
+ c++;
+ continue;
+ }
+ if (*c == '(')
+ level++;
+ if (*c == ')')
+ level--;
+ if (*c == '<')
+ angle_level++;
+ if (*c == '>' && *(c - 1) != '-')
+ angle_level--;
+ if (isspace((int) *c) && leading)
+ start++;
+ if (!isspace((int) *c))
+ leading = 0;
+ c++;
+ }
+ return args;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_replace_embedded_typemap()
+ *
+ * For special variable macro $typemap(...) expansion outside of typemaps.
+ * Only limited usage works as most typemap special variables ($1, $input etc)
+ * are not expanded correctly outside of typemaps.
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node) {
+ Setfile(s, Getfile(file_line_node));
+ Setline(s, Getline(file_line_node));
+ Replaceall(s, "$typemap", "$TYPEMAP");
+ replace_embedded_typemap(s, 0, 0, file_line_node);
+}
+
+/* -----------------------------------------------------------------------------
+ * replace_embedded_typemap()
+ *
+ * This function replaces the special variable macro $typemap(...) with typemap
+ * code. The general form of $typemap is as follows:
+ *
+ * $typemap(method, typelist, var1=value, var2=value, ...)
+ *
+ * where varx parameters are optional and undocumented; they were initially an experiment in the first implementation of $typemap.
+ * They allow one to override known special variable replacements or even add in new special variables for replacement
+ * from the calling typemap to the called typemap.
+ * A search is made using the typemap matching rules of form:
+ *
+ * %typemap(method) typelist {...}
+ *
+ * and if found will substitute in the typemap contents, making appropriate variable replacements.
+ *
+ * For example:
+ * $typemap(in, int) # simple usage matching %typemap(in) int { ... }
+ * $typemap(in, int b) # simple usage matching %typemap(in) int b { ... } or above %typemap
+ * $typemap(in, (Foo<int, bool> a, int b)) # multi-argument typemap matching %typemap(in) (Foo<int, bool> a, int b) {...}
+ * ----------------------------------------------------------------------------- */
+
+static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f, Node *file_line_node) {
+ char *start = 0;
+ while ((start = strstr(Char(s), "$TYPEMAP("))) { /* note $typemap capitalisation to $TYPEMAP hack */
+
+ /* Gather the parameters */
+ char *end = 0, *c;
+ int level = 0;
+ String *dollar_typemap;
+ int syntax_error = 1;
+ c = start;
+ while (*c) {
+ if (*c == '(')
+ level++;
+ if (*c == ')') {
+ level--;
+ if (level == 0) {
+ end = c + 1;
+ break;
+ }
+ }
+ c++;
+ }
+ if (end) {
+ dollar_typemap = NewStringWithSize(start, (int)((end - start)));
+ syntax_error = 0;
+ } else {
+ dollar_typemap = NewStringWithSize(start, (int)((c - start)));
+ }
+
+ if (!syntax_error) {
+ List *l;
+ String *tmap_method;
+ Hash *override_vars;
+ syntax_error = 1;
+
+ /* Split apart each parameter in $typemap(...) */
+ l = split_embedded_typemap(dollar_typemap);
+
+ if (Len(l) >= 2) {
+ ParmList *to_match_parms;
+ tmap_method = Getitem(l, 0);
+
+ /* the second parameter might contain multiple sub-parameters for multi-argument
+ * typemap matching, so split these parameters apart */
+ to_match_parms = Swig_cparse_parms(Getitem(l, 1), file_line_node);
+ if (to_match_parms) {
+ Parm *p = to_match_parms;
+ Parm *sub_p = parm_sublist;
+ String *empty_string = NewStringEmpty();
+ String *lname = empty_string;
+ while (p) {
+ if (sub_p) {
+ lname = Getattr(sub_p, "lname");
+ sub_p = nextSibling(sub_p);
+ }
+ Setattr(p, "lname", lname);
+ p = nextSibling(p);
+ }
+ Delete(empty_string);
+ }
+
+ /* process optional extra parameters - the override variable replacements (undocumented) */
+ override_vars = NewHash();
+ {
+ int i, ilen;
+ ilen = Len(l);
+ for (i = 2; i < ilen; i++) {
+ String *parm = Getitem(l, i);
+ char *eq = strchr(Char(parm), '=');
+ char *c = Char(parm);
+ if (eq && (eq - c > 0)) {
+ String *name = NewStringWithSize(c, (int)(eq - c));
+ String *value = NewString(eq + 1);
+ Insert(name, 0, "$");
+ Setattr(override_vars, name, value);
+ } else {
+ to_match_parms = 0; /* error - variable replacement parameters must be of form varname=value */
+ }
+ }
+ }
+
+ /* Perform a typemap search */
+ if (to_match_parms) {
+ static int already_substituting = 0;
+ String *tm;
+ String *attr;
+ int match = 0;
+#ifdef SWIG_DEBUG
+ Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
+#endif
+ if (already_substituting < 10) {
+ char* found_colon;
+ already_substituting++;
+ if ((in_typemap_search_multi == 0) && typemap_search_debug) {
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Printf(stdout, " Containing: %s\n", dtypemap);
+ Delete(dtypemap);
+ }
+ found_colon = Strchr(tmap_method, ':');
+ if (found_colon) {
+ /* Substitute from a keyword argument to a typemap. Avoid emitting local variables from the attached typemap by passing NULL for the file. */
+ String *temp_tmap_method = NewStringWithSize(Char(tmap_method), (int)(found_colon - Char(tmap_method)));
+ typemap_attach_parms(temp_tmap_method, to_match_parms, NULL, override_vars);
+ Delete(temp_tmap_method);
+ } else {
+ typemap_attach_parms(tmap_method, to_match_parms, f, override_vars);
+ }
+ already_substituting--;
+
+ /* Look for the typemap code */
+ attr = NewStringf("tmap:%s", tmap_method);
+ tm = Getattr(to_match_parms, attr);
+ if (tm) {
+ Printf(attr, "%s", ":next");
+ /* fail if multi-argument lookup requested in $typemap(...) and the lookup failed */
+ if (!Getattr(to_match_parms, attr)) {
+ /* Replace parameter variables */
+ Iterator ki;
+ for (ki = First(override_vars); ki.key; ki = Next(ki)) {
+ Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY);
+ }
+ /* offer the target language module the chance to make special variable substitutions */
+ Language_replace_special_variables(tmap_method, tm, to_match_parms);
+ /* finish up - do the substitution */
+ Replace(s, dollar_typemap, tm, DOH_REPLACE_ANY);
+ Delete(tm);
+ match = 1;
+ }
+ }
+
+ if (!match) {
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", dtypemap);
+ Delete(dtypemap);
+ }
+ Delete(attr);
+ } else {
+ /* Simple recursive call check to prevent infinite recursion - this strategy only allows a limited
+ * number of calls by a embedded typemaps to other embedded typemaps though */
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Swig_error(Getfile(s), Getline(s), "Likely recursive $typemap calls containing %s. Use -debug-tmsearch to debug.\n", dtypemap);
+ Delete(dtypemap);
+ }
+ syntax_error = 0;
+ }
+ Delete(override_vars);
+ }
+ Delete(l);
+ }
+
+ if (syntax_error) {
+ String *dtypemap = NewString(dollar_typemap);
+ Replaceall(dtypemap, "$TYPEMAP", "$typemap");
+ Swig_error(Getfile(s), Getline(s), "Syntax error in: %s\n", dtypemap);
+ Delete(dtypemap);
+ }
+ Replace(s, dollar_typemap, "<error in embedded typemap>", DOH_REPLACE_ANY);
+ Delete(dollar_typemap);
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_debug()
+ *
+ * Display all typemaps
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_debug(void) {
+ int nesting_level = 2;
+ Printf(stdout, "---[ typemaps ]--------------------------------------------------------------\n");
+ Swig_print(typemaps, nesting_level);
+ Printf(stdout, "-----------------------------------------------------------------------------\n");
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_search_debug_set()
+ *
+ * Turn on typemap searching debug display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_search_debug_set(void) {
+ typemap_search_debug = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_used_debug_set()
+ *
+ * Turn on typemaps used debug display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_used_debug_set(void) {
+ typemaps_used_debug = 1;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_typemap_register_debug_set()
+ *
+ * Turn on typemaps used debug display
+ * ----------------------------------------------------------------------------- */
+
+void Swig_typemap_register_debug_set(void) {
+ typemap_register_debug = 1;
+}
+
diff --git a/contrib/tools/swig/Source/Swig/typeobj.c b/contrib/tools/swig/Source/Swig/typeobj.c
new file mode 100644
index 00000000000..fc443d8aa16
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/typeobj.c
@@ -0,0 +1,1404 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * typeobj.c
+ *
+ * This file provides functions for constructing, manipulating, and testing
+ * type objects. Type objects are merely the raw low-level representation
+ * of C++ types. They do not incorporate high-level type system features
+ * like typedef, namespaces, etc.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <ctype.h>
+#include <limits.h>
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * This file provides a collection of low-level functions for constructing and
+ * manipulating C++ data types. In SWIG, C++ datatypes are encoded as simple
+ * text strings. This representation is compact, easy to debug, and easy to read.
+ *
+ * General idea:
+ *
+ * Types are represented by a base type (e.g., "int") and a collection of
+ * type operators applied to the base (e.g., pointers, arrays, etc...).
+ *
+ * Encoding:
+ *
+ * Types are encoded as strings of type constructors such as follows:
+ *
+ * String Encoding C Example
+ * --------------- ---------
+ * p.p.int int **
+ * a(300).a(400).int int [300][400]
+ * p.q(const).char char const *
+ *
+ * All type constructors are denoted by a trailing '.':
+ *
+ * 'p.' = Pointer (*)
+ * 'r.' = Reference or ref-qualifier (&)
+ * 'z.' = Rvalue reference or ref-qualifier (&&)
+ * 'v.' = Variadic (...)
+ * 'a(n).' = Array of size n [n]
+ * 'f(..,..).' = Function with arguments (args)
+ * 'q(str).' = Qualifier, such as const or volatile (cv-qualifier)
+ * 'm(cls).' = Pointer to member (cls::*)
+ *
+ * The complete type representation for varargs is:
+ * 'v(...)'
+ *
+ * The encoding follows the order that you might describe a type in words.
+ * For example "p.a(200).int" is "A pointer to array of int's" and
+ * "p.q(const).char" is "a pointer to a const char".
+ *
+ * This representation of types is fairly convenient because ordinary string
+ * operations can be used for type manipulation. For example, a type could be
+ * formed by combining two strings such as the following:
+ *
+ * "p.p." + "a(400).int" = "p.p.a(400).int"
+ *
+ * For C++, typenames may be parameterized using <(...)>. Here are some
+ * examples:
+ *
+ * String Encoding C++ Example
+ * --------------- ------------
+ * p.vector<(int)> vector<int> *
+ * r.foo<(int,p.double)> foo<int,double *> &
+ *
+ * Contents of this file:
+ *
+ * Most of this functions in this file pertain to the low-level manipulation
+ * of type objects. There are constructor functions like this:
+ *
+ * SwigType_add_pointer()
+ * SwigType_add_reference()
+ * SwigType_add_rvalue_reference()
+ * SwigType_add_variadic()
+ * SwigType_add_array()
+ *
+ * These are used to build new types. There are also functions to undo these
+ * operations. For example:
+ *
+ * SwigType_del_pointer()
+ * SwigType_del_reference()
+ * SwigType_del_rvalue_reference()
+ * SwigType_del_variadic()
+ * SwigType_del_array()
+ *
+ * In addition, there are query functions
+ *
+ * SwigType_ispointer()
+ * SwigType_isreference()
+ * SwigType_isrvalue_reference()
+ * SwigType_isvariadic()
+ * SwigType_isarray()
+ *
+ * Finally, there are some data extraction functions that can be used to
+ * extract array dimensions, template arguments, and so forth.
+ *
+ * It is very important for developers to realize that the functions in this
+ * module do *NOT* incorporate higher-level type system features like typedef.
+ * For example, you could have C code like this:
+ *
+ * typedef int *intptr;
+ *
+ * In this case, a SwigType of type 'intptr' will be treated as a simple type and
+ * functions like SwigType_ispointer() will evaluate as false. It is strongly
+ * advised that developers use the TypeSys_* interface to check types in a more
+ * reliable manner.
+ * ----------------------------------------------------------------------------- */
+
+/* The next few functions are utility functions used in the construction and
+ management of types */
+
+/* -----------------------------------------------------------------------------
+ * static element_size()
+ *
+ * This utility function finds the size of a single type element in a type string.
+ * Type elements are always delimited by periods, but may be nested with
+ * parentheses. A nested element is always handled as a single item.
+ *
+ * Returns the integer size of the element (which can be used to extract a
+ * substring, to chop the element off, or for other purposes).
+ * ----------------------------------------------------------------------------- */
+
+static int element_size(char *c) {
+ int nparen;
+ char *s = c;
+ while (*c) {
+ if (*c == '.') {
+ c++;
+ return (int) (c - s);
+ } else if (*c == '(') {
+ nparen = 1;
+ c++;
+ while (*c) {
+ if (*c == '(')
+ nparen++;
+ if (*c == ')') {
+ nparen--;
+ if (nparen == 0)
+ break;
+ }
+ c++;
+ }
+ }
+ if (*c)
+ c++;
+ }
+ return (int) (c - s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_del_element()
+ *
+ * Deletes one type element from the type.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_del_element(SwigType *t) {
+ int sz = element_size(Char(t));
+ Delslice(t, 0, sz);
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop()
+ *
+ * Pop one type element off the type.
+ * For example:
+ * t in: q(const).p.Integer
+ * t out: p.Integer
+ * result: q(const).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop(SwigType *t) {
+ SwigType *result;
+ char *c;
+ int sz;
+
+ c = Char(t);
+ if (!*c)
+ return 0;
+
+ sz = element_size(c);
+ result = NewStringWithSize(c, sz);
+ Delslice(t, 0, sz);
+ c = Char(t);
+ if (*c == '.') {
+ Delitem(t, 0);
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_last()
+ *
+ * Return the last element of the given (partial) type.
+ * For example:
+ * t: q(const).p.
+ * result: p.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_last(SwigType *t) {
+ SwigType *result;
+ char *c;
+ char *last;
+ int sz = 0;
+
+ if (!t)
+ return 0;
+
+ /* Find the last element */
+ c = Char(t);
+ last = 0;
+ while (*c) {
+ last = c;
+ sz = element_size(c);
+ c = c + sz;
+ if (*c == '.') {
+ c++;
+ sz++;
+ }
+ }
+
+ /* Extract the last element */
+ if (last) {
+ result = NewStringWithSize(last, sz);
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_parm()
+ *
+ * Returns the parameter of an operator as a string
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_parm(const SwigType *t) {
+ char *start, *c;
+ int nparens = 0;
+
+ c = Char(t);
+ while (*c && (*c != '(') && (*c != '.'))
+ c++;
+ if (!*c || (*c == '.'))
+ return 0;
+ c++;
+ start = c;
+ while (*c) {
+ if (*c == ')') {
+ if (nparens == 0)
+ break;
+ nparens--;
+ } else if (*c == '(') {
+ nparens++;
+ }
+ c++;
+ }
+ return NewStringWithSize(start, (int) (c - start));
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_split()
+ *
+ * Splits a type into its component parts and returns a list of string.
+ * The component parts of SwigType are split by '.'.
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_split(const SwigType *t) {
+ String *item;
+ List *list;
+ char *c;
+ int len;
+
+ c = Char(t);
+ list = NewList();
+ while (*c) {
+ len = element_size(c);
+ item = NewStringWithSize(c, len);
+ Append(list, item);
+ Delete(item);
+ c = c + len;
+ if (*c == '.')
+ c++;
+ }
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_parmlist()
+ *
+ * Splits a comma separated list of SwigType * parameters into its component parts
+ * The input is expected to contain the parameter list within () brackets
+ * Returns 0 if no argument list in the input, ie there are no round brackets ()
+ * Returns an empty List if there are no parameters in the () brackets
+ * For example:
+ *
+ * Foo(std::string,p.f().Bar<(int,double)>)
+ *
+ * returns 2 SwigType * elements in the list:
+ * std::string
+ * p.f().Bar<(int,double)>
+ * ----------------------------------------------------------------------------- */
+
+List *SwigType_parmlist(const SwigType *p) {
+ String *item = 0;
+ List *list;
+ char *c;
+ char *itemstart;
+ int size;
+
+ assert(p);
+ c = Char(p);
+ while (*c && (*c != '(') && (*c != '.'))
+ c++;
+ if (!*c)
+ return 0;
+ assert(*c != '.'); /* p is expected to contain sub elements of a type */
+ c++;
+ list = NewList();
+ itemstart = c;
+ while (*c) {
+ if (*c == ',') {
+ size = (int) (c - itemstart);
+ item = NewStringWithSize(itemstart, size);
+ Append(list, item);
+ Delete(item);
+ itemstart = c + 1;
+ } else if (*c == '(') {
+ int nparens = 1;
+ c++;
+ while (*c) {
+ if (*c == '(')
+ nparens++;
+ if (*c == ')') {
+ nparens--;
+ if (nparens == 0)
+ break;
+ }
+ c++;
+ }
+ } else if (*c == ')') {
+ break;
+ }
+ if (*c)
+ c++;
+ }
+ size = (int) (c - itemstart);
+ if (size > 0) {
+ item = NewStringWithSize(itemstart, size);
+ Append(list, item);
+ }
+ Delete(item);
+ return list;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pointers
+ *
+ * SwigType_add_pointer()
+ * SwigType_del_pointer()
+ * SwigType_ispointer()
+ *
+ * Add, remove, and test if a type is a pointer. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_pointer(SwigType *t) {
+ Insert(t, 0, "p.");
+ return t;
+}
+
+SwigType *SwigType_del_pointer(SwigType *t) {
+ char *c, *s;
+ c = Char(t);
+ s = c;
+ /* Skip qualifiers, if any */
+ if (strncmp(c, "q(", 2) == 0) {
+ c = strchr(c, '.');
+ assert(c);
+ c++;
+ }
+ if (strncmp(c, "p.", 2)) {
+ printf("Fatal error: SwigType_del_pointer applied to non-pointer.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, (int)((c - s) + 2));
+ return t;
+}
+
+int SwigType_ispointer(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ /* Skip qualifiers, if any */
+ if (strncmp(c, "q(", 2) == 0) {
+ c = strchr(c, '.');
+ if (!c)
+ return 0;
+ c++;
+ }
+ if (strncmp(c, "p.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * References
+ *
+ * SwigType_add_reference()
+ * SwigType_del_reference()
+ * SwigType_isreference()
+ *
+ * Add, remove, and test if a type is a reference. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_reference(SwigType *t) {
+ Insert(t, 0, "r.");
+ return t;
+}
+
+SwigType *SwigType_del_reference(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "r.", 2)) {
+ printf("Fatal error: SwigType_del_reference applied to non-reference.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, 2);
+ return t;
+}
+
+int SwigType_isreference(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "r.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Rvalue References
+ *
+ * SwigType_add_rvalue_reference()
+ * SwigType_del_rvalue_reference()
+ * SwigType_isrvalue_reference()
+ *
+ * Add, remove, and test if a type is a rvalue reference. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_rvalue_reference(SwigType *t) {
+ Insert(t, 0, "z.");
+ return t;
+}
+
+SwigType *SwigType_del_rvalue_reference(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "z.", 2)) {
+ fprintf(stderr, "Fatal error: SwigType_del_rvalue_reference() applied to non-rvalue-reference.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, 2);
+ return t;
+}
+
+int SwigType_isrvalue_reference(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "z.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Variadic
+ *
+ * SwigType_add_variadic()
+ * SwigType_del_variadic()
+ * SwigType_isvariadic()
+ *
+ * Add, remove, and test if a type is a variadic. The deletion and query
+ * functions take into account qualifiers (if any).
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_variadic(SwigType *t) {
+ Insert(t, 0, "v.");
+ return t;
+}
+
+SwigType *SwigType_del_variadic(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "v.", 2)) {
+ printf("Fatal error: SwigType_del_variadic applied to non-variadic.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, 2);
+ return t;
+}
+
+int SwigType_isvariadic(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "v.", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Qualifiers
+ *
+ * SwigType_add_qualifier()
+ * SwigType_del_qualifier()
+ * SwigType_is_qualifier()
+ *
+ * Adds type qualifiers like "const" and "volatile". When multiple qualifiers
+ * are added to a type, they are combined together into a single qualifier.
+ * Repeated qualifications have no effect. Moreover, the order of qualifications
+ * is alphabetical---meaning that "const volatile" and "volatile const" are
+ * stored in exactly the same way as "q(const volatile)".
+ * 'qual' can be a list of multiple qualifiers in any order, separated by spaces.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
+ List *qlist;
+ String *allq, *newq;
+ int i, sz;
+ const char *cqprev = 0;
+ const char *c = Char(t);
+ const char *cqual = Char(qual);
+
+ /* if 't' has no qualifiers and 'qual' is a single qualifier, simply add it */
+ if ((strncmp(c, "q(", 2) != 0) && (strchr(cqual, ' ') == 0)) {
+ String *temp = NewStringf("q(%s).", cqual);
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+ }
+
+ /* create string of all qualifiers */
+ if (strncmp(c, "q(", 2) == 0) {
+ allq = SwigType_parm(t);
+ Append(allq, " ");
+ SwigType_del_element(t); /* delete old qualifier list from 't' */
+ } else {
+ allq = NewStringEmpty();
+ }
+ Append(allq, qual);
+
+ /* create list of all qualifiers from string */
+ qlist = Split(allq, ' ', INT_MAX);
+ Delete(allq);
+
+ /* sort in alphabetical order */
+ SortList(qlist, Strcmp);
+
+ /* create new qualifier string from unique elements of list */
+ sz = Len(qlist);
+ newq = NewString("q(");
+ for (i = 0; i < sz; ++i) {
+ String *q = Getitem(qlist, i);
+ const char *cq = Char(q);
+ if (cqprev == 0 || strcmp(cqprev, cq) != 0) {
+ if (i > 0) {
+ Append(newq, " ");
+ }
+ Append(newq, q);
+ cqprev = cq;
+ }
+ }
+ Append(newq, ").");
+ Delete(qlist);
+
+ /* replace qualifier string with new one */
+ Insert(t, 0, newq);
+ Delete(newq);
+ return t;
+}
+
+SwigType *SwigType_del_qualifier(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "q(", 2);
+ assert(check == 0);
+ (void)check;
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_isqualifier(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "q(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Function Pointers
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_isfunctionpointer(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "p.f(", 4) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_functionpointer_decompose
+ *
+ * Decompose the function pointer into the parameter list and the return type
+ * t - input and on completion contains the return type
+ * returns the function's parameters
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_functionpointer_decompose(SwigType *t) {
+ String *p;
+ assert(SwigType_isfunctionpointer(t));
+ p = SwigType_pop(t);
+ Delete(p);
+ p = SwigType_pop(t);
+ return p;
+}
+
+/* -----------------------------------------------------------------------------
+ * Member Pointers
+ *
+ * SwigType_add_memberpointer()
+ * SwigType_del_memberpointer()
+ * SwigType_ismemberpointer()
+ *
+ * Add, remove, and test for C++ pointer to members.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
+ String *temp = NewStringf("m(%s).", name);
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+}
+
+SwigType *SwigType_del_memberpointer(SwigType *t) {
+ char *c = Char(t);
+ int check = strncmp(c, "m(", 2);
+ assert(check == 0);
+ (void)check;
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_ismemberpointer(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "m(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Arrays
+ *
+ * SwigType_add_array()
+ * SwigType_del_array()
+ * SwigType_isarray()
+ *
+ * Utility functions:
+ *
+ * SwigType_array_ndim() - Calculate number of array dimensions.
+ * SwigType_array_getdim() - Get array dimension
+ * SwigType_array_setdim() - Set array dimension
+ * SwigType_array_type() - Return array type
+ * SwigType_pop_arrays() - Remove all arrays
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
+ String *temp = NewString("a(");
+ Append(temp, size);
+ Append(temp, ").");
+ Insert(t, 0, temp);
+ Delete(temp);
+ return t;
+}
+
+SwigType *SwigType_del_array(SwigType *t) {
+ char *c = Char(t);
+ if (strncmp(c, "a(", 2)) {
+ fprintf(stderr, "Fatal error: SwigType_del_array() applied to non-array.\n");
+ Exit(EXIT_FAILURE);
+ }
+ Delslice(t, 0, element_size(c));
+ return t;
+}
+
+int SwigType_isarray(const SwigType *t) {
+ char *c;
+ if (!t)
+ return 0;
+ c = Char(t);
+ if (strncmp(c, "a(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+/*
+ * SwigType_prefix_is_simple_1D_array
+ *
+ * Determine if the type is a 1D array type that is treated as a pointer within SWIG
+ * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
+ */
+int SwigType_prefix_is_simple_1D_array(const SwigType *t) {
+ char *c = Char(t);
+
+ if (c && (strncmp(c, "a(", 2) == 0)) {
+ c = strchr(c, '.');
+ if (c)
+ return (*(++c) == 0);
+ }
+ return 0;
+}
+
+
+/* Remove all arrays */
+SwigType *SwigType_pop_arrays(SwigType *t) {
+ String *ta;
+ assert(SwigType_isarray(t));
+ ta = NewStringEmpty();
+ while (SwigType_isarray(t)) {
+ SwigType *td = SwigType_pop(t);
+ Append(ta, td);
+ Delete(td);
+ }
+ return ta;
+}
+
+/* Return number of array dimensions */
+int SwigType_array_ndim(const SwigType *t) {
+ int ndim = 0;
+ char *c = Char(t);
+
+ while (c && (strncmp(c, "a(", 2) == 0)) {
+ c = strchr(c, '.');
+ if (c) {
+ c++;
+ ndim++;
+ }
+ }
+ return ndim;
+}
+
+/* Get nth array dimension */
+String *SwigType_array_getdim(const SwigType *t, int n) {
+ char *c = Char(t);
+ while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
+ c = strchr(c, '.');
+ if (c) {
+ c++;
+ n--;
+ }
+ }
+ if (n == 0) {
+ String *dim = SwigType_parm(c);
+ if (SwigType_istemplate(dim)) {
+ String *ndim = SwigType_namestr(dim);
+ Delete(dim);
+ dim = ndim;
+ }
+
+ return dim;
+ }
+
+ return 0;
+}
+
+/* Replace nth array dimension */
+void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
+ String *result = 0;
+ char temp;
+ char *start;
+ char *c = Char(t);
+
+ start = c;
+ if (strncmp(c, "a(", 2)) {
+ fprintf(stderr, "Fatal error: SwigType_array_type applied to non-array.\n");
+ Exit(EXIT_FAILURE);
+ }
+
+ while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
+ c = strchr(c, '.');
+ if (c) {
+ c++;
+ n--;
+ }
+ }
+ if (n == 0) {
+ temp = *c;
+ *c = 0;
+ result = NewString(start);
+ Printf(result, "a(%s)", rep);
+ *c = temp;
+ c = strchr(c, '.');
+ Append(result, c);
+ }
+ Clear(t);
+ Append(t, result);
+ Delete(result);
+}
+
+/* Return base type of an array */
+SwigType *SwigType_array_type(const SwigType *ty) {
+ SwigType *t;
+ t = Copy(ty);
+ while (SwigType_isarray(t)) {
+ Delete(SwigType_pop(t));
+ }
+ return t;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Functions
+ *
+ * SwigType_add_function()
+ * SwigType_function_parms_only()
+ * SwigType_isfunction()
+ * SwigType_pop_function()
+ *
+ * Add, remove, and test for function types.
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * SwigType_function_parms_only()
+ *
+ * Creates a comma separated list of SwigType strings from parms
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_function_parms_only(ParmList *parms) {
+ Parm *p;
+ SwigType *t = NewString("");
+ for (p = parms; p; p = nextSibling(p)) {
+ if (p != parms)
+ Putc(',', t);
+ Append(t, Getattr(p, "type"));
+ }
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_add_function()
+ *
+ * Returns the function type, t, constructed from the parameters, parms
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
+ SwigType *fparms = SwigType_function_parms_only(parms);
+ Insert(fparms, 0, "f(");
+ Append(fparms, ").");
+ Insert(t, 0, fparms);
+ Delete(fparms);
+ return t;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop_function()
+ *
+ * Pop and return the function from the input type leaving the function's return
+ * type, if any.
+ * For example:
+ * t in: q(const).f().p.
+ * t out: p.
+ * result: q(const).f().
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop_function(SwigType *t) {
+ SwigType *f = 0;
+ SwigType *g = 0;
+ char *c = Char(t);
+ if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
+ /* Remove ref-qualifier */
+ f = SwigType_pop(t);
+ c = Char(t);
+ }
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Remove cv-qualifier */
+ String *qual = SwigType_pop(t);
+ if (f) {
+ SwigType_push(qual, f);
+ Delete(f);
+ }
+ f = qual;
+ c = Char(t);
+ }
+ if (strncmp(c, "f(", 2)) {
+ fprintf(stderr, "Fatal error. SwigType_pop_function applied to non-function.\n");
+ Exit(EXIT_FAILURE);
+ }
+ g = SwigType_pop(t);
+ if (f)
+ SwigType_push(g, f);
+ Delete(f);
+ return g;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop_function_qualifiers()
+ *
+ * Pop and return the function qualifiers from the input type leaving the rest of
+ * function declaration. Returns NULL if no qualifiers.
+ * For example:
+ * t in: r.q(const).f().p.
+ * t out: f().p.
+ * result: r.q(const)
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_pop_function_qualifiers(SwigType *t) {
+ SwigType *qualifiers = 0;
+ char *c = Char(t);
+ if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
+ /* Remove ref-qualifier */
+ String *qual = SwigType_pop(t);
+ qualifiers = qual;
+ c = Char(t);
+ }
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Remove cv-qualifier */
+ String *qual = SwigType_pop(t);
+ if (qualifiers) {
+ SwigType_push(qual, qualifiers);
+ Delete(qualifiers);
+ }
+ qualifiers = qual;
+ }
+ assert(Strncmp(t, "f(", 2) == 0);
+
+ return qualifiers;
+}
+
+int SwigType_isfunction(const SwigType *t) {
+ char *c;
+ if (!t) {
+ return 0;
+ }
+ c = Char(t);
+ if (strncmp(c, "r.", 2) == 0 || strncmp(c, "z.", 2) == 0) {
+ /* Might be a function with a ref-qualifier, skip over */
+ c += 2;
+ if (!*c)
+ return 0;
+ }
+ if (strncmp(c, "q(", 2) == 0) {
+ /* Might be a function with a cv-qualifier, skip over */
+ c = strchr(c, '.');
+ if (c)
+ c++;
+ else
+ return 0;
+ }
+ if (strncmp(c, "f(", 2) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/* Create a list of parameters from the type t, using the file_line_node Node for
+ * file and line numbering for the parameters */
+ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node) {
+ List *l = SwigType_parmlist(t);
+ Hash *p, *pp = 0, *firstp = 0;
+ Iterator o;
+
+ for (o = First(l); o.item; o = Next(o)) {
+ p = file_line_node ? NewParm(o.item, 0, file_line_node) : NewParmWithoutFileLineInfo(o.item, 0);
+ if (!firstp)
+ firstp = p;
+ if (pp) {
+ set_nextSibling(pp, p);
+ Delete(p);
+ }
+ pp = p;
+ }
+ Delete(l);
+ return firstp;
+}
+
+int SwigType_isvarargs(const SwigType *t) {
+ if (Strcmp(t, "v(...)") == 0)
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Templates
+ *
+ * SwigType_add_template()
+ *
+ * Template handling.
+ * ----------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * SwigType_add_template()
+ *
+ * Adds a template to a type. This template is encoded in the SWIG type
+ * mechanism and produces a string like this:
+ *
+ * vector<int *> ----> "vector<(p.int)>"
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
+ Parm *p;
+
+ Append(t, "<(");
+ for (p = parms; p; p = nextSibling(p)) {
+ String *v;
+ if (Getattr(p, "default"))
+ continue;
+ if (p != parms)
+ Append(t, ",");
+ v = Getattr(p, "value");
+ if (v) {
+ Append(t, v);
+ } else {
+ Append(t, Getattr(p, "type"));
+ }
+ }
+ Append(t, ")>");
+ return t;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templateprefix()
+ *
+ * Returns the prefix before the first template definition.
+ * Returns the type unmodified if not a template.
+ * For example:
+ *
+ * Foo<(p.int)>::bar => Foo
+ * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
+ * Foo => Foo
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templateprefix(const SwigType *t) {
+ const char *s = Char(t);
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, (int)(c - s)) : NewString(s);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templatesuffix()
+ *
+ * Returns text after a template substitution. Used to handle scope names
+ * for example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "::bar"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templatesuffix(const SwigType *t) {
+ const char *c, *d;
+ c = Char(t);
+ d = c + strlen(c);
+ while (d > c) {
+ if ((*c == '<') && (*(c + 1) == '(')) {
+ int nest = 1;
+ c++;
+ while ((d > c) && nest) {
+ if (*c == '<' && *(c + 1) == '(')
+ nest++;
+ if (*c == '>' && *(c - 1) == ')')
+ nest--;
+ c++;
+ }
+ return NewString(c);
+ }
+ c++;
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate_templateprefix()
+ *
+ * Combines SwigType_istemplate and SwigType_templateprefix efficiently into one function.
+ * Returns the prefix before the first template definition.
+ * Returns NULL if not a template.
+ * For example:
+ *
+ * Foo<(p.int)>::bar => Foo
+ * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
+ * Foo => NULL
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_istemplate_templateprefix(const SwigType *t) {
+ const char *s = Char(t);
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, (int)(c - s)) : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate_only_templateprefix()
+ *
+ * Similar to SwigType_istemplate_templateprefix() but only returns the template
+ * prefix if the type is just the template and not a subtype/symbol within the template.
+ * Returns NULL if not a template or is a template with a symbol within the template.
+ * For example:
+ *
+ * Foo<(p.int)> => Foo
+ * Foo<(p.int)>::bar => NULL
+ * r.q(const).Foo<(p.int)> => r.q(const).Foo
+ * r.q(const).Foo<(p.int)>::bar => NULL
+ * Foo => NULL
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_istemplate_only_templateprefix(const SwigType *t) {
+ int len = Len(t);
+ const char *s = Char(t);
+ if (len >= 4 && strcmp(s + len - 2, ")>") == 0) {
+ const char *c = strstr(s, "<(");
+ return c ? NewStringWithSize(s, (int)(c - s)) : 0;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_templateargs()
+ *
+ * Returns the template arguments
+ * For example:
+ *
+ * Foo<(p.int)>::bar
+ *
+ * returns "<(p.int)>"
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_templateargs(const SwigType *t) {
+ const char *c, *d;
+ const char *start;
+ c = Char(t);
+ d = c + strlen(c);
+ while (d > c) {
+ if ((*c == '<') && (*(c + 1) == '(')) {
+ int nest = 1;
+ start = c;
+ c++;
+ while ((d > c) && nest) {
+ if (*c == '<' && *(c + 1) == '(')
+ nest++;
+ if (*c == '>' && *(c - 1) == ')')
+ nest--;
+ c++;
+ }
+ return NewStringWithSize(start, (int)(c - start));
+ }
+ c++;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istemplate()
+ *
+ * Tests a type to see if it includes template parameters
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_istemplate(const SwigType *t) {
+ char *ct = Char(t);
+ ct = strstr(ct, "<(");
+ if (ct && (strstr(ct + 2, ")>")))
+ return 1;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_base()
+ *
+ * This function returns the base of a type. For example, if you have a
+ * type "p.p.int", the function would return "int".
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_base(const SwigType *t) {
+ char *c;
+ char *lastop = 0;
+ c = Char(t);
+
+ lastop = c;
+
+ /* Search for the last type constructor separator '.' */
+ while (*c) {
+ if (*c == '.') {
+ if (*(c + 1)) {
+ lastop = c + 1;
+ }
+ c++;
+ continue;
+ }
+ if (*c == '<' && *(c + 1) == '(') {
+ /* start of template parameters --- the remainder is part of the base */
+ break;
+ }
+ if (*c == '(') {
+ /* Skip over params */
+ int nparen = 1;
+ c++;
+ while ((*c) && (nparen > 0)) {
+ if (*c == '(')
+ nparen++;
+ else if (*c == ')')
+ nparen--;
+ c++;
+ }
+ if (nparen)
+ break;
+ continue;
+ }
+ c++;
+ }
+ return NewString(lastop);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_prefix()
+ *
+ * Returns the prefix of a datatype. For example, the prefix of the
+ * type "p.p.int" is "p.p.".
+ * ----------------------------------------------------------------------------- */
+
+String *SwigType_prefix(const SwigType *t) {
+ char *c, *d;
+ String *r = 0;
+
+ c = Char(t);
+ d = c + strlen(c);
+
+ /* Check for a type constructor */
+ if ((d > c) && (*(d - 1) == '.'))
+ d--;
+
+ while (d > c) {
+ d--;
+ if (*d == '>' && (d > c) && *(d - 1) == ')') {
+ /* skip over template parameters */
+ int nest = 1;
+ d--;
+ d--;
+ while ((d > c) && (nest)) {
+ if (*d == '>' && *(d - 1) == ')')
+ nest++;
+ if (*d == '<' && *(d + 1) == '(')
+ nest--;
+ d--;
+ }
+ }
+
+ if (*d == ')') {
+ /* Skip over params */
+ int nparen = 1;
+ d--;
+ while ((d > c) && (nparen)) {
+ if (*d == ')')
+ nparen++;
+ if (*d == '(')
+ nparen--;
+ d--;
+ }
+ }
+
+ if (*d == '.') {
+ char x = *(d + 1);
+ *(d + 1) = 0;
+ r = NewString(c);
+ *(d + 1) = x;
+ return r;
+ }
+ }
+ return NewStringEmpty();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_strip_qualifiers()
+ *
+ * Strip all qualifiers from a type and return a new type
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_strip_qualifiers(const SwigType *t) {
+ static Hash *memoize_stripped = 0;
+ SwigType *r;
+ List *l;
+ Iterator ei;
+
+ if (!memoize_stripped)
+ memoize_stripped = NewHash();
+ r = Getattr(memoize_stripped, t);
+ if (r)
+ return Copy(r);
+
+ l = SwigType_split(t);
+ r = NewStringEmpty();
+
+ for (ei = First(l); ei.item; ei = Next(ei)) {
+ if (SwigType_isqualifier(ei.item))
+ continue;
+ Append(r, ei.item);
+ }
+ Delete(l);
+ {
+ String *key, *value;
+ key = Copy(t);
+ value = Copy(r);
+ Setattr(memoize_stripped, key, value);
+ Delete(key);
+ Delete(value);
+ }
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_strip_single_qualifier()
+ *
+ * If the type contains a qualifier, strip one qualifier and return a new type.
+ * The left most qualifier is stripped first (when viewed as C source code) but
+ * this is the equivalent to the right most qualifier using SwigType notation.
+ * Example:
+ * r.q(const).p.q(const).int => r.q(const).p.int
+ * r.q(const).p.int => r.p.int
+ * r.p.int => r.p.int
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_strip_single_qualifier(const SwigType *t) {
+ static Hash *memoize_stripped = 0;
+ SwigType *r = 0;
+ List *l;
+ int numitems;
+
+ if (!memoize_stripped)
+ memoize_stripped = NewHash();
+ r = Getattr(memoize_stripped, t);
+ if (r)
+ return Copy(r);
+
+ l = SwigType_split(t);
+
+ numitems = Len(l);
+ if (numitems >= 2) {
+ int item;
+ /* iterate backwards from last but one item */
+ for (item = numitems - 2; item >= 0; --item) {
+ String *subtype = Getitem(l, item);
+ if (SwigType_isqualifier(subtype)) {
+ Iterator it;
+ Delitem(l, item);
+ r = NewStringEmpty();
+ for (it = First(l); it.item; it = Next(it)) {
+ Append(r, it.item);
+ }
+ break;
+ }
+ }
+ }
+ if (!r)
+ r = Copy(t);
+
+ Delete(l);
+ {
+ String *key, *value;
+ key = Copy(t);
+ value = Copy(r);
+ Setattr(memoize_stripped, key, value);
+ Delete(key);
+ Delete(value);
+ }
+ return r;
+}
+
diff --git a/contrib/tools/swig/Source/Swig/typesys.c b/contrib/tools/swig/Source/Swig/typesys.c
new file mode 100644
index 00000000000..7ea21074896
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/typesys.c
@@ -0,0 +1,2301 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * typesys.c
+ *
+ * SWIG type system management. These functions are used to manage
+ * the C++ type system including typenames, typedef, type scopes,
+ * inheritance, and namespaces. Generation of support code for the
+ * run-time type checker is also handled here.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include "cparse.h"
+
+/* -----------------------------------------------------------------------------
+ * Synopsis
+ *
+ * The purpose of this module is to manage type names and scoping issues related
+ * to the C++ type system. The primary use is tracking typenames through typedef
+ * and inheritance.
+ *
+ * New typenames are introduced by typedef, class, and enum declarations.
+ * Each type is declared in a scope. This is either the global scope, a
+ * class, or a namespace. For example:
+ *
+ * typedef int A; // Typename A, in global scope
+ * namespace Foo {
+ * typedef int A; // Typename A, in scope Foo::
+ * }
+ * class Bar { // Typename Bar, in global scope
+ * typedef int A; // Typename A, in scope Bar::
+ * }
+ *
+ * To manage scopes, the type system is constructed as a tree of hash tables. Each
+ * hash table contains the following attributes:
+ *
+ * "name" - Scope name
+ * "qname" - Fully qualified typename
+ * "typetab" - Type table containing typenames and typedef information
+ * For a given key in the typetab table, the value is a fully
+ * qualified name if not pointing to itself.
+ * "symtab" - Hash table of symbols defined in a scope
+ * "inherit" - List of inherited scopes
+ * "parent" - Parent scope
+ *
+ * The contents of these tables can be viewed for debugging using the -debug-typedef
+ * option which calls SwigType_print_scope().
+ *
+ * Typedef information is stored in the "typetab" hash table. For example,
+ * if you have these declarations:
+ *
+ * typedef int A;
+ * typedef A B;
+ * typedef B *C;
+ *
+ * typetab in scope '' contains:
+ * "A" : "int"
+ * "B" : "A"
+ * "C" : "p.B"
+ *
+ * To resolve a type back to its root type, one repeatedly expands on the type base.
+ * For example:
+ *
+ * C *[40] ---> a(40).p.C (string type representation, see stype.c)
+ * ---> a(40).p.p.B (C --> p.B)
+ * ---> a(40).p.p.A (B --> A)
+ * ---> a(40).p.p.int (A --> int)
+ *
+ *
+ * Using declarations are stored in the "typetab" hash table. For example,
+ *
+ * namespace NN {
+ * struct SS {};
+ * }
+ * namespace N {
+ * struct S {};
+ * using NN::SS;
+ * }
+ * using N::S;
+ *
+ * typetab in scope '' contains:
+ * "S" : "N::S"
+ *
+ * and typetab in scope 'N' contains:
+ * "SS" : "NN::SS"
+ * "S" : "S"
+ *
+ *
+ * For inheritance, SWIG tries to resolve types back to the base class. For instance, if
+ * you have this:
+ *
+ * class Foo {
+ * public:
+ * typedef int Integer;
+ * };
+ * struct Bar : public Foo {
+ * void blah(Integer x);
+ * };
+ *
+ * In this case typetab in scope '' contains:
+ * "Foo" : "Foo"
+ * "Bar" : "Bar"
+ * and scope 'Foo' contains:
+ * "Integer" : "int"
+ * and scope 'Bar' inherits from 'Foo' but is empty (observe that blah is not a scope or typedef)
+ *
+ * The argument type of Bar::blah will be set to Foo::Integer.
+ *
+ *
+ * The scope-inheritance mechanism is used to manage C++ using directives.
+ *
+ * namespace XX {
+ * class CC {};
+ * }
+ * namespace X {
+ * class C {};
+ * using namespace XX;
+ * }
+ * using namespace X;
+ *
+ * typetab in scope '' inherits from 'X'
+ * typetab in scope 'X' inherits from 'XX' and contains:
+ * "C" : "C"
+ * typetab in scope 'XX' contains:
+ * "CC" : "CC"
+ *
+ *
+ * The scope-inheritance mechanism is used to manage C++ namespace aliases.
+ * For example, if you have this:
+ *
+ * namespace Foo {
+ * typedef int Integer;
+ * }
+ *
+ * namespace F = Foo;
+ *
+ * In this case, F is defined as a scope that "inherits" from Foo. Internally,
+ * F will merely be an empty scope that points to Foo. SWIG will never
+ * place new type information into a namespace alias---attempts to do so
+ * will generate a warning message (in the parser) and will place information into
+ * Foo instead.
+ *
+ *----------------------------------------------------------------------------- */
+
+static Typetab *current_scope = 0; /* Current type scope */
+static Hash *current_typetab = 0; /* Current type table */
+static Hash *current_symtab = 0; /* Current symbol table */
+static Typetab *global_scope = 0; /* The global scope */
+static Hash *scopes = 0; /* Hash table containing fully qualified scopes */
+
+/* Performance optimization */
+#define SWIG_TYPEDEF_RESOLVE_CACHE
+static Hash *typedef_resolve_cache = 0;
+static Hash *typedef_all_cache = 0;
+static Hash *typedef_qualified_cache = 0;
+
+static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix);
+
+/* common attribute keys, to avoid calling find_key all the times */
+
+/*
+ Enable this one if your language fully support SwigValueWrapper<T>.
+
+ Leaving at '0' keeps the old swig behavior, which is not
+ always safe, but is well known.
+
+ Setting at '1' activates the new scheme, which is always safe but
+ it requires all the typemaps to be ready for that.
+
+*/
+static int value_wrapper_mode = 0;
+int Swig_value_wrapper_mode(int mode) {
+ value_wrapper_mode = mode;
+ return mode;
+}
+
+
+static void flush_cache(void) {
+ typedef_resolve_cache = 0;
+ typedef_all_cache = 0;
+ typedef_qualified_cache = 0;
+}
+
+/* Initialize the scoping system */
+
+void SwigType_typesystem_init(void) {
+ if (global_scope)
+ Delete(global_scope);
+ if (scopes)
+ Delete(scopes);
+
+ current_scope = NewHash();
+ global_scope = current_scope;
+
+ Setattr(current_scope, "name", ""); /* No name for global scope */
+ current_typetab = NewHash();
+ Setattr(current_scope, "typetab", current_typetab);
+
+ current_symtab = 0;
+ scopes = NewHash();
+ Setattr(scopes, "", current_scope);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef()
+ *
+ * Defines a new typedef in the current scope. Returns -1 if the type name is
+ * already defined.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
+ /* Printf(stdout, "typedef %s %s\n", type, name); */
+ if (Getattr(current_typetab, name))
+ return -1; /* Already defined */
+ if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
+ return 0;
+ }
+
+ /* Check if 'type' is already a scope. If so, we create an alias in the type
+ system for it. This is needed to make strange nested scoping problems work
+ correctly. */
+ {
+ Typetab *t = SwigType_find_scope(current_scope, type);
+ if (t) {
+ SwigType_new_scope(name);
+ SwigType_inherit_scope(t);
+ SwigType_pop_scope();
+ }
+ }
+ Setattr(current_typetab, name, type);
+ flush_cache();
+ return 0;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_class()
+ *
+ * Defines a class in the current scope.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_typedef_class(const_String_or_char_ptr name) {
+ String *cname;
+ /* Printf(stdout,"class : '%s'\n", name); */
+ if (Getattr(current_typetab, name))
+ return -1; /* Already defined */
+ cname = NewString(name);
+ Setmeta(cname, "class", "1");
+ Setattr(current_typetab, cname, cname);
+ Delete(cname);
+ flush_cache();
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_scope_name()
+ *
+ * Returns the qualified scope name of a type table
+ * ----------------------------------------------------------------------------- */
+
+static String *SwigType_scope_name(Typetab *ttab) {
+ String *qname = NewString(Getattr(ttab, "name"));
+ ttab = Getattr(ttab, "parent");
+ while (ttab) {
+ String *pname = Getattr(ttab, "name");
+ if (Len(pname)) {
+ Insert(qname, 0, "::");
+ Insert(qname, 0, pname);
+ }
+ ttab = Getattr(ttab, "parent");
+ }
+ return qname;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_new_scope()
+ *
+ * Creates a new scope
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_new_scope(const_String_or_char_ptr name) {
+ Typetab *s;
+ Hash *ttab;
+ String *qname;
+
+ if (!name) {
+ name = "<unnamed>";
+ }
+ s = NewHash();
+ Setattr(s, "name", name);
+ Setattr(s, "parent", current_scope);
+ ttab = NewHash();
+ Setattr(s, "typetab", ttab);
+
+ /* Build fully qualified name */
+ qname = SwigType_scope_name(s);
+#if 1
+ {
+ /* TODO: only do with templates? What happens with non-templates with code below? */
+ String *stripped_qname;
+ stripped_qname = SwigType_remove_global_scope_prefix(qname);
+ /* Use fully qualified name for hash key without unary scope prefix, qname may contain unary scope */
+ Setattr(scopes, stripped_qname, s);
+ Setattr(s, "qname", qname);
+ /*
+ Printf(stdout, "SwigType_new_scope stripped %s %s\n", qname, stripped_qname);
+ */
+ Delete(stripped_qname);
+ }
+#else
+ Printf(stdout, "SwigType_new_scope %s\n", qname);
+ Setattr(scopes, qname, s);
+ Setattr(s, "qname", qname);
+#endif
+ Delete(qname);
+
+ current_scope = s;
+ current_typetab = ttab;
+ current_symtab = 0;
+ flush_cache();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_inherit_scope()
+ *
+ * Makes the current scope inherit from another scope. This is used for both
+ * C++ class inheritance, namespaces, and namespace aliases.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_inherit_scope(Typetab *scope) {
+ List *inherits;
+ int i, len;
+ inherits = Getattr(current_scope, "inherit");
+ if (!inherits) {
+ inherits = NewList();
+ Setattr(current_scope, "inherit", inherits);
+ Delete(inherits);
+ }
+ assert(scope != current_scope);
+
+ len = Len(inherits);
+ for (i = 0; i < len; i++) {
+ Node *n = Getitem(inherits, i);
+ if (n == scope)
+ return;
+ }
+ Append(inherits, scope);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_scope_alias()
+ *
+ * Creates a scope-alias.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_scope_alias(String *aliasname, Typetab *ttab) {
+ String *q;
+ /* Printf(stdout,"alias: '%s' '%p'\n", aliasname, ttab); */
+ q = SwigType_scope_name(current_scope);
+ if (Len(q)) {
+ Append(q, "::");
+ }
+ Append(q, aliasname);
+ Setattr(scopes, q, ttab);
+ flush_cache();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_using_scope()
+ *
+ * Import another scope into this scope.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_using_scope(Typetab *scope) {
+ SwigType_inherit_scope(scope);
+ {
+ List *ulist;
+ int i, len;
+ ulist = Getattr(current_scope, "using");
+ if (!ulist) {
+ ulist = NewList();
+ Setattr(current_scope, "using", ulist);
+ Delete(ulist);
+ }
+ assert(scope != current_scope);
+ len = Len(ulist);
+ for (i = 0; i < len; i++) {
+ Typetab *n = Getitem(ulist, i);
+ if (n == scope)
+ return;
+ }
+ Append(ulist, scope);
+ }
+ flush_cache();
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_pop_scope()
+ *
+ * Pop off the last scope and perform a merge operation. Returns the hash
+ * table for the scope that was popped off.
+ * ----------------------------------------------------------------------------- */
+
+Typetab *SwigType_pop_scope(void) {
+ Typetab *t, *old = current_scope;
+ t = Getattr(current_scope, "parent");
+ if (!t)
+ t = global_scope;
+ current_scope = t;
+ current_typetab = Getattr(t, "typetab");
+ current_symtab = Getattr(t, "symtab");
+ flush_cache();
+ return old;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_set_scope()
+ *
+ * Set the scope. Returns the old scope.
+ * ----------------------------------------------------------------------------- */
+
+Typetab *SwigType_set_scope(Typetab *t) {
+ Typetab *old = current_scope;
+ if (!t)
+ t = global_scope;
+ current_scope = t;
+ current_typetab = Getattr(t, "typetab");
+ current_symtab = Getattr(t, "symtab");
+ flush_cache();
+ return old;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_attach_symtab()
+ *
+ * Attaches a symbol table to a type scope
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_attach_symtab(Symtab *sym) {
+ Setattr(current_scope, "symtab", sym);
+ current_symtab = sym;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_print_scope()
+ *
+ * Debugging function for printing out current scope
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_print_scope(void) {
+ Hash *ttab;
+ Iterator i, j;
+
+ Printf(stdout, "SCOPES start =======================================\n");
+ for (i = First(scopes); i.key; i = Next(i)) {
+ Printf(stdout, "-------------------------------------------------------------\n");
+ ttab = Getattr(i.item, "typetab");
+
+ Printf(stdout, "Type scope '%s' (%p)\n", i.key, i.item);
+ {
+ List *inherit = Getattr(i.item, "inherit");
+ if (inherit) {
+ Iterator j;
+ for (j = First(inherit); j.item; j = Next(j)) {
+ Printf(stdout, " Inherits from '%s' (%p)\n", Getattr(j.item, "qname"), j.item);
+ }
+ }
+ }
+ for (j = First(ttab); j.key; j = Next(j)) {
+ Printf(stdout, "%40s -> %s\n", j.key, j.item);
+ }
+ }
+ Printf(stdout, "SCOPES finish =======================================\n");
+}
+
+static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
+ Typetab *ss;
+ Typetab *s_orig = s;
+ String *nnameprefix = 0;
+ static int check_parent = 1;
+ int is_template = 0;
+
+ if (Getmark(s))
+ return 0;
+ Setmark(s, 1);
+
+ is_template = SwigType_istemplate(nameprefix);
+ if (is_template) {
+ nnameprefix = SwigType_typedef_resolve_all(nameprefix);
+ nameprefix = nnameprefix;
+ }
+
+ ss = s;
+ while (ss) {
+ String *full;
+ String *qname = Getattr(ss, "qname");
+ if (qname) {
+ full = NewStringf("%s::%s", qname, nameprefix);
+ if (Strncmp(full, "enum ", 5) == 0) {
+ Delslice(full, 0, 5);
+ }
+ } else {
+ full = NewString(nameprefix);
+ }
+ s = Getattr(scopes, full);
+ if (!s && is_template) {
+ /* try look up scope with all the unary scope operators within the template parameter list removed */
+ SwigType *full_stripped = SwigType_remove_global_scope_prefix(full);
+ s = Getattr(scopes, full_stripped);
+ Delete(full_stripped);
+ }
+ Delete(full);
+ if (s) {
+ if (nnameprefix)
+ Delete(nnameprefix);
+ Setmark(s_orig, 0);
+ return s;
+ }
+ if (!s) {
+ /* Check inheritance */
+ List *inherit;
+ inherit = Getattr(ss, "using");
+ if (inherit) {
+ Typetab *ttab;
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ int oldcp = check_parent;
+ ttab = Getitem(inherit, i);
+ check_parent = 0;
+ s = SwigType_find_scope(ttab, nameprefix);
+ check_parent = oldcp;
+ if (s) {
+ if (nnameprefix)
+ Delete(nnameprefix);
+ Setmark(s_orig, 0);
+ return s;
+ }
+ }
+ }
+ }
+ if (!check_parent)
+ break;
+ ss = Getattr(ss, "parent");
+ }
+ if (nnameprefix)
+ Delete(nnameprefix);
+ Setmark(s_orig, 0);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * typedef_resolve()
+ *
+ * Resolves a typedef and returns a new type string. Returns 0 if there is no
+ * typedef mapping. base is a name without qualification.
+ * Internal function.
+ * ----------------------------------------------------------------------------- */
+
+static Typetab *resolved_scope = 0;
+
+/* Internal function */
+
+static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
+ Hash *ttab;
+ SwigType *type = 0;
+ List *inherit;
+ Typetab *parent;
+
+ /* if (!s) return 0; *//* now is checked below */
+ /* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */
+
+ if (!Getmark(s)) {
+ Setmark(s, 1);
+
+ ttab = Getattr(s, "typetab");
+ type = Getattr(ttab, base);
+ if (type) {
+ resolved_scope = s;
+ Setmark(s, 0);
+ } else {
+ /* Hmmm. Not found in my scope. It could be in an inherited scope */
+ inherit = Getattr(s, "inherit");
+ if (inherit) {
+ int i, len;
+ len = Len(inherit);
+ for (i = 0; i < len; i++) {
+ type = _typedef_resolve(Getitem(inherit, i), base, 0);
+ if (type) {
+ Setmark(s, 0);
+ break;
+ }
+ }
+ }
+ if (!type) {
+ /* Hmmm. Not found in my scope. check parent */
+ if (look_parent) {
+ parent = Getattr(s, "parent");
+ type = parent ? _typedef_resolve(parent, base, 1) : 0;
+ }
+ }
+ Setmark(s, 0);
+ }
+ }
+ return type;
+}
+
+/* -----------------------------------------------------------------------------
+ * template_parameters_resolve()
+ *
+ * For use with templates only. Attempts to resolve one template parameter.
+ *
+ * If one of the template parameters can be resolved, the type is returned with
+ * just the one parameter resolved and the remaining parameters left as is.
+ * If none of the template parameters can be resolved, zero is returned.
+ * ----------------------------------------------------------------------------- */
+
+static String *template_parameters_resolve(const String *base) {
+ List *tparms;
+ String *suffix;
+ String *type;
+ int i, sz;
+ int rep = 0;
+ type = SwigType_templateprefix(base);
+ suffix = SwigType_templatesuffix(base);
+ Append(type, "<(");
+ tparms = SwigType_parmlist(base);
+ sz = Len(tparms);
+ for (i = 0; i < sz; i++) {
+ SwigType *tpr;
+ SwigType *tp = Getitem(tparms, i);
+ if (!rep) {
+ tpr = SwigType_typedef_resolve(tp);
+ } else {
+ tpr = 0;
+ }
+ if (tpr) {
+ Append(type, tpr);
+ Delete(tpr);
+ rep = 1;
+ } else {
+ Append(type, tp);
+ }
+ if ((i + 1) < sz)
+ Append(type, ",");
+ }
+ if (rep) {
+ Append(type, ")>");
+ Append(type, suffix);
+ } else {
+ Delete(type);
+ type = 0;
+ }
+ Delete(suffix);
+ Delete(tparms);
+ return type;
+}
+
+static SwigType *typedef_resolve(Typetab *s, String *base) {
+ return _typedef_resolve(s, base, 1);
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_resolve()
+ *
+ * Given a type declaration, this function looks to reduce/resolve the type via a
+ * typedef (including via C++ using declarations).
+ *
+ * If it is able to find a typedef, the resolved type is returned. If no typedef
+ * is found NULL is returned. The type name is resolved in the current scope.
+ * The type returned is not always fully qualified for the global scope, it is
+ * valid for use in the current scope. If the current scope is global scope, a
+ * fully qualified type should be returned.
+ *
+ * Some additional notes are in Doc/Manual/Extending.html.
+ * ----------------------------------------------------------------------------- */
+
+/* #define SWIG_DEBUG */
+SwigType *SwigType_typedef_resolve(const SwigType *t) {
+ String *base;
+ String *type = 0;
+ String *r = 0;
+ Typetab *s;
+ Hash *ttab;
+ String *namebase = 0;
+ String *nameprefix = 0, *rnameprefix = 0;
+ int newtype = 0;
+
+ resolved_scope = 0;
+
+#ifdef SWIG_TYPEDEF_RESOLVE_CACHE
+ if (!typedef_resolve_cache) {
+ typedef_resolve_cache = NewHash();
+ }
+ r = Getattr(typedef_resolve_cache, t);
+ if (r) {
+ resolved_scope = Getmeta(r, "scope");
+ return Copy(r);
+ }
+#endif
+
+ base = SwigType_base(t);
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "base = '%s' t='%s'\n", base, t);
+#endif
+
+ if (SwigType_issimple(base)) {
+ s = current_scope;
+ ttab = current_typetab;
+ if (strncmp(Char(base), "::", 2) == 0) {
+ s = global_scope;
+ ttab = Getattr(s, "typetab");
+ Delitem(base, 0);
+ Delitem(base, 0);
+ }
+ /* Do a quick check in the local scope */
+ type = Getattr(ttab, base);
+ if (type) {
+ resolved_scope = s;
+ }
+ if (!type) {
+ /* Didn't find in this scope. We need to do a little more searching */
+ if (Swig_scopename_check(base)) {
+ /* A qualified name. */
+ Swig_scopename_split(base, &nameprefix, &namebase);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "nameprefix = '%s'\n", nameprefix);
+#endif
+ if (nameprefix) {
+ rnameprefix = SwigType_typedef_resolve(nameprefix);
+ if(rnameprefix != NULL) {
+#ifdef SWIG_DEBUG
+ Printf(stdout, "nameprefix '%s' is a typedef to '%s'\n", nameprefix, rnameprefix);
+#endif
+ type = Copy(namebase);
+ Insert(type, 0, "::");
+ Insert(type, 0, rnameprefix);
+ if (Strncmp(type, "enum ", 5) == 0) {
+ Delslice(type, 0, 5);
+ }
+ if (Strncmp(type, "::", 2) == 0) {
+ Delslice(type, 0, 2);
+ }
+ newtype = 1;
+ } else {
+ /* Name had a prefix on it. See if we can locate the proper scope for it */
+ String *rnameprefix = template_parameters_resolve(nameprefix);
+ nameprefix = rnameprefix ? Copy(rnameprefix) : nameprefix;
+ Delete(rnameprefix);
+ s = SwigType_find_scope(s, nameprefix);
+
+ /* Couldn't locate a scope for the type. */
+ if (!s) {
+ Delete(base);
+ Delete(namebase);
+ Delete(nameprefix);
+ r = 0;
+ goto return_result;
+ }
+ /* Try to locate the name starting in the scope */
+#ifdef SWIG_DEBUG
+ Printf(stdout, "namebase = '%s'\n", namebase);
+#endif
+ type = typedef_resolve(s, namebase);
+ if (type && resolved_scope) {
+ /* we need to look for the resolved type, this will also
+ fix the resolved_scope if 'type' and 'namebase' are
+ declared in different scopes */
+ String *rtype = 0;
+ rtype = typedef_resolve(resolved_scope, type);
+ if (rtype)
+ type = rtype;
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "%s type = '%s'\n", Getattr(s, "name"), type);
+#endif
+ if ((type) && (!Swig_scopename_check(type)) && resolved_scope) {
+ Typetab *rtab = resolved_scope;
+ String *qname = Getattr(resolved_scope, "qname");
+ /* If qualified *and* the typename is defined from the resolved scope, we qualify */
+ if ((qname) && typedef_resolve(resolved_scope, type)) {
+ type = Copy(type);
+ Insert(type, 0, "::");
+ Insert(type, 0, qname);
+#ifdef SWIG_DEBUG
+ Printf(stdout, "qual %s \n", type);
+#endif
+ newtype = 1;
+ }
+ resolved_scope = rtab;
+ }
+ }
+ } else {
+ /* Name is unqualified. */
+ type = typedef_resolve(s, base);
+ }
+ } else {
+ /* Name is unqualified. */
+ type = typedef_resolve(s, base);
+ }
+ }
+
+ if (!type && SwigType_istemplate(base)) {
+ String *tprefix = SwigType_templateprefix(base);
+ String *rtprefix = SwigType_typedef_resolve(tprefix);
+ /* We're looking for a using declaration on the template prefix to resolve the template prefix
+ * in another scope. Using declaration do not have template parameters. */
+ if (rtprefix && !SwigType_istemplate(rtprefix)) {
+ String *tsuffix = SwigType_templatesuffix(base);
+ String *targs = SwigType_templateargs(base);
+ type = NewString(rtprefix);
+ newtype = 1;
+ Append(type, targs);
+ Append(type, tsuffix);
+ Delete(targs);
+ Delete(tsuffix);
+ Delete(rtprefix);
+ }
+ Delete(tprefix);
+ }
+
+ if (type && (Equal(base, type))) {
+ if (newtype)
+ Delete(type);
+ Delete(base);
+ Delete(namebase);
+ Delete(nameprefix);
+ r = 0;
+ goto return_result;
+ }
+
+ /* If the type is a template, and no typedef was found, we need to check the
+ template arguments one by one to see if they can be resolved. */
+
+ if (!type && SwigType_istemplate(base)) {
+ newtype = 1;
+ type = template_parameters_resolve(base);
+ }
+ Delete(namebase);
+ Delete(nameprefix);
+ } else {
+ if (SwigType_isfunction(base)) {
+ List *parms;
+ int i, sz;
+ int rep = 0;
+ type = NewString("f(");
+ newtype = 1;
+ parms = SwigType_parmlist(base);
+ sz = Len(parms);
+ for (i = 0; i < sz; i++) {
+ SwigType *tpr;
+ SwigType *tp = Getitem(parms, i);
+ if (!rep) {
+ tpr = SwigType_typedef_resolve(tp);
+ } else {
+ tpr = 0;
+ }
+ if (tpr) {
+ Append(type, tpr);
+ Delete(tpr);
+ rep = 1;
+ } else {
+ Append(type, tp);
+ }
+ if ((i + 1) < sz)
+ Append(type, ",");
+ }
+ Append(type, ").");
+ Delete(parms);
+ if (!rep) {
+ Delete(type);
+ type = 0;
+ }
+ } else if (SwigType_ismemberpointer(base)) {
+ String *rt;
+ String *mtype = SwigType_parm(base);
+ rt = SwigType_typedef_resolve(mtype);
+ if (rt) {
+ type = NewStringf("m(%s).", rt);
+ newtype = 1;
+ Delete(rt);
+ }
+ Delete(mtype);
+ } else {
+ type = 0;
+ }
+ }
+ r = SwigType_prefix(t);
+ if (!type) {
+ if (r && Len(r)) {
+ char *cr = Char(r);
+ if ((strstr(cr, "f(") || (strstr(cr, "m(")))) {
+ SwigType *rt = SwigType_typedef_resolve(r);
+ if (rt) {
+ Delete(r);
+ Append(rt, base);
+ Delete(base);
+ r = rt;
+ goto return_result;
+ }
+ }
+ }
+ Delete(r);
+ Delete(base);
+ r = 0;
+ goto return_result;
+ }
+ Delete(base);
+
+ /* If 'type' is an array, then the right-most qualifier in 'r' should
+ be added to 'type' after the array qualifier, so that given
+ a(7).q(volatile).double myarray // typedef volatile double[7] myarray;
+ the type
+ q(const).myarray // const myarray
+ becomes
+ a(7).q(const volatile).double // const volatile double[7]
+ and NOT
+ q(const).a(7).q(volatile).double // non-sensical type
+ */
+ if (r && Len(r) && SwigType_isarray(type)) {
+ List *r_elem;
+ String *r_qual;
+ int r_sz;
+ r_elem = SwigType_split(r);
+ r_sz = Len(r_elem);
+ r_qual = Getitem(r_elem, r_sz-1);
+ if (SwigType_isqualifier(r_qual)) {
+ String *new_r;
+ String *new_type;
+ List *type_elem;
+ String *type_qual;
+ String *r_qual_arg;
+ int i, type_sz;
+
+ type_elem = SwigType_split(type);
+ type_sz = Len(type_elem);
+
+ for (i = 0; i < type_sz; ++i) {
+ String *e = Getitem(type_elem, i);
+ if (!SwigType_isarray(e))
+ break;
+ }
+ type_qual = Copy(Getitem(type_elem, i));
+ r_qual_arg = SwigType_parm(r_qual);
+ SwigType_add_qualifier(type_qual, r_qual_arg);
+ Delete(r_qual_arg);
+ Setitem(type_elem, i, type_qual);
+
+ new_r = NewStringEmpty();
+ for (i = 0; i < r_sz-1; ++i) {
+ Append(new_r, Getitem(r_elem, i));
+ }
+ new_type = NewStringEmpty();
+ for (i = 0; i < type_sz; ++i) {
+ Append(new_type, Getitem(type_elem, i));
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "r+type='%s%s' new_r+new_type='%s%s'\n", r, type, new_r, new_type);
+#endif
+
+ Delete(r);
+ r = new_r;
+ newtype = 1;
+ type = new_type;
+ Delete(type_elem);
+ }
+ Delete(r_elem);
+ }
+
+ Append(r, type);
+ if (newtype) {
+ Delete(type);
+ }
+
+return_result:
+#ifdef SWIG_TYPEDEF_RESOLVE_CACHE
+ {
+ String *key = NewString(t);
+ if (r) {
+ SwigType *r1;
+ Setattr(typedef_resolve_cache, key, r);
+ Setmeta(r, "scope", resolved_scope);
+ r1 = Copy(r);
+ Delete(r);
+ r = r1;
+ }
+ Delete(key);
+ }
+#endif
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_resolve_all()
+ *
+ * Fully resolve a type down to its most basic datatype
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
+ SwigType *n;
+ SwigType *r;
+ int count = 0;
+
+ /* Check to see if the typedef resolve has been done before by checking the cache */
+ if (!typedef_all_cache) {
+ typedef_all_cache = NewHash();
+ }
+ r = Getattr(typedef_all_cache, t);
+ if (r) {
+ return Copy(r);
+ }
+
+#ifdef SWIG_DEBUG
+ Printf(stdout, "SwigType_typedef_resolve_all start ... %s\n", t);
+#endif
+ /* Recursively resolve the typedef */
+ r = NewString(t);
+ while ((n = SwigType_typedef_resolve(r))) {
+ Delete(r);
+ r = n;
+ if (++count >= 512) {
+ Swig_error(Getfile(t), Getline(t), "Recursive typedef detected resolving '%s' to '%s' to '%s' and so on...\n", SwigType_str(t, 0), SwigType_str(SwigType_typedef_resolve(t), 0), SwigType_str(SwigType_typedef_resolve(SwigType_typedef_resolve(t)), 0));
+ break;
+ }
+ }
+
+ /* Add the typedef to the cache for next time it is looked up */
+ {
+ String *key;
+ SwigType *rr = Copy(r);
+ key = NewString(t);
+ Setattr(typedef_all_cache, key, rr);
+ Delete(key);
+ Delete(rr);
+ }
+#ifdef SWIG_DEBUG
+ Printf(stdout, "SwigType_typedef_resolve_all end === %s => %s\n", t, r);
+#endif
+ return r;
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_qualified()
+ *
+ * Given a type declaration, this function tries to fully qualify it so that the
+ * resulting type can be used in the global scope. The type name is resolved in
+ * the current scope.
+ *
+ * It provides a fully qualified name, not necessarily a fully expanded name.
+ * When a using declaration or using directive is found the type may not be fully
+ * expanded, but it will be resolved and fully qualified for use in the global scope.
+ *
+ * This function is for looking up scopes to qualify a type. It does not resolve
+ * C typedefs, it just qualifies them. See SwigType_typedef_resolve for resolving.
+ *
+ * If the unary scope operator (::) is used as a prefix to the type to denote global
+ * scope, it is left in place.
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_typedef_qualified(const SwigType *t) {
+ List *elements;
+ String *result;
+ int i, len;
+
+ if (!typedef_qualified_cache)
+ typedef_qualified_cache = NewHash();
+ result = Getattr(typedef_qualified_cache, t);
+ if (result) {
+ String *rc = Copy(result);
+ return rc;
+ }
+
+ result = NewStringEmpty();
+ elements = SwigType_split(t);
+ len = Len(elements);
+ for (i = 0; i < len; i++) {
+ String *ty = 0;
+ String *e = Getitem(elements, i);
+ if (SwigType_issimple(e)) {
+ if (!SwigType_istemplate(e)) {
+ String *isenum = 0;
+ if (SwigType_isenum(e)) {
+ isenum = NewString("enum ");
+ ty = NewString(Char(e) + 5);
+ e = ty;
+ }
+ resolved_scope = 0;
+ if (typedef_resolve(current_scope, e) && resolved_scope) {
+ /* resolved_scope contains the scope that actually resolved the symbol */
+ String *qname = Getattr(resolved_scope, "qname");
+ if (qname) {
+ Insert(e, 0, "::");
+ Insert(e, 0, qname);
+ }
+ } else {
+ if (Swig_scopename_check(e)) {
+ String *qlast;
+ String *qname;
+ Swig_scopename_split(e, &qname, &qlast);
+ if (qname) {
+ String *tqname = SwigType_typedef_qualified(qname);
+ Clear(e);
+ Printf(e, "%s::%s", tqname, qlast);
+ Delete(qname);
+ Delete(tqname);
+ }
+ Delete(qlast);
+
+ /* Automatic template instantiation might go here??? */
+ } else {
+ /* It's a bare name. It's entirely possible, that the
+ name is part of a namespace. We'll check this by unrolling
+ out of the current scope */
+
+ Typetab *cs = current_scope;
+ if (cs) {
+ Typetab *found_scope = SwigType_find_scope(cs, e);
+ if (found_scope) {
+ String *qs = SwigType_scope_name(found_scope);
+ Clear(e);
+ Append(e, qs);
+ Delete(qs);
+ }
+ }
+ }
+ }
+ if (isenum) {
+ Insert(e, 0, isenum);
+ Delete(isenum);
+ }
+ } else {
+ /* Template. We need to qualify template parameters as well as the template itself */
+ String *tprefix, *qprefix;
+ String *tsuffix;
+ Iterator pi;
+ Parm *p;
+ List *parms;
+ ty = Swig_symbol_template_deftype(e, current_symtab);
+ e = ty;
+ parms = SwigType_parmlist(e);
+ tprefix = SwigType_templateprefix(e);
+ tsuffix = SwigType_templatesuffix(e);
+ qprefix = SwigType_typedef_qualified(tprefix);
+ Append(qprefix, "<(");
+ pi = First(parms);
+ while ((p = pi.item)) {
+ /* TODO: the logic here should be synchronised with that in symbol_template_qualify() in symbol.c */
+ String *qt = SwigType_typedef_qualified(p);
+ if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
+ /* No change in value. It is entirely possible that the parameter is an integer value.
+ If there is a symbol table associated with this scope, we're going to check for this */
+
+ if (current_symtab) {
+ Node *lastnode = 0;
+ String *value = Copy(p);
+ while (1) {
+ Node *n = Swig_symbol_clookup(value, current_symtab);
+ if (n == lastnode)
+ break;
+ lastnode = n;
+ if (n) {
+ char *ntype = Char(nodeType(n));
+ if (strcmp(ntype, "enumitem") == 0) {
+ /* An enum item. Generate a fully qualified name */
+ String *qn = Swig_symbol_qualified(n);
+ if (Len(qn)) {
+ Append(qn, "::");
+ Append(qn, Getattr(n, "name"));
+ Delete(value);
+ value = qn;
+ continue;
+ } else {
+ Delete(qn);
+ break;
+ }
+ } else if ((strcmp(ntype, "cdecl") == 0) && (Getattr(n, "value"))) {
+ Delete(value);
+ value = Copy(Getattr(n, "value"));
+ continue;
+ }
+ }
+ break;
+ }
+ Append(qprefix, value);
+ Delete(value);
+ } else {
+ Append(qprefix, p);
+ }
+ } else {
+ Append(qprefix, qt);
+ }
+ Delete(qt);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(qprefix, ",");
+ }
+ }
+ Append(qprefix, ")>");
+ Append(qprefix, tsuffix);
+ Delete(tsuffix);
+ Clear(e);
+ Append(e, qprefix);
+ Delete(tprefix);
+ Delete(qprefix);
+ Delete(parms);
+ }
+ Append(result, e);
+ Delete(ty);
+ } else if (SwigType_isfunction(e)) {
+ List *parms = SwigType_parmlist(e);
+ String *s = NewString("f(");
+ Iterator pi;
+ pi = First(parms);
+ while (pi.item) {
+ String *pq = SwigType_typedef_qualified(pi.item);
+ Append(s, pq);
+ Delete(pq);
+ pi = Next(pi);
+ if (pi.item) {
+ Append(s, ",");
+ }
+ }
+ Append(s, ").");
+ Append(result, s);
+ Delete(s);
+ Delete(parms);
+ } else if (SwigType_isarray(e)) {
+ String *ndim;
+ String *dim = SwigType_parm(e);
+ ndim = Swig_symbol_string_qualify(dim, 0);
+ Printf(result, "a(%s).", ndim);
+ Delete(dim);
+ Delete(ndim);
+ } else {
+ Append(result, e);
+ }
+ }
+ Delete(elements);
+ {
+ String *key, *cresult;
+ key = NewString(t);
+ cresult = NewString(result);
+ Setattr(typedef_qualified_cache, key, cresult);
+ Delete(key);
+ Delete(cresult);
+ }
+ return result;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_istypedef()
+ *
+ * Checks a typename to see if it is a typedef.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_istypedef(const SwigType *t) {
+ String *type;
+
+ type = SwigType_typedef_resolve(t);
+ if (type) {
+ Delete(type);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_typedef_using()
+ *
+ * Processes a 'using' declaration to import types from one scope into another.
+ * Name is a qualified name like A::B.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_typedef_using(const_String_or_char_ptr name) {
+ String *base;
+ String *td;
+ String *prefix;
+ Typetab *s;
+ Typetab *tt = 0;
+
+ String *defined_name = 0;
+
+ /* Printf(stdout, "using %s\n", name); */
+
+ if (!Swig_scopename_check(name))
+ return -1; /* Not properly qualified */
+ base = Swig_scopename_last(name);
+
+ /* See if the base is already defined in this scope */
+ if (Getattr(current_typetab, base)) {
+ Delete(base);
+ return -1;
+ }
+
+ /* See if the using name is a scope */
+ /* tt = SwigType_find_scope(current_scope,name);
+ Printf(stdout,"tt = %p, name = '%s'\n", tt, name); */
+
+ /* We set up a typedef B --> A::B */
+ Setattr(current_typetab, base, name);
+
+ /* Find the scope name where the symbol is defined */
+ td = SwigType_typedef_resolve(name);
+ /* Printf(stdout,"td = '%s' %p\n", td, resolved_scope); */
+ if (resolved_scope) {
+ defined_name = Getattr(resolved_scope, "qname");
+ if (defined_name) {
+ defined_name = Copy(defined_name);
+ Append(defined_name, "::");
+ Append(defined_name, base);
+ /* Printf(stdout,"defined_name = '%s'\n", defined_name); */
+ tt = SwigType_find_scope(current_scope, defined_name);
+ }
+ }
+ if (td)
+ Delete(td);
+
+
+ /* Figure out the scope the using directive refers to */
+ {
+ prefix = Swig_scopename_prefix(name);
+ if (prefix) {
+ s = SwigType_find_scope(current_scope, prefix);
+ if (s) {
+ Hash *ttab = Getattr(s, "typetab");
+ if (!Getattr(ttab, base) && defined_name) {
+ Setattr(ttab, base, defined_name);
+ }
+ }
+ }
+ }
+
+ if (tt) {
+ /* Using directive had its own scope. We need to create a new scope for it */
+ SwigType_new_scope(base);
+ SwigType_inherit_scope(tt);
+ SwigType_pop_scope();
+ }
+
+ if (defined_name)
+ Delete(defined_name);
+ Delete(prefix);
+ Delete(base);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_isclass()
+ *
+ * Determines if a type defines a class or not. A class is defined by
+ * its type-table entry maps to itself. Note: a pointer to a class is not
+ * a class.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_isclass(const SwigType *t) {
+ SwigType *qty, *qtys;
+ int isclass = 0;
+
+ qty = SwigType_typedef_resolve_all(t);
+ qtys = SwigType_strip_qualifiers(qty);
+ if (SwigType_issimple(qtys)) {
+ String *td = SwigType_typedef_resolve(qtys);
+ if (td) {
+ Delete(td);
+ }
+ if (resolved_scope) {
+ isclass = 1;
+ }
+ /* Hmmm. Not a class. If a template, it might be uninstantiated */
+ if (!isclass) {
+ String *tp = SwigType_istemplate_templateprefix(qtys);
+ if (tp && Strcmp(tp, t) != 0) {
+ isclass = SwigType_isclass(tp);
+ }
+ Delete(tp);
+ }
+ }
+ Delete(qty);
+ Delete(qtys);
+ return isclass;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_type()
+ *
+ * Returns an integer code describing the datatype. This is only used for
+ * compatibility with SWIG1.1 language modules and is likely to go away once
+ * everything is based on typemaps.
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_type(const SwigType *t) {
+ char *c;
+ /* Check for the obvious stuff */
+ c = Char(t);
+
+ if (strncmp(c, "p.", 2) == 0) {
+ if (SwigType_type(c + 2) == T_CHAR)
+ return T_STRING;
+ else if (SwigType_type(c + 2) == T_WCHAR)
+ return T_WSTRING;
+ else
+ return T_POINTER;
+ }
+ if (strncmp(c, "a(", 2) == 0)
+ return T_ARRAY;
+ if (strncmp(c, "r.", 2) == 0)
+ return T_REFERENCE;
+ if (strncmp(c, "z.", 2) == 0)
+ return T_RVALUE_REFERENCE;
+ if (strncmp(c, "m(", 2) == 0)
+ return T_MPOINTER;
+ if (strncmp(c, "q(", 2) == 0) {
+ while (*c && (*c != '.'))
+ c++;
+ if (*c)
+ return SwigType_type(c + 1);
+ Printf(stderr, "*** Internal error: Invalid type string '%s'\n", t);
+ Exit(EXIT_FAILURE);
+ }
+ if (strncmp(c, "f(", 2) == 0)
+ return T_FUNCTION;
+
+ /* Look for basic types */
+ if (strcmp(c, "int") == 0)
+ return T_INT;
+ if (strcmp(c, "long") == 0)
+ return T_LONG;
+ if (strcmp(c, "short") == 0)
+ return T_SHORT;
+ if (strcmp(c, "unsigned") == 0)
+ return T_UINT;
+ if (strcmp(c, "unsigned short") == 0)
+ return T_USHORT;
+ if (strcmp(c, "unsigned long") == 0)
+ return T_ULONG;
+ if (strcmp(c, "unsigned int") == 0)
+ return T_UINT;
+ if (strcmp(c, "char") == 0)
+ return T_CHAR;
+ if (strcmp(c, "signed char") == 0)
+ return T_SCHAR;
+ if (strcmp(c, "unsigned char") == 0)
+ return T_UCHAR;
+ if (strcmp(c, "wchar_t") == 0)
+ return T_WCHAR;
+ if (strcmp(c, "float") == 0)
+ return T_FLOAT;
+ if (strcmp(c, "double") == 0)
+ return T_DOUBLE;
+ if (strcmp(c, "long double") == 0)
+ return T_LONGDOUBLE;
+ if (!cparse_cplusplus && (strcmp(c, "float _Complex") == 0))
+ return T_FLTCPLX;
+ if (!cparse_cplusplus && (strcmp(c, "double _Complex") == 0))
+ return T_DBLCPLX;
+ if (!cparse_cplusplus && (strcmp(c, "_Complex") == 0))
+ return T_COMPLEX;
+ if (strcmp(c, "void") == 0)
+ return T_VOID;
+ if (strcmp(c, "bool") == 0)
+ return T_BOOL;
+ if (strcmp(c, "long long") == 0)
+ return T_LONGLONG;
+ if (strcmp(c, "unsigned long long") == 0)
+ return T_ULONGLONG;
+ if (strncmp(c, "enum ", 5) == 0)
+ return T_INT;
+ if (strcmp(c, "auto") == 0)
+ return T_AUTO;
+
+ if (strcmp(c, "v(...)") == 0)
+ return T_VARARGS;
+ /* Hmmm. Unknown type */
+ if (SwigType_istypedef(t)) {
+ int r;
+ SwigType *nt = SwigType_typedef_resolve(t);
+ r = SwigType_type(nt);
+ Delete(nt);
+ return r;
+ }
+ return T_USER;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_alttype()
+ *
+ * Returns the alternative value type needed in C++ for class value
+ * types. When swig is not sure about using a plain $ltype value,
+ * since the class doesn't have a default constructor, or it can't be
+ * assigned, you will get back 'SwigValueWrapper<(type)>'.
+ *
+ * This is the default behavior unless:
+ *
+ * 1.- swig detects a default_constructor and 'allocate:default_constructor'
+ * attribute.
+ *
+ * 2.- swig doesn't mark 'type' as non-assignable.
+ *
+ * 3.- the user specifies that the value wrapper is not needed by using
+ * %feature("novaluewrapper") like so:
+ *
+ * %feature("novaluewrapper") MyOpaqueClass;
+ * class MyOpaqueClass;
+ *
+ * The user can also force the use of the value wrapper with
+ * %feature("valuewrapper").
+ * ----------------------------------------------------------------------------- */
+
+SwigType *SwigType_alttype(const SwigType *t, int local_tmap) {
+ Node *n;
+ SwigType *w = 0;
+ int use_wrapper = 0;
+ SwigType *td = 0;
+
+ if (!cparse_cplusplus)
+ return 0;
+
+ if (value_wrapper_mode == 0) {
+ /* old partial use of SwigValueTypes, it can fail for opaque types */
+ if (local_tmap)
+ return 0;
+ if (SwigType_isclass(t)) {
+ SwigType *ftd = SwigType_typedef_resolve_all(t);
+ td = SwigType_strip_qualifiers(ftd);
+ Delete(ftd);
+ n = Swig_symbol_clookup(td, 0);
+ if (n) {
+ if (GetFlag(n, "feature:valuewrapper")) {
+ use_wrapper = 1;
+ } else {
+ if (Checkattr(n, "nodeType", "class")
+ && (!Getattr(n, "allocate:default_constructor")
+ || (Getattr(n, "allocate:noassign")))) {
+ use_wrapper = !GetFlag(n, "feature:novaluewrapper") || GetFlag(n, "feature:nodefault");
+ }
+ }
+ } else {
+ if (SwigType_issimple(td) && SwigType_istemplate(td)) {
+ use_wrapper = 1;
+ }
+ }
+ }
+ } else {
+ /* safe use of SwigValueTypes, it can fail with some typemaps */
+ SwigType *ftd = SwigType_typedef_resolve_all(t);
+ td = SwigType_strip_qualifiers(ftd);
+ Delete(ftd);
+ if (SwigType_type(td) == T_USER) {
+ use_wrapper = 1;
+ n = Swig_symbol_clookup(td, 0);
+ if (n) {
+ if ((Checkattr(n, "nodeType", "class")
+ && !Getattr(n, "allocate:noassign")
+ && (Getattr(n, "allocate:default_constructor")))
+ || (GetFlag(n, "feature:novaluewrapper"))) {
+ use_wrapper = GetFlag(n, "feature:valuewrapper");
+ }
+ }
+ }
+ }
+
+ if (use_wrapper) {
+ w = NewStringf("SwigValueWrapper<(%s)>", td);
+ }
+ Delete(td);
+ return w;
+}
+
+/* ----------------------------------------------------------------------------
+ * * * * WARNING * * * ***
+ * ***
+ * Don't even think about modifying anything below this line unless you ***
+ * are completely on top of *EVERY* subtle aspect of the C++ type system ***
+ * and you are prepared to suffer endless hours of agony trying to ***
+ * debug the SWIG run-time type checker after you break it. ***
+ * ------------------------------------------------------------------------- */
+
+/* -----------------------------------------------------------------------------
+ * SwigType_remember()
+ *
+ * This function "remembers" a datatype that was used during wrapper code generation
+ * so that a type-checking table can be generated later on. It is up to the language
+ * modules to actually call this function--it is not done automatically.
+ *
+ * Type tracking is managed through two separate hash tables. The hash 'r_mangled'
+ * is mapping between mangled type names (used in the target language) and
+ * fully-resolved C datatypes used in the source input. The second hash 'r_resolved'
+ * is the inverse mapping that maps fully-resolved C datatypes to all of the mangled
+ * names in the scripting languages. For example, consider the following set of
+ * typedef declarations:
+ *
+ * typedef double Real;
+ * typedef double Float;
+ * typedef double Point[3];
+ *
+ * Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and
+ * 'Point' were used in an interface file and "remembered" using this function.
+ * The hash tables would look like this:
+ *
+ * r_mangled {
+ * _p_double : [ p.double, a(3).double ]
+ * _p_Real : [ p.double ]
+ * _p_Float : [ p.double ]
+ * _Point : [ a(3).double ]
+ *
+ * r_resolved {
+ * p.double : [ _p_double, _p_Real, _p_Float ]
+ * a(3).double : [ _p_double, _Point ]
+ * }
+ *
+ * Together these two hash tables can be used to determine type-equivalency between
+ * mangled typenames. To do this, we view the two hash tables as a large graph and
+ * compute the transitive closure.
+ * ----------------------------------------------------------------------------- */
+
+static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */
+static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */
+static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */
+static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */
+static Hash *r_mangleddata = 0; /* Hash mapping mangled types to client data */
+static Hash *r_remembered = 0; /* Hash of types we remembered already */
+
+static void (*r_tracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
+
+void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata) {
+ if (!r_mangleddata) {
+ r_mangleddata = NewHash();
+ }
+ Setattr(r_mangleddata, mangled, clientdata);
+}
+
+
+void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata) {
+ String *mt;
+ SwigType *lt;
+ Hash *h;
+ SwigType *fr;
+ SwigType *qr;
+ String *tkey;
+ String *cd;
+ Hash *lthash;
+
+ if (!r_mangled) {
+ r_mangled = NewHash();
+ r_resolved = NewHash();
+ r_ltype = NewHash();
+ r_clientdata = NewHash();
+ r_remembered = NewHash();
+ }
+
+ {
+ String *last;
+ last = Getattr(r_remembered, t);
+ if (last && (Cmp(last, clientdata) == 0))
+ return;
+ }
+
+ tkey = Copy(t);
+ cd = clientdata ? NewString(clientdata) : NewStringEmpty();
+ Setattr(r_remembered, tkey, cd);
+ Delete(tkey);
+ Delete(cd);
+
+ mt = SwigType_manglestr(t); /* Create mangled string */
+
+ if (r_tracefunc) {
+ (*r_tracefunc) (t, mt, (String *) clientdata);
+ }
+
+ if (SwigType_istypedef(t)) {
+ lt = Copy(t);
+ } else {
+ lt = SwigType_ltype(t);
+ }
+
+ lthash = Getattr(r_ltype, mt);
+ if (!lthash) {
+ lthash = NewHash();
+ Setattr(r_ltype, mt, lthash);
+ }
+ Setattr(lthash, lt, "1");
+ Delete(lt);
+
+ fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
+ qr = SwigType_typedef_qualified(fr);
+ Delete(fr);
+
+ /* Added to deal with possible table bug */
+ fr = SwigType_strip_qualifiers(qr);
+ Delete(qr);
+
+ /*Printf(stdout,"t = '%s'\n", t);
+ Printf(stdout,"fr= '%s'\n\n", fr); */
+
+ h = Getattr(r_mangled, mt);
+ if (!h) {
+ h = NewHash();
+ Setattr(r_mangled, mt, h);
+ Delete(h);
+ }
+ Setattr(h, fr, mt);
+
+ h = Getattr(r_resolved, fr);
+ if (!h) {
+ h = NewHash();
+ Setattr(r_resolved, fr, h);
+ Delete(h);
+ }
+ Setattr(h, mt, fr);
+
+ if (clientdata) {
+ String *cd = Getattr(r_clientdata, fr);
+ if (cd) {
+ if (Strcmp(clientdata, cd) != 0) {
+ Printf(stderr, "*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr, 0));
+ Printf(stderr, "*** '%s' != '%s'\n", clientdata, cd);
+ assert(0);
+ }
+ } else {
+ String *cstr = NewString(clientdata);
+ Setattr(r_clientdata, fr, cstr);
+ Delete(cstr);
+ }
+ }
+
+ /* If the remembered type is a reference, we also remember the pointer version.
+ This is to prevent odd problems with mixing pointers and references--especially
+ when different functions are using different typenames (via typedef). */
+
+ if (SwigType_isreference(t)) {
+ SwigType *tt = Copy(t);
+ SwigType_del_reference(tt);
+ SwigType_add_pointer(tt);
+ SwigType_remember_clientdata(tt, clientdata);
+ } else if (SwigType_isrvalue_reference(t)) {
+ SwigType *tt = Copy(t);
+ SwigType_del_rvalue_reference(tt);
+ SwigType_add_pointer(tt);
+ SwigType_remember_clientdata(tt, clientdata);
+ }
+}
+
+void SwigType_remember(const SwigType *ty) {
+ SwigType_remember_clientdata(ty, 0);
+}
+
+void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *) {
+ void (*o) (const SwigType *, String *, String *) = r_tracefunc;
+ r_tracefunc = tf;
+ return o;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_equivalent_mangle()
+ *
+ * Return a list of all of the mangled typenames that are equivalent to another
+ * mangled name. This works as follows: For each fully qualified C datatype
+ * in the r_mangled hash entry, we collect all of the mangled names from the
+ * r_resolved hash and combine them together in a list (removing duplicate entries).
+ * ----------------------------------------------------------------------------- */
+
+static List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) {
+ List *l;
+ Hash *h;
+ Hash *ch;
+ Hash *mh;
+
+ if (found) {
+ h = found;
+ } else {
+ h = NewHash();
+ }
+ if (checked) {
+ ch = checked;
+ } else {
+ ch = NewHash();
+ }
+ if (Getattr(ch, ms))
+ goto check_exit; /* Already checked this type */
+ Setattr(h, ms, "1");
+ Setattr(ch, ms, "1");
+ mh = Getattr(r_mangled, ms);
+ if (mh) {
+ Iterator ki;
+ ki = First(mh);
+ while (ki.key) {
+ Hash *rh;
+ if (Getattr(ch, ki.key)) {
+ ki = Next(ki);
+ continue;
+ }
+ Setattr(ch, ki.key, "1");
+ rh = Getattr(r_resolved, ki.key);
+ if (rh) {
+ Iterator rk;
+ rk = First(rh);
+ while (rk.key) {
+ Setattr(h, rk.key, "1");
+ SwigType_equivalent_mangle(rk.key, ch, h);
+ rk = Next(rk);
+ }
+ }
+ ki = Next(ki);
+ }
+ }
+check_exit:
+ if (!found) {
+ l = Keys(h);
+ Delete(h);
+ Delete(ch);
+ return l;
+ } else {
+ return 0;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_clientdata_collect()
+ *
+ * Returns the clientdata field for a mangled type-string.
+ * ----------------------------------------------------------------------------- */
+
+static
+String *SwigType_clientdata_collect(String *ms) {
+ Hash *mh;
+ String *clientdata = 0;
+
+ if (r_mangleddata) {
+ clientdata = Getattr(r_mangleddata, ms);
+ if (clientdata)
+ return clientdata;
+ }
+
+ mh = Getattr(r_mangled, ms);
+ if (mh) {
+ Iterator ki;
+ ki = First(mh);
+ while (ki.key) {
+ clientdata = Getattr(r_clientdata, ki.key);
+ if (clientdata)
+ break;
+ ki = Next(ki);
+ }
+ }
+ return clientdata;
+}
+
+
+
+
+/* -----------------------------------------------------------------------------
+ * SwigType_inherit()
+ *
+ * Record information about inheritance. We keep a hash table that keeps
+ * a mapping between base classes and all of the classes that are derived
+ * from them.
+ *
+ * subclass is a hash that maps base-classes to all of the classes derived from them.
+ *
+ * derived - name of derived class
+ * base - name of base class
+ * cast - additional casting code when casting from derived to base
+ * conversioncode - if set, overrides the default code in the function when casting
+ * from derived to base
+ * ----------------------------------------------------------------------------- */
+
+static Hash *subclass = 0;
+static Hash *conversions = 0;
+
+void SwigType_inherit(String *derived, String *base, String *cast, String *conversioncode) {
+ Hash *h;
+ String *dd = 0;
+ String *bb = 0;
+ if (!subclass)
+ subclass = NewHash();
+
+ /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
+
+ if (SwigType_istemplate(derived)) {
+ String *ty = SwigType_typedef_resolve_all(derived);
+ dd = SwigType_typedef_qualified(ty);
+ derived = dd;
+ Delete(ty);
+ }
+ if (SwigType_istemplate(base)) {
+ String *ty = SwigType_typedef_resolve_all(base);
+ bb = SwigType_typedef_qualified(ty);
+ base = bb;
+ Delete(ty);
+ }
+
+ /* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
+
+ h = Getattr(subclass, base);
+ if (!h) {
+ h = NewHash();
+ Setattr(subclass, base, h);
+ Delete(h);
+ }
+ if (!Getattr(h, derived)) {
+ Hash *c = NewHash();
+ if (cast)
+ Setattr(c, "cast", cast);
+ if (conversioncode)
+ Setattr(c, "convcode", conversioncode);
+ Setattr(h, derived, c);
+ Delete(c);
+ }
+
+ Delete(dd);
+ Delete(bb);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_issubtype()
+ *
+ * Determines if a t1 is a subtype of t2, ie, is t1 derived from t2
+ * ----------------------------------------------------------------------------- */
+
+int SwigType_issubtype(const SwigType *t1, const SwigType *t2) {
+ SwigType *ft1, *ft2;
+ String *b1, *b2;
+ Hash *h;
+ int r = 0;
+
+ if (!subclass)
+ return 0;
+
+ ft1 = SwigType_typedef_resolve_all(t1);
+ ft2 = SwigType_typedef_resolve_all(t2);
+ b1 = SwigType_base(ft1);
+ b2 = SwigType_base(ft2);
+
+ h = Getattr(subclass, b2);
+ if (h) {
+ if (Getattr(h, b1)) {
+ r = 1;
+ }
+ }
+ Delete(ft1);
+ Delete(ft2);
+ Delete(b1);
+ Delete(b2);
+ /* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */
+ return r;
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_inherit_equiv()
+ *
+ * Modify the type table to handle C++ inheritance
+ * ----------------------------------------------------------------------------- */
+
+static void SwigType_inherit_equiv(File *out) {
+ String *ckey;
+ String *prefix, *base;
+ String *mprefix, *mkey;
+ Hash *sub;
+ Hash *rh;
+ List *rlist;
+ List *r_resolved_sorted_keys;
+ Iterator rk, bk, ck;
+
+ if (!conversions)
+ conversions = NewHash();
+ if (!subclass)
+ subclass = NewHash();
+
+ r_resolved_sorted_keys = SortedKeys(r_resolved, Strcmp);
+ rk = First(r_resolved_sorted_keys);
+ while (rk.item) {
+ List *sub_sorted_keys;
+ /* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */
+ base = SwigType_base(rk.item);
+ /* Check to see whether the base is recorded in the subclass table */
+ sub = Getattr(subclass, base);
+ Delete(base);
+ if (!sub) {
+ rk = Next(rk);
+ continue;
+ }
+
+ /* This type has subclasses. We now need to walk through these subtypes and generate pointer conversion functions */
+
+ rh = Getattr(r_resolved, rk.item);
+ rlist = NewList();
+ for (ck = First(rh); ck.key; ck = Next(ck)) {
+ Append(rlist, ck.key);
+ }
+ /* Printf(stdout,"rk.item = '%s'\n", rk.item);
+ Printf(stdout,"rh = %p '%s'\n", rh,rh); */
+
+ sub_sorted_keys = SortedKeys(sub, Strcmp);
+ bk = First(sub_sorted_keys);
+ while (bk.item) {
+ prefix = SwigType_prefix(rk.item);
+ Append(prefix, bk.item);
+ /* Printf(stdout,"set %p = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */
+ mprefix = SwigType_manglestr(prefix);
+ Setattr(rh, mprefix, prefix);
+ mkey = SwigType_manglestr(rk.item);
+ ckey = NewStringf("%s+%s", mprefix, mkey);
+ if (!Getattr(conversions, ckey)) {
+ String *convname = NewStringf("%sTo%s", mprefix, mkey);
+ String *lkey = SwigType_lstr(rk.item, 0);
+ String *lprefix = SwigType_lstr(prefix, 0);
+ Hash *subhash = Getattr(sub, bk.item);
+ String *convcode = Getattr(subhash, "convcode");
+ if (convcode) {
+ char *newmemoryused = Strstr(convcode, "newmemory"); /* see if newmemory parameter is used in order to avoid unused parameter warnings */
+ String *fn = Copy(convcode);
+ Replaceall(fn, "$from", "x");
+ Printf(out, "static void *%s(void *x, int *%s) {", convname, newmemoryused ? "newmemory" : "SWIGUNUSEDPARM(newmemory)");
+ Printf(out, "%s", fn);
+ } else {
+ String *cast = Getattr(subhash, "cast");
+ Printf(out, "static void *%s(void *x, int *SWIGUNUSEDPARM(newmemory)) {", convname);
+ Printf(out, "\n return (void *)((%s) ", lkey);
+ if (cast)
+ Printf(out, "%s", cast);
+ Printf(out, " ((%s) x));\n", lprefix);
+ }
+ Printf(out, "}\n");
+ Setattr(conversions, ckey, convname);
+ Delete(ckey);
+ Delete(lkey);
+ Delete(lprefix);
+
+ /* This inserts conversions for typedefs */
+ {
+ Hash *r = Getattr(r_resolved, prefix);
+ if (r) {
+ Iterator rrk;
+ rrk = First(r);
+ while (rrk.key) {
+ Iterator rlk;
+ String *rkeymangle;
+
+ /* Make sure this name equivalence is not due to inheritance */
+ if (Cmp(prefix, Getattr(r, rrk.key)) == 0) {
+ rkeymangle = Copy(mkey);
+ ckey = NewStringf("%s+%s", rrk.key, rkeymangle);
+ if (!Getattr(conversions, ckey)) {
+ Setattr(conversions, ckey, convname);
+ }
+ Delete(ckey);
+ for (rlk = First(rlist); rlk.item; rlk = Next(rlk)) {
+ ckey = NewStringf("%s+%s", rrk.key, rlk.item);
+ Setattr(conversions, ckey, convname);
+ Delete(ckey);
+ }
+ Delete(rkeymangle);
+ /* This is needed to pick up other alternative names for the same type.
+ Needed to make templates work */
+ Setattr(rh, rrk.key, rrk.item);
+ }
+ rrk = Next(rrk);
+ }
+ }
+ }
+ Delete(convname);
+ }
+ Delete(prefix);
+ Delete(mprefix);
+ Delete(mkey);
+ bk = Next(bk);
+ }
+ Delete(sub_sorted_keys);
+ rk = Next(rk);
+ Delete(rlist);
+ }
+ Delete(r_resolved_sorted_keys);
+}
+
+/* -----------------------------------------------------------------------------
+ * SwigType_type_table()
+ *
+ * Generate the type-table for the type-checker.
+ * ----------------------------------------------------------------------------- */
+
+void SwigType_emit_type_table(File *f_forward, File *f_table) {
+ Iterator ki;
+ String *types, *table, *cast, *cast_init, *cast_temp;
+ Hash *imported_types;
+ List *mangled_list;
+ List *table_list = NewList();
+ int i = 0;
+
+ if (!r_mangled) {
+ r_mangled = NewHash();
+ r_resolved = NewHash();
+ }
+
+ Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n");
+
+ SwigType_inherit_equiv(f_table);
+
+ /*#define DEBUG 1*/
+#ifdef DEBUG
+ Printf(stdout, "---r_mangled---\n");
+ Swig_print(r_mangled, 2);
+
+ Printf(stdout, "---r_resolved---\n");
+ Swig_print(r_resolved, 2);
+
+ Printf(stdout, "---r_ltype---\n");
+ Swig_print(r_ltype, 2);
+
+ Printf(stdout, "---subclass---\n");
+ Swig_print(subclass, 2);
+
+ Printf(stdout, "---conversions---\n");
+ Swig_print(conversions, 2);
+
+ Printf(stdout, "---r_clientdata---\n");
+ Swig_print(r_clientdata, 2);
+
+#endif
+ table = NewStringEmpty();
+ types = NewStringEmpty();
+ cast = NewStringEmpty();
+ cast_init = NewStringEmpty();
+ imported_types = NewHash();
+
+ Printf(table, "static swig_type_info *swig_type_initial[] = {\n");
+ Printf(cast_init, "static swig_cast_info *swig_cast_initial[] = {\n");
+
+ Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n");
+
+ mangled_list = SortedKeys(r_mangled, Strcmp);
+ for (ki = First(mangled_list); ki.item; ki = Next(ki)) {
+ List *el;
+ Iterator ei;
+ String *nt;
+ String *ln;
+ String *rn;
+ const String *cd;
+ Hash *lthash;
+ Iterator ltiter;
+ Hash *nthash;
+ String *cast_temp_conv;
+ String *resolved_lstr = 0;
+ List *ntlist;
+
+ cast_temp = NewStringEmpty();
+ cast_temp_conv = NewStringEmpty();
+
+ Printv(types, "static swig_type_info _swigt_", ki.item, " = {", NIL);
+ Append(table_list, ki.item);
+ Printf(cast_temp, "static swig_cast_info _swigc_%s[] = {", ki.item);
+ i++;
+
+ cd = SwigType_clientdata_collect(ki.item);
+ if (!cd)
+ cd = "0";
+
+ lthash = Getattr(r_ltype, ki.item);
+ nt = 0;
+ nthash = NewHash();
+ ltiter = First(lthash);
+ while (ltiter.key) {
+ SwigType *lt = ltiter.key;
+ SwigType *rt = SwigType_typedef_resolve_all(lt);
+ /* we save the original type and the fully resolved version */
+ ln = SwigType_lstr(lt, 0);
+ rn = SwigType_lstr(rt, 0);
+ if (Equal(ln, rn)) {
+ Setattr(nthash, ln, "1");
+ } else {
+ Setattr(nthash, rn, "1");
+ Setattr(nthash, ln, "1");
+ }
+ if (!resolved_lstr) {
+ resolved_lstr = Copy(rn);
+ } else if (Len(rn) < Len(resolved_lstr)) {
+ Delete(resolved_lstr);
+ resolved_lstr = Copy(rn);
+ }
+ if (SwigType_istemplate(rt)) {
+ String *dt = Swig_symbol_template_deftype(rt, 0);
+ String *dn = SwigType_lstr(dt, 0);
+ if (!Equal(dn, rn) && !Equal(dn, ln)) {
+ Setattr(nthash, dn, "1");
+ }
+ Delete(dt);
+ Delete(dn);
+ }
+ Delete(rt);
+ Delete(rn);
+ Delete(ln);
+
+ ltiter = Next(ltiter);
+ }
+
+ /* now build nt */
+ ntlist = SortedKeys(nthash, Strcmp);
+ ltiter = First(ntlist);
+ nt = 0;
+ while (ltiter.item) {
+ if (!Equal(resolved_lstr, ltiter.item)) {
+ if (nt) {
+ Printf(nt, "|%s", ltiter.item);
+ } else {
+ nt = NewString(ltiter.item);
+ }
+ }
+ ltiter = Next(ltiter);
+ }
+ /* Last in list is a resolved type used by SWIG_TypePrettyName.
+ * There can be more than one resolved type and the chosen one is simply the
+ * shortest in length, arguably the most user friendly/readable. */
+ if (nt) {
+ Printf(nt, "|%s", resolved_lstr);
+ } else {
+ nt = NewString(resolved_lstr);
+ }
+ Delete(ntlist);
+ Delete(nthash);
+ Delete(resolved_lstr);
+
+ Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd);
+
+ el = SwigType_equivalent_mangle(ki.item, 0, 0);
+ SortList(el, Strcmp);
+ for (ei = First(el); ei.item; ei = Next(ei)) {
+ String *ckey;
+ String *conv;
+ ckey = NewStringf("%s+%s", ei.item, ki.item);
+ conv = Getattr(conversions, ckey);
+ if (conv) {
+ Printf(cast_temp_conv, " {&_swigt_%s, %s, 0, 0},", ei.item, conv);
+ } else {
+ Printf(cast_temp, " {&_swigt_%s, 0, 0, 0},", ei.item);
+ }
+ Delete(ckey);
+
+ if (!Getattr(r_mangled, ei.item) && !Getattr(imported_types, ei.item)) {
+ Printf(types, "static swig_type_info _swigt_%s = {\"%s\", 0, 0, 0, 0, 0};\n", ei.item, ei.item);
+ Append(table_list, ei.item);
+
+ Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s, 0, 0, 0},{0, 0, 0, 0}};\n", ei.item, ei.item);
+ i++;
+
+ Setattr(imported_types, ei.item, "1");
+ }
+ }
+ Delete(el);
+ Printf(cast, "%s%s{0, 0, 0, 0}};\n", cast_temp, cast_temp_conv);
+ Delete(cast_temp_conv);
+ Delete(cast_temp);
+ Delete(nt);
+ }
+ /* print the tables in the proper order */
+ SortList(table_list, Strcmp);
+ i = 0;
+ for (ki = First(table_list); ki.item; ki = Next(ki)) {
+ Printf(f_forward, "#define SWIGTYPE%s swig_types[%d]\n", ki.item, i++);
+ Printf(table, " &_swigt_%s,\n", ki.item);
+ Printf(cast_init, " _swigc_%s,\n", ki.item);
+ }
+ if (i == 0) {
+ /* empty arrays are not allowed by ISO C */
+ Printf(table, " NULL\n");
+ Printf(cast_init, " NULL\n");
+ }
+
+ Delete(table_list);
+
+ Delete(mangled_list);
+
+ Printf(table, "};\n");
+ Printf(cast_init, "};\n");
+ Printf(f_table, "%s\n", types);
+ Printf(f_table, "%s\n", table);
+ Printf(f_table, "%s\n", cast);
+ Printf(f_table, "%s\n", cast_init);
+ Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n");
+
+ Printf(f_forward, "static swig_type_info *swig_types[%d];\n", i + 1);
+ Printf(f_forward, "static swig_module_info swig_module = {swig_types, %d, 0, 0, 0, 0};\n", i);
+ Printf(f_forward, "#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)\n");
+ Printf(f_forward, "#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)\n");
+ Printf(f_forward, "\n/* -------- TYPES TABLE (END) -------- */\n\n");
+
+ Delete(types);
+ Delete(table);
+ Delete(cast);
+ Delete(cast_init);
+ Delete(imported_types);
+}
diff --git a/contrib/tools/swig/Source/Swig/wrapfunc.c b/contrib/tools/swig/Source/Swig/wrapfunc.c
new file mode 100644
index 00000000000..6d823724538
--- /dev/null
+++ b/contrib/tools/swig/Source/Swig/wrapfunc.c
@@ -0,0 +1,520 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at https://www.swig.org/legal.html.
+ *
+ * wrapfunc.c
+ *
+ * This file defines a object for creating wrapper functions. Primarily
+ * this is used for convenience since it allows pieces of a wrapper function
+ * to be created in a piecemeal manner.
+ * ----------------------------------------------------------------------------- */
+
+#include "swig.h"
+#include <ctype.h>
+
+static int Compact_mode = 0; /* set to 0 on default */
+static int Max_line_size = 128;
+
+/* -----------------------------------------------------------------------------
+ * NewWrapper()
+ *
+ * Create a new wrapper function object.
+ * ----------------------------------------------------------------------------- */
+
+Wrapper *NewWrapper(void) {
+ Wrapper *w;
+ w = (Wrapper *) Malloc(sizeof(Wrapper));
+ w->localh = NewHash();
+ w->locals = NewStringEmpty();
+ w->code = NewStringEmpty();
+ w->def = NewStringEmpty();
+ return w;
+}
+
+/* -----------------------------------------------------------------------------
+ * DelWrapper()
+ *
+ * Delete a wrapper function object.
+ * ----------------------------------------------------------------------------- */
+
+void DelWrapper(Wrapper *w) {
+ Delete(w->localh);
+ Delete(w->locals);
+ Delete(w->code);
+ Delete(w->def);
+ Free(w);
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_compact_print_mode_set()
+ *
+ * Set compact_mode.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_compact_print_mode_set(int flag) {
+ Compact_mode = flag;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_pretty_print()
+ *
+ * Formats a wrapper function and fixes up the indentation.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_pretty_print(String *str, File *f) {
+ String *ts;
+ int level = 0;
+ int c, i;
+ int empty = 1;
+ int indent = 2;
+ int plevel = 0;
+ int label = 0;
+
+ ts = NewStringEmpty();
+ Seek(str, 0, SEEK_SET);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\"') {
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\"')
+ break;
+ }
+ empty = 0;
+ } else if (c == '\'') {
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\'')
+ break;
+ }
+ empty = 0;
+ } else if (c == ':') {
+ Putc(c, ts);
+ if ((c = Getc(str)) == '\n') {
+ if (!empty && !strchr(Char(ts), '?'))
+ label = 1;
+ }
+ Ungetc(c, str);
+ } else if (c == '(') {
+ Putc(c, ts);
+ plevel += indent;
+ empty = 0;
+ } else if (c == ')') {
+ Putc(c, ts);
+ plevel -= indent;
+ empty = 0;
+ } else if (c == '{') {
+ Putc(c, ts);
+ Putc('\n', ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', f);
+ Printf(f, "%s", ts);
+ Clear(ts);
+ level += indent;
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ empty = 0;
+ } else if (c == '}') {
+ if (!empty) {
+ Putc('\n', ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', f);
+ Printf(f, "%s", ts);
+ Clear(ts);
+ }
+ level -= indent;
+ Putc(c, ts);
+ empty = 0;
+ } else if (c == '\n') {
+ Putc(c, ts);
+ empty = 0;
+ if (!empty) {
+ int slevel = level;
+ if (label && (slevel >= indent))
+ slevel -= indent;
+ if ((Char(ts))[0] != '#') {
+ for (i = 0; i < slevel; i++)
+ Putc(' ', f);
+ }
+ Printf(f, "%s", ts);
+ for (i = 0; i < plevel; i++)
+ Putc(' ', f);
+ }
+ Clear(ts);
+ label = 0;
+ empty = 1;
+ } else if (c == '/') {
+ empty = 0;
+ Putc(c, ts);
+ c = Getc(str);
+ if (c != EOF) {
+ Putc(c, ts);
+ if (c == '/') { /* C++ comment */
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, str);
+ break;
+ }
+ Putc(c, ts);
+ }
+ } else if (c == '*') { /* C comment */
+ int endstar = 0;
+ while ((c = Getc(str)) != EOF) {
+ if (endstar && c == '/') { /* end of C comment */
+ Putc(c, ts);
+ break;
+ }
+ endstar = (c == '*');
+ Putc(c, ts);
+ if (c == '\n') { /* multi-line C comment. Could be improved slightly. */
+ for (i = 0; i < level; i++)
+ Putc(' ', ts);
+ }
+ }
+ }
+ }
+ } else {
+ if (!empty || !isspace(c)) {
+ Putc(c, ts);
+ empty = 0;
+ }
+ }
+ }
+ if (!empty)
+ Printf(f, "%s", ts);
+ Delete(ts);
+ Printf(f, "\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_compact_print()
+ *
+ * Formats a wrapper function and fixes up the indentation.
+ * Print out in compact format, with Compact enabled.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_compact_print(String *str, File *f) {
+ String *ts, *tf; /*temp string & temp file */
+ int level = 0;
+ int c, i;
+ int empty = 1;
+ int indent = 2;
+
+ ts = NewStringEmpty();
+ tf = NewStringEmpty();
+ Seek(str, 0, SEEK_SET);
+
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\"') { /* string 1 */
+ empty = 0;
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\"')
+ break;
+ }
+ } else if (c == '\'') { /* string 2 */
+ empty = 0;
+ Putc(c, ts);
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\\') {
+ Putc(c, ts);
+ c = Getc(str);
+ }
+ Putc(c, ts);
+ if (c == '\'')
+ break;
+ }
+ } else if (c == '{') { /* start of {...} */
+ empty = 0;
+ Putc(c, ts);
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Clear(ts);
+ level += indent;
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c)) {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ } else if (c == '}') { /* end of {...} */
+ empty = 0;
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Putc(c, tf);
+ Clear(ts);
+ level -= indent;
+ } else if (c == '\n') { /* line end */
+ while ((c = Getc(str)) != EOF) {
+ if (!isspace(c))
+ break;
+ }
+ if (c == '#') {
+ Putc('\n', ts);
+ } else if (c == '}') {
+ Putc(' ', ts);
+ } else if ((c != EOF) || (Len(ts) != 0)) {
+ if (Len(tf) == 0) {
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ } else if ((Len(tf) + Len(ts)) < Max_line_size) {
+ Putc(' ', tf);
+ } else {
+ Putc('\n', tf);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ }
+ Append(tf, ts);
+ Clear(ts);
+ }
+ Ungetc(c, str);
+
+ empty = 1;
+ } else if (c == '/') { /* comment */
+ empty = 0;
+ c = Getc(str);
+ if (c != EOF) {
+ if (c == '/') { /* C++ comment */
+ while ((c = Getc(str)) != EOF) {
+ if (c == '\n') {
+ Ungetc(c, str);
+ break;
+ }
+ }
+ } else if (c == '*') { /* C comment */
+ int endstar = 0;
+ while ((c = Getc(str)) != EOF) {
+ if (endstar && c == '/') { /* end of C comment */
+ break;
+ }
+ endstar = (c == '*');
+ }
+ } else {
+ Putc('/', ts);
+ Putc(c, ts);
+ }
+ }
+ } else if (c == '#') { /* Preprocessor line */
+ Putc('#', ts);
+ while ((c = Getc(str)) != EOF) {
+ Putc(c, ts);
+ if (c == '\\') { /* Continued line of the same PP */
+ c = Getc(str);
+ if (c == '\n')
+ Putc(c, ts);
+ else
+ Ungetc(c, str);
+ } else if (c == '\n')
+ break;
+ }
+ if (!empty) {
+ Append(tf, "\n");
+ }
+ Append(tf, ts);
+ Printf(f, "%s", tf);
+ Clear(tf);
+ Clear(ts);
+ for (i = 0; i < level; i++)
+ Putc(' ', tf);
+ empty = 1;
+ } else {
+ if (!empty || !isspace(c)) {
+ Putc(c, ts);
+ empty = 0;
+ }
+ }
+ }
+ if (!empty) {
+ Append(tf, ts);
+ }
+ if (Len(tf) != 0)
+ Printf(f, "%s", tf);
+ Delete(ts);
+ Delete(tf);
+ Printf(f, "\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_print()
+ *
+ * Print out a wrapper function. Does pretty or compact printing as well.
+ * ----------------------------------------------------------------------------- */
+
+void Wrapper_print(Wrapper *w, File *f) {
+ String *str;
+
+ str = NewStringEmpty();
+ Printf(str, "%s\n", w->def);
+ Printf(str, "%s\n", w->locals);
+ Printf(str, "%s\n", w->code);
+ if (Compact_mode == 1)
+ Wrapper_compact_print(str, f);
+ else
+ Wrapper_pretty_print(str, f);
+
+ Delete(str);
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_add_local()
+ *
+ * Adds a new local variable declaration to a function. Returns -1 if already
+ * present (which may or may not be okay to the caller).
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_add_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ /* See if the local has already been declared */
+ if (Getattr(w->localh, name)) {
+ return -1;
+ }
+ Setattr(w->localh, name, decl);
+ Printf(w->locals, "%s;\n", decl);
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_add_localv()
+ *
+ * Same as add_local(), but allows a NULL terminated list of strings to be
+ * used as a replacement for decl. This saves the caller the trouble of having
+ * to manually construct the 'decl' string before calling.
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_add_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
+ va_list ap;
+ int ret;
+ String *decl;
+ DOH *obj;
+ decl = NewStringEmpty();
+ va_start(ap, name);
+
+ obj = va_arg(ap, void *);
+ while (obj) {
+ Append(decl, obj);
+ Putc(' ', decl);
+ obj = va_arg(ap, void *);
+ }
+ va_end(ap);
+
+ ret = Wrapper_add_local(w, name, decl);
+ Delete(decl);
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_check_local()
+ *
+ * Check to see if a local name has already been declared
+ * ----------------------------------------------------------------------------- */
+
+int Wrapper_check_local(Wrapper *w, const_String_or_char_ptr name) {
+ if (Getattr(w->localh, name)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_new_local()
+ *
+ * Adds a new local variable with a guarantee that a unique local name will be
+ * used. Returns the name that was actually selected.
+ * ----------------------------------------------------------------------------- */
+
+char *Wrapper_new_local(Wrapper *w, const_String_or_char_ptr name, const_String_or_char_ptr decl) {
+ int i;
+ String *nname = NewString(name);
+ String *ndecl = NewString(decl);
+ char *ret;
+
+ i = 0;
+
+ while (Wrapper_check_local(w, nname)) {
+ Clear(nname);
+ Printf(nname, "%s%d", name, i);
+ i++;
+ }
+ Replace(ndecl, name, nname, DOH_REPLACE_ID);
+ Setattr(w->localh, nname, ndecl);
+ Printf(w->locals, "%s;\n", ndecl);
+ ret = Char(nname);
+ Delete(nname);
+ Delete(ndecl);
+ return ret; /* Note: nname should still exists in the w->localh hash */
+}
+
+
+/* -----------------------------------------------------------------------------
+ * Wrapper_new_localv()
+ *
+ * Same as add_local(), but allows a NULL terminated list of strings to be
+ * used as a replacement for decl. This saves the caller the trouble of having
+ * to manually construct the 'decl' string before calling.
+ * ----------------------------------------------------------------------------- */
+
+char *Wrapper_new_localv(Wrapper *w, const_String_or_char_ptr name, ...) {
+ va_list ap;
+ char *ret;
+ String *decl;
+ DOH *obj;
+ decl = NewStringEmpty();
+ va_start(ap, name);
+
+ obj = va_arg(ap, void *);
+ while (obj) {
+ Append(decl, obj);
+ Putc(' ', decl);
+ obj = va_arg(ap, void *);
+ }
+ va_end(ap);
+
+ ret = Wrapper_new_local(w, name, decl);
+ Delete(decl);
+ return ret;
+}
diff --git a/contrib/tools/swig/TODO b/contrib/tools/swig/TODO
new file mode 100644
index 00000000000..2182ef86a1b
--- /dev/null
+++ b/contrib/tools/swig/TODO
@@ -0,0 +1,226 @@
+SWIG TO-DO
+
+-----------------------------------------------------------------------------
+
+**** = High Priority
+*** = Implement if possible.
+** = Will implement if time.
+* = Implement if bored (or deemed necessary).
+
+defer = Implement in next version
+
+CORE:
+
+**** Add support for nested classes. The type system should be
+defer ready to go. The primary obstacle lies in the target language
+ modules (which were never programmed with nested classes in
+ mind). There are also issues with nested C structures. For
+ example:
+
+ struct Foo {
+ struct {
+ int x,y;
+ } z;
+ };
+
+ This is one of the last remaining "hard" problems in the SWIG
+ core, but it is important that we solve it.
+
+*** Implement $fail special variable substitution in wrappers. Used
+ to properly transfer control out of a wrapper function while
+ reclaiming resources.
+
+ Note: Implemented in languages that uses the UTL via the
+ 'SWIG_fail' macro.
+
+*** Rewrite declaration annotation to better unify %rename and related
+ directives. Add a selector mechanism that allows specific parse tree
+ nodes to be identified. For example:
+
+ %feature("foo", nodetype="class") Foo { ... some code ... };
+
+ Consider use of wildcards. Namespace/nested scope support in
+ %feature is currently weak. It works, but is fragile. Consider
+ an implementation that is better integrated with symbol table
+ management. Continue to consolidate SWIG directives to %feature.
+
+ Note: Initial implementation in the %rename directive.
+
+*** Add more intelligent information related to object ownership.
+ SWIG should be able to automatically strip ownership from
+ objects when they are assigned to pointer variables and structure
+ members as well as stored in a container (i.e., an array of pointers).
+
+ [ Partially finished for Ruby/Perl/Tcl/Python. ]
+
+** Restoration of the documentation system.
+ [ Partially done for Python. ]
+
+
+** Restoration of Objective-C support.
+
+** Unification of symbol tables and type system scopes. In a sense
+ they capture the same information so it is not necessary to have
+ both. The existence of two symbol management systems is mostly
+ historical.
+
+Build
+-----
+
+Library
+-------
+
+**** Add more support for the C++ standard library. std::complex and other
+ core datatypes. Refine support for STL vector. Add more STL objects.
+
+ [ Partially finished for Python. ]
+
+**** Continue to expand the set of recognized typemaps.
+
+Windows
+-------
+
+All language modules
+--------------------
+
+Python
+------
+
+*** Ability to wrap certain classes as Python built-in types.
+
+Perl
+----
+
+**** Rewrite runtime pointer type checking to better integrate
+ shadow classes. Creation of shadow classes should be done
+ in C instead of Perl. This will fix a number of problems
+ related to typemaps and reduce the amount of Perl wrapper code.
+
+**** Create tests for existing support for operator overloading
+
+Tcl
+---
+
+Ruby
+----
+
+**** The "Resource Management in Proxies" section of the "SWIG and C++"
+ chapter discusses how proxies' ownership of their associated C++
+ object can change, and the use of the special disown() and
+ acquire() methods to change this ownership status. Need to
+ address this for Ruby as well.
+
+*** Add support for keyword arguments (by collecting them in a hash?).
+
+Java
+----
+
+
+C#
+--
+
+PHP
+---
+
+**** Look at moving to using the UTL.
+
+** When returning wrapped objects via alternate constructors if that
+ pointer value already exists "out there" as a resource we should
+ use the same resource, we can't have multiple ref-counted resources
+ mapping to the same object in case it gets twice destroyed.
+
+** Look at pass by point and passby ref,
+ Make sometype** to be auto allocated
+ Make sometype& and sometype* to be autoallocated IF THEY ARE NOT
+ ALREADY swigtype wrapped.
+
+* Review to see what else is missing!
+
+Guile
+-----
+
+** Maybe rename slot setters from CLASS-SLOT-set to CLASS-SLOT-set!
+ to match Scheme convention for naming of mutators.
+
+** Support keyword args.
+
+** Director Support!
+
+** Cleaner handling of multiple values.
+ Use a typemap keyword argument "numoutputs" of "out" and
+ "argout" to indicate how many values are returned.
+
+** Make SWIG's types first-class by using a separate smob type for
+ SWIG type descriptors; enable reflection on types. (Maybe
+ GOOPS metaclasses?)
+
+** Provide a clean way to construct type predicates.
+
+** In GOOPS mode, maybe make overloaded functions methods.
+
+** Increase the safety of destructor functions. John Lenz suggests:
+
+ I think the best way of doing this would be to use %feature to mark
+ which classes allow for "normal" <swig> smobs to be deleted explicitly.
+
+ We separate pointers into two classes, those that can be deleted from
+ scheme and those that can't. The pointers that can be deleted use the
+ <collectable-swig> smob and those that can not be deleted use the
+ <swig> smob. A user can specify which type of each object they want
+ with %newobject and the CONSUMED typemap.
+
+ By default, the exported destructor will only accept <collectable-swig>
+ smobs, because by definition, collectable-swig smobs are those that can
+ be deleted from scheme. This allows for the user to implement
+ protection. In the interface file, the user has complete control over
+ which objects can and can not be deleted, and can guarantee that
+ objects that should not be deleted can not be deleted, and that objects
+ that should eventually be deleted will be garbage collected.
+
+ This protection can then be overridden with a %feature directive,
+ something like
+
+ %feature("guile_allow_destroy_all","1") Foo::~Foo;
+
+ I don't know what word we want to use, guile_allow_destroy_all is kinda
+ bad. This feature would then allow for a <swig Foo *> smob to be
+ deleted by passing it to the destructor. This would allow users to
+ maintain the protection on other classes, only manually overriding the
+ protection on the classes that need it.
+
+
+Mzscheme
+--------
+
+** Port list-vector.i and pointer-in-out.i from Guile.
+
+** Add shadow class support for the Swindle system.
+
+Ocaml
+-----
+** I've been working with my camlp4 module and type information
+ from the compiler. When I'm done, the user will have access
+ to type inference when writing code, when the inference is
+ unambiguous. This allows the user to write x = _foo 1.0
+ instead of x = get_float (_foo (C_float 1.0)). It's not as
+ easy as it sounds, because O'caml doesn't keep type information
+ at run time, and doesn't really have a mechanism for doing what
+ I need. However, it's possible to write a preprocessor that
+ inserts correct type info at compile time.
+
+ That having been said, the program must compile for type info
+ to be available, so I need to attend to a lot of details; The
+ program must compile both with and without type augmentation.
+
+Xml
+---
+
+
+Documentation
+-------------
+
+**** Extending SWIG (and internals).
+
+*** Perl, Python, Tcl modules.
+
+*** add section for Perl module support for operator overloading
diff --git a/contrib/tools/swig/patches/fix-unused-parameter.patch b/contrib/tools/swig/patches/fix-unused-parameter.patch
new file mode 100644
index 00000000000..9bff7c57c79
--- /dev/null
+++ b/contrib/tools/swig/patches/fix-unused-parameter.patch
@@ -0,0 +1,33 @@
+--- contrib/tools/swig/Source/Modules/python.cxx (index)
++++ contrib/tools/swig/Source/Modules/python.cxx (working tree)
+@@ -2981,6 +2981,8 @@ public:
+ } else {
+ int is_tp_call = Equal(Getattr(n, "feature:python:slot"), "tp_call");
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, PyObject *args", builtin_kwargs, ") {", NIL);
++ /* Avoid warning if the self parameter is not used. */
++ Append(f->def, "(void)self;\n");
+ if (builtin_ctor)
+ Printf(parse_args, "if (!SWIG_Python_CheckNoKeywords(kwargs, \"%s\")) SWIG_fail;\n", iname);
+ if (onearg && !builtin_ctor && !is_tp_call) {
+--- contrib/tools/swig/Source/Modules/python.cxx (index)
++++ contrib/tools/swig/Source/Modules/python.cxx (working tree)
+@@ -2977,6 +2977,8 @@ public:
+ } else {
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {", NIL);
+ }
++ /* Avoid warning if the self parameter is not used. */
++ Append(f->def, "(void)self;\n");
+ Printf(parse_args, "if ((nobjs < %d) || (nobjs > %d)) SWIG_fail;\n", num_required, num_arguments);
+ } else {
+ int is_tp_call = Equal(Getattr(n, "feature:python:slot"), "tp_call");
+--- contrib/tools/swig/Source/Modules/python.cxx (index)
++++ contrib/tools/swig/Source/Modules/python.cxx (working tree)
+@@ -2808,6 +2808,8 @@ public:
+ varargs = 0;
+ }
+ Printv(f->def, linkage, wrap_return, wname, "(PyObject *self, PyObject *args, PyObject *kwargs) {", NIL);
++ /* Avoid warning if the self parameter is not used. */
++ Append(f->def, "(void)self;\n");
+ }
+
+ if (builtin) {
diff --git a/contrib/tools/swig/patches/gostring.patch b/contrib/tools/swig/patches/gostring.patch
new file mode 100644
index 00000000000..388385c8c83
--- /dev/null
+++ b/contrib/tools/swig/patches/gostring.patch
@@ -0,0 +1,18 @@
+Fix go vet warning "possible misuse of unsafe.Pointer".
+--- a/Lib/go/gostring.swg
++++ b/Lib/go/gostring.swg
+@@ -19,11 +19,11 @@
+ // Go code to convert a string allocated in C++ memory to one
+ // allocated in Go memory.
+ %fragment("CopyString", "go_runtime") %{
+-type swig_gostring struct { p uintptr; n int }
++type swig_gostring struct { p unsafe.Pointer; n int }
+ func swigCopyString(s string) string {
+ p := *(*swig_gostring)(unsafe.Pointer(&s))
+- r := string((*[0x7fffffff]byte)(unsafe.Pointer(p.p))[:p.n])
+- Swig_free(p.p)
++ r := string((*[0x7fffffff]byte)(p.p)[:p.n])
++ Swig_free(uintptr(p.p))
+ return r
+ }
+ %}
diff --git a/contrib/tools/swig/patches/issue-2881.patch b/contrib/tools/swig/patches/issue-2881.patch
new file mode 100644
index 00000000000..aa525ee4347
--- /dev/null
+++ b/contrib/tools/swig/patches/issue-2881.patch
@@ -0,0 +1,611 @@
+From 49a7d2b0c6aed00bd07a9a28569020d560c2658c Mon Sep 17 00:00:00 2001
+From: William S Fulton <[email protected]>
+Date: Sat, 10 May 2025 13:47:35 +0100
+Subject: [PATCH 1/5] Python DeprecationWarning fixes
+
+DeprecationWarning fixes when using 'python -Walways' or if using one of the types being warned about:
+
+ DeprecationWarning: builtin type SwigPyPacked has no __module__ attribute
+ DeprecationWarning: builtin type SwigPyObject has no __module__ attribute
+ DeprecationWarning: builtin type swigvarlink has no __module__ attribute
+
+The warning was present if code was generated without using -builtin in 4.3.x.
+The warning was only present if using the Python limited API in 4.2.1 and earlier.
+
+These 3 types were not in any module at all. Now they are in the swig runtime module.
+Docs to follow.
+
+Issue #2881
+Issue #3061
+Issue #3160
+---
+ CHANGES.current | 11 +++++++++++
+ Lib/python/pyhead.swg | 4 +++-
+ Lib/python/pyrun.swg | 22 +++++++++++-----------
+ 3 files changed, 25 insertions(+), 12 deletions(-)
+
+--- a/Lib/python/pyhead.swg
++++ b/Lib/python/pyhead.swg
+@@ -60,6 +60,8 @@ SWIG_Python_str_FromChar(const char *c)
+ #endif
+ }
+
++#define SWIG_RUNTIME_MODULE "swig_runtime_data" SWIG_RUNTIME_VERSION
++
+ /* SWIGPY_USE_CAPSULE is no longer used within SWIG itself, but some user interface files check for it. */
+ # define SWIGPY_USE_CAPSULE
+ #ifdef SWIGPYTHON_BUILTIN
+@@ -67,7 +69,7 @@ SWIG_Python_str_FromChar(const char *c)
+ #else
+ # define SWIGPY_CAPSULE_ATTR_NAME "type_pointer_capsule" SWIG_TYPE_TABLE_NAME
+ #endif
+-# define SWIGPY_CAPSULE_NAME ("swig_runtime_data" SWIG_RUNTIME_VERSION "." SWIGPY_CAPSULE_ATTR_NAME)
++#define SWIGPY_CAPSULE_NAME SWIG_RUNTIME_MODULE "." SWIGPY_CAPSULE_ATTR_NAME
+
+ #if PY_VERSION_HEX < 0x03020000
+ #define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type)
+--- a/Lib/python/pyrun.swg
++++ b/Lib/python/pyrun.swg
+@@ -353,7 +353,7 @@ swig_varlink_type(void) {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ #endif
+- "swigvarlink", /* tp_name */
++ SWIG_RUNTIME_MODULE ".swigvarlink", /* tp_name */
+ sizeof(swig_varlinkobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) swig_varlink_dealloc, /* tp_dealloc */
+@@ -424,7 +424,7 @@ swig_varlink_type(void) {
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+- "swigvarlink",
++ SWIG_RUNTIME_MODULE ".swigvarlink",
+ sizeof(swig_varlinkobject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+@@ -750,7 +750,7 @@ SwigPyObject_Check(PyObject *op) {
+ #ifdef SWIGPYTHON_BUILTIN
+ if (PyType_IsSubtype(op_type, target_tp))
+ return 1;
+- return (strcmp(op_type->tp_name, "SwigPyObject") == 0);
++ return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyObject") == 0);
+ #else
+ # ifdef Py_LIMITED_API
+ int cmp;
+@@ -766,7 +766,7 @@ SwigPyObject_Check(PyObject *op) {
+ SWIG_Py_DECREF(tp_name);
+ return cmp == 0;
+ # else
+- return (strcmp(op_type->tp_name, "SwigPyObject") == 0);
++ return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyObject") == 0);
+ # endif
+ #endif
+ }
+@@ -966,7 +966,7 @@ SwigPyObject_TypeOnce(void) {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ #endif
+- "SwigPyObject", /* tp_name */
++ SWIG_RUNTIME_MODULE ".SwigPyObject", /* tp_name */
+ sizeof(SwigPyObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SwigPyObject_dealloc, /* tp_dealloc */
+@@ -1061,7 +1061,7 @@ SwigPyObject_TypeOnce(void) {
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+- "SwigPyObject",
++ SWIG_RUNTIME_MODULE ".SwigPyObject",
+ sizeof(SwigPyObject),
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+@@ -1160,7 +1160,7 @@ SwigPyPacked_Check(PyObject *op) {
+ SWIG_Py_DECREF(tp_name);
+ return cmp == 0;
+ #else
+- return (strcmp(op_type->tp_name, "SwigPyPacked") == 0);
++ return (strcmp(op_type->tp_name, SWIG_RUNTIME_MODULE ".SwigPyPacked") == 0);
+ #endif
+ }
+
+@@ -1188,7 +1188,7 @@ SwigPyPacked_TypeOnce(void) {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ #endif
+- "SwigPyPacked", /* tp_name */
++ SWIG_RUNTIME_MODULE ".SwigPyPacked", /* tp_name */
+ sizeof(SwigPyPacked), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SwigPyPacked_dealloc, /* tp_dealloc */
+@@ -1281,7 +1281,7 @@ SwigPyPacked_TypeOnce(void) {
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+- "SwigPyPacked",
++ SWIG_RUNTIME_MODULE ".SwigPyPacked",
+ sizeof(SwigPyPacked),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+@@ -1846,10 +1846,10 @@ SWIGRUNTIME void
+ SWIG_Python_SetModule(swig_module_info *swig_module) {
+ #if PY_VERSION_HEX >= 0x03000000
+ /* Add a dummy module object into sys.modules */
+- PyObject *module = PyImport_AddModule("swig_runtime_data" SWIG_RUNTIME_VERSION);
++ PyObject *module = PyImport_AddModule(SWIG_RUNTIME_MODULE);
+ #else
+ static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+- PyObject *module = Py_InitModule("swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table);
++ PyObject *module = Py_InitModule(SWIG_RUNTIME_MODULE, swig_empty_runtime_method_table);
+ #endif
+ PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+ if (pointer && module) {
+
+From 7ecbb7103dec48bb316baa9ccd71ba7888de7c54 Mon Sep 17 00:00:00 2001
+From: William S Fulton <[email protected]>
+Date: Sun, 11 May 2025 16:02:43 +0100
+Subject: [PATCH 2/5] Add SwigPyObject, SwigPyPacked, swigvarlink to the swig
+ runtime module
+
+Also add SWIG_REFCNT_DEBUG for debugging reference counts when the main
+module is destroyed - there's some work to be done here on reference
+counts!
+---
+ Lib/python/pyinit.swg | 1 +
+ Lib/python/pyrun.swg | 91 +++++++++++++++++++++++++++++++++----------
+ 2 files changed, 71 insertions(+), 21 deletions(-)
+
+--- a/Lib/python/pyinit.swg
++++ b/Lib/python/pyinit.swg
+@@ -261,6 +261,7 @@ SWIG_init(void) {
+ (void)globals;
+
+ /* Create singletons now to avoid potential deadlocks with multi-threaded usage after module initialization */
++ SWIG_runtime_data_module();
+ SWIG_This();
+ SWIG_Python_TypeCache();
+ SwigPyPacked_type();
+--- a/Lib/python/pyrun.swg
++++ b/Lib/python/pyrun.swg
+@@ -114,8 +114,25 @@ SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {
+
+ #endif
+
+-/* Append a value to the result obj */
++/* SWIG runtime data Python module */
++static PyObject *Swig_runtime_data_module_global = NULL;
++
++/* Create/obtain the single swig_runtime_data module which is used across different SWIG generated modules */
++SWIGINTERN PyObject *
++SWIG_runtime_data_module() {
++ if (!Swig_runtime_data_module_global) {
++#if PY_VERSION_HEX >= 0x03000000
++ Swig_runtime_data_module_global = PyImport_AddModule(SWIG_RUNTIME_MODULE);
++#else
++ static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
++ Swig_runtime_data_module_global = Py_InitModule(SWIG_RUNTIME_MODULE, swig_empty_runtime_method_table);
++#endif
++ SWIG_Py_XINCREF(Swig_runtime_data_module_global);
++ }
++ return Swig_runtime_data_module_global;
++}
+
++/* Append a value to the result obj */
+ SWIGINTERN PyObject*
+ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj, int is_void) {
+ if (!result) {
+@@ -341,7 +358,7 @@ swig_varlink_setattr(PyObject *o, char *n, PyObject *p) {
+
+ SWIGINTERN PyTypeObject*
+ swig_varlink_type(void) {
+- static char varlink__doc__[] = "Swig var link object";
++ static char varlink__doc__[] = "Swig variable link object";
+ #ifndef SWIG_HEAPTYPES
+ static PyTypeObject varlink_type;
+ static int type_init = 0;
+@@ -407,10 +424,13 @@ swig_varlink_type(void) {
+ 0 /* tp_next */
+ #endif
+ };
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ varlink_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&varlink_type) < 0)
+ return NULL;
++ if (PyModule_AddObject(runtime_data_module, "swigvarlink", (PyObject *)&varlink_type) == 0)
++ SWIG_Py_INCREF((PyObject *)&varlink_type);
+ }
+ return &varlink_type;
+ #else
+@@ -430,7 +450,11 @@ swig_varlink_type(void) {
+ Py_TPFLAGS_DEFAULT,
+ slots
+ };
+- return (PyTypeObject *)PyType_FromSpec(&spec);
++ PyObject *pytype = PyType_FromSpec(&spec);
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
++ if (pytype && PyModule_AddObject(runtime_data_module, "swigvarlink", pytype) == 0)
++ SWIG_Py_INCREF(pytype);
++ return (PyTypeObject *)pytype;
+ #endif
+ }
+
+@@ -910,7 +934,7 @@ swigobject_methods[] = {
+
+ SWIGRUNTIME PyTypeObject*
+ SwigPyObject_TypeOnce(void) {
+- static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
++ static char swigobject_doc[] = "Swig object holding a C/C++ pointer";
+ #ifndef SWIG_HEAPTYPES
+ static PyNumberMethods SwigPyObject_as_number = {
+ (binaryfunc)0, /*nb_add*/
+@@ -1043,10 +1067,13 @@ SwigPyObject_TypeOnce(void) {
+ 0 /* tp_next */
+ #endif
+ };
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ swigpyobject_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&swigpyobject_type) != 0)
+ return NULL;
++ if (PyModule_AddObject(runtime_data_module, "SwigPyObject", (PyObject *)&swigpyobject_type) == 0)
++ SWIG_Py_INCREF((PyObject *)&swigpyobject_type);
+ }
+ return &swigpyobject_type;
+ #else
+@@ -1067,7 +1094,11 @@ SwigPyObject_TypeOnce(void) {
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ slots
+ };
+- return (PyTypeObject *)PyType_FromSpec(&spec);
++ PyObject *pytype = PyType_FromSpec(&spec);
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
++ if (pytype && PyModule_AddObject(runtime_data_module, "SwigPyObject", pytype) == 0)
++ SWIG_Py_INCREF(pytype);
++ return (PyTypeObject *)pytype;
+ #endif
+ }
+
+@@ -1150,7 +1181,7 @@ SwigPyPacked_Check(PyObject *op) {
+ PyObject *tp_name;
+ #endif
+ PyTypeObject* op_type = Py_TYPE(op);
+- if (op_type == SwigPyPacked_TypeOnce())
++ if (op_type == SwigPyPacked_type())
+ return 1;
+ #ifdef Py_LIMITED_API
+ tp_name = PyObject_GetAttrString((PyObject *)op_type, "__name__");
+@@ -1176,7 +1207,7 @@ SwigPyPacked_dealloc(PyObject *v)
+
+ SWIGRUNTIME PyTypeObject*
+ SwigPyPacked_TypeOnce(void) {
+- static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
++ static char swigpacked_doc[] = "Swig object holding a C/C++ function pointer";
+ #ifndef SWIG_HEAPTYPES
+ static PyTypeObject swigpypacked_type;
+ static int type_init = 0;
+@@ -1265,10 +1296,13 @@ SwigPyPacked_TypeOnce(void) {
+ 0 /* tp_next */
+ #endif
+ };
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ swigpypacked_type = tmp;
+ type_init = 1;
+ if (PyType_Ready(&swigpypacked_type) != 0)
+ return NULL;
++ if (PyModule_AddObject(runtime_data_module, "SwigPyPacked", (PyObject *)&swigpypacked_type) == 0)
++ SWIG_Py_INCREF((PyObject *)&swigpypacked_type);
+ }
+ return &swigpypacked_type;
+ #else
+@@ -1287,7 +1321,11 @@ SwigPyPacked_TypeOnce(void) {
+ Py_TPFLAGS_DEFAULT,
+ slots
+ };
+- return (PyTypeObject *)PyType_FromSpec(&spec);
++ PyObject *pytype = PyType_FromSpec(&spec);
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
++ if (pytype && PyModule_AddObject(runtime_data_module, "SwigPyPacked", pytype) == 0)
++ SWIG_Py_INCREF(pytype);
++ return (PyTypeObject *)pytype;
+ #endif
+ }
+
+@@ -1815,6 +1853,12 @@ SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) {
+ }
+
+
++#if defined(SWIG_REFCNT_DEBUG)
++#define SWIG_PYOBJ_REFCNT(OBJ) fprintf(stdout, "" #OBJ " count %ld\n", (OBJ ? Py_REFCNT(OBJ) : 0))
++#else
++#define SWIG_PYOBJ_REFCNT(OBJ)
++#endif
++
+ static int interpreter_counter = 0; /* how many (sub-)interpreters are using swig_module's types */
+
+ SWIGRUNTIME void
+@@ -1825,7 +1869,7 @@ SWIG_Python_DestroyModule(PyObject *obj)
+ size_t i;
+ if (--interpreter_counter != 0) /* another sub-interpreter may still be using the swig_module's types */
+ return;
+- for (i =0; i < swig_module->size; ++i) {
++ for (i = 0; i < swig_module->size; ++i) {
+ swig_type_info *ty = types[i];
+ if (ty->owndata) {
+ SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
+@@ -1833,27 +1877,32 @@ SWIG_Python_DestroyModule(PyObject *obj)
+ if (data) SwigPyClientData_Del(data);
+ }
+ }
+- SWIG_Py_DECREF(SWIG_This());
++ SWIG_Py_XDECREF(Swig_This_global);
++ SWIG_PYOBJ_REFCNT(Swig_This_global);
+ Swig_This_global = NULL;
+- SWIG_Py_DECREF(SWIG_globals());
++
++ SWIG_Py_XDECREF(Swig_Globals_global);
++ SWIG_PYOBJ_REFCNT(Swig_Globals_global);
+ Swig_Globals_global = NULL;
+- SWIG_Py_DECREF(SWIG_Python_TypeCache());
++
++ SWIG_Py_XDECREF(Swig_TypeCache_global);
++ SWIG_PYOBJ_REFCNT(Swig_TypeCache_global);
+ Swig_TypeCache_global = NULL;
++
++ SWIG_PYOBJ_REFCNT(Swig_Capsule_global);
+ Swig_Capsule_global = NULL;
++
++ SWIG_Py_XDECREF(Swig_runtime_data_module_global);
++ SWIG_PYOBJ_REFCNT(Swig_runtime_data_module_global);
++ Swig_runtime_data_module_global = NULL;
+ }
+
+ SWIGRUNTIME void
+ SWIG_Python_SetModule(swig_module_info *swig_module) {
+-#if PY_VERSION_HEX >= 0x03000000
+- /* Add a dummy module object into sys.modules */
+- PyObject *module = PyImport_AddModule(SWIG_RUNTIME_MODULE);
+-#else
+- static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */
+- PyObject *module = Py_InitModule(SWIG_RUNTIME_MODULE, swig_empty_runtime_method_table);
+-#endif
++ PyObject *runtime_data_module = SWIG_runtime_data_module();
+ PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule);
+- if (pointer && module) {
+- if (PyModule_AddObject(module, SWIGPY_CAPSULE_ATTR_NAME, pointer) == 0) {
++ if (pointer && runtime_data_module) {
++ if (PyModule_AddObject(runtime_data_module, SWIGPY_CAPSULE_ATTR_NAME, pointer) == 0) {
+ ++interpreter_counter;
+ Swig_Capsule_global = pointer;
+ } else {
+
+From 53453d51ec3ca111c5c97530d8ee4c6b5184c85e Mon Sep 17 00:00:00 2001
+From: William S Fulton <[email protected]>
+Date: Mon, 12 May 2025 07:25:35 +0100
+Subject: [PATCH 3/5] Rename Python swigvarlink type to SwigVarLink
+
+With this type having just moved into a module, let's also
+make a change to use correct Python naming conventions for the
+name of the type.
+---
+ CHANGES.current | 8 ++++++
+ Lib/python/pyrun.swg | 64 ++++++++++++++++++++++----------------------
+ 2 files changed, 40 insertions(+), 32 deletions(-)
+
+--- a/Lib/python/pyrun.swg
++++ b/Lib/python/pyrun.swg
+@@ -257,7 +257,7 @@ typedef struct swig_varlinkobject {
+ } swig_varlinkobject;
+
+ SWIGINTERN PyObject *
+-swig_varlink_repr(PyObject *SWIGUNUSEDPARM(v)) {
++SwigVarLink_repr(PyObject *SWIGUNUSEDPARM(v)) {
+ #if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_InternFromString("<Swig global variables>");
+ #else
+@@ -266,7 +266,7 @@ swig_varlink_repr(PyObject *SWIGUNUSEDPARM(v)) {
+ }
+
+ SWIGINTERN PyObject *
+-swig_varlink_str(PyObject *o) {
++SwigVarLink_str(PyObject *o) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ #if PY_VERSION_HEX >= 0x03000000
+ PyObject *str = PyUnicode_InternFromString("(");
+@@ -305,7 +305,7 @@ swig_varlink_str(PyObject *o) {
+ }
+
+ SWIGINTERN void
+-swig_varlink_dealloc(PyObject *o) {
++SwigVarLink_dealloc(PyObject *o) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ swig_globalvar *var = v->vars;
+ while (var) {
+@@ -317,7 +317,7 @@ swig_varlink_dealloc(PyObject *o) {
+ }
+
+ SWIGINTERN PyObject *
+-swig_varlink_getattr(PyObject *o, char *n) {
++SwigVarLink_getattr(PyObject *o, char *n) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ PyObject *res = NULL;
+ swig_globalvar *var = v->vars;
+@@ -335,7 +335,7 @@ swig_varlink_getattr(PyObject *o, char *n) {
+ }
+
+ SWIGINTERN int
+-swig_varlink_setattr(PyObject *o, char *n, PyObject *p) {
++SwigVarLink_setattr(PyObject *o, char *n, PyObject *p) {
+ swig_varlinkobject *v = (swig_varlinkobject *) o;
+ int res = 1;
+ swig_globalvar *var = v->vars;
+@@ -358,7 +358,7 @@ swig_varlink_setattr(PyObject *o, char *n, PyObject *p) {
+
+ SWIGINTERN PyTypeObject*
+ swig_varlink_type(void) {
+- static char varlink__doc__[] = "Swig variable link object";
++ static char SwigVarLink_doc[] = "Swig variable link object";
+ #ifndef SWIG_HEAPTYPES
+ static PyTypeObject varlink_type;
+ static int type_init = 0;
+@@ -370,30 +370,30 @@ swig_varlink_type(void) {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ #endif
+- SWIG_RUNTIME_MODULE ".swigvarlink", /* tp_name */
++ SWIG_RUNTIME_MODULE ".SwigVarLink", /* tp_name */
+ sizeof(swig_varlinkobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+- (destructor) swig_varlink_dealloc, /* tp_dealloc */
++ (destructor) SwigVarLink_dealloc, /* tp_dealloc */
+ #if PY_VERSION_HEX < 0x030800b4
+ (printfunc)0, /* tp_print */
+ #else
+ (Py_ssize_t)0, /* tp_vectorcall_offset */
+ #endif
+- (getattrfunc) swig_varlink_getattr, /* tp_getattr */
+- (setattrfunc) swig_varlink_setattr, /* tp_setattr */
++ (getattrfunc) SwigVarLink_getattr, /* tp_getattr */
++ (setattrfunc) SwigVarLink_setattr, /* tp_setattr */
+ 0, /* tp_compare */
+- (reprfunc) swig_varlink_repr, /* tp_repr */
++ (reprfunc) SwigVarLink_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+- (reprfunc) swig_varlink_str, /* tp_str */
++ (reprfunc) SwigVarLink_str, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ 0, /* tp_flags */
+- varlink__doc__, /* tp_doc */
++ SwigVarLink_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+@@ -429,22 +429,22 @@ swig_varlink_type(void) {
+ type_init = 1;
+ if (PyType_Ready(&varlink_type) < 0)
+ return NULL;
+- if (PyModule_AddObject(runtime_data_module, "swigvarlink", (PyObject *)&varlink_type) == 0)
++ if (PyModule_AddObject(runtime_data_module, "SwigVarLink", (PyObject *)&varlink_type) == 0)
+ SWIG_Py_INCREF((PyObject *)&varlink_type);
+ }
+ return &varlink_type;
+ #else
+ PyType_Slot slots[] = {
+- { Py_tp_dealloc, (void *)swig_varlink_dealloc },
+- { Py_tp_repr, (void *)swig_varlink_repr },
+- { Py_tp_getattr, (void *)swig_varlink_getattr },
+- { Py_tp_setattr, (void *)swig_varlink_setattr },
+- { Py_tp_str, (void *)swig_varlink_str },
+- { Py_tp_doc, (void *)varlink__doc__ },
++ { Py_tp_dealloc, (void *)SwigVarLink_dealloc },
++ { Py_tp_repr, (void *)SwigVarLink_repr },
++ { Py_tp_getattr, (void *)SwigVarLink_getattr },
++ { Py_tp_setattr, (void *)SwigVarLink_setattr },
++ { Py_tp_str, (void *)SwigVarLink_str },
++ { Py_tp_doc, (void *)SwigVarLink_doc },
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
+- SWIG_RUNTIME_MODULE ".swigvarlink",
++ SWIG_RUNTIME_MODULE ".SwigVarLink",
+ sizeof(swig_varlinkobject),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+@@ -452,7 +452,7 @@ swig_varlink_type(void) {
+ };
+ PyObject *pytype = PyType_FromSpec(&spec);
+ PyObject *runtime_data_module = SWIG_runtime_data_module();
+- if (pytype && PyModule_AddObject(runtime_data_module, "swigvarlink", pytype) == 0)
++ if (pytype && PyModule_AddObject(runtime_data_module, "SwigVarLink", pytype) == 0)
+ SWIG_Py_INCREF(pytype);
+ return (PyTypeObject *)pytype;
+ #endif
+@@ -715,7 +715,7 @@ SwigPyObject_repr(SwigPyObject *v)
+ }
+
+ /* We need a version taking two PyObject* parameters so it's a valid
+- * PyCFunction to use in swigobject_methods[]. */
++ * PyCFunction to use in SwigPyObject_methods[]. */
+ SWIGRUNTIME PyObject *
+ SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+ {
+@@ -922,7 +922,7 @@ SwigPyObject_own(PyObject *v, PyObject *args)
+ }
+
+ static PyMethodDef
+-swigobject_methods[] = {
++SwigPyObject_methods[] = {
+ {"disown", SwigPyObject_disown, METH_NOARGS, "releases ownership of the pointer"},
+ {"acquire", SwigPyObject_acquire, METH_NOARGS, "acquires ownership of the pointer"},
+ {"own", SwigPyObject_own, METH_VARARGS, "returns/sets ownership of the pointer"},
+@@ -934,7 +934,7 @@ swigobject_methods[] = {
+
+ SWIGRUNTIME PyTypeObject*
+ SwigPyObject_TypeOnce(void) {
+- static char swigobject_doc[] = "Swig object holding a C/C++ pointer";
++ static char SwigPyObject_doc[] = "Swig object holding a C/C++ pointer";
+ #ifndef SWIG_HEAPTYPES
+ static PyNumberMethods SwigPyObject_as_number = {
+ (binaryfunc)0, /*nb_add*/
+@@ -1017,14 +1017,14 @@ SwigPyObject_TypeOnce(void) {
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+- swigobject_doc, /* tp_doc */
++ SwigPyObject_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+- swigobject_methods, /* tp_methods */
++ SwigPyObject_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+@@ -1081,9 +1081,9 @@ SwigPyObject_TypeOnce(void) {
+ { Py_tp_dealloc, (void *)SwigPyObject_dealloc },
+ { Py_tp_repr, (void *)SwigPyObject_repr },
+ { Py_tp_getattro, (void *)PyObject_GenericGetAttr },
+- { Py_tp_doc, (void *)swigobject_doc },
++ { Py_tp_doc, (void *)SwigPyObject_doc },
+ { Py_tp_richcompare, (void *)SwigPyObject_richcompare },
+- { Py_tp_methods, (void *)swigobject_methods },
++ { Py_tp_methods, (void *)SwigPyObject_methods },
+ { Py_nb_int, (void *)SwigPyObject_long },
+ { 0, NULL }
+ };
+@@ -1207,7 +1207,7 @@ SwigPyPacked_dealloc(PyObject *v)
+
+ SWIGRUNTIME PyTypeObject*
+ SwigPyPacked_TypeOnce(void) {
+- static char swigpacked_doc[] = "Swig object holding a C/C++ function pointer";
++ static char SwigPyPacked_doc[] = "Swig object holding a C/C++ function pointer";
+ #ifndef SWIG_HEAPTYPES
+ static PyTypeObject swigpypacked_type;
+ static int type_init = 0;
+@@ -1246,7 +1246,7 @@ SwigPyPacked_TypeOnce(void) {
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+- swigpacked_doc, /* tp_doc */
++ SwigPyPacked_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+@@ -1311,7 +1311,7 @@ SwigPyPacked_TypeOnce(void) {
+ { Py_tp_repr, (void *)SwigPyPacked_repr },
+ { Py_tp_str, (void *)SwigPyPacked_str },
+ { Py_tp_getattro, (void *)PyObject_GenericGetAttr },
+- { Py_tp_doc, (void *)swigpacked_doc },
++ { Py_tp_doc, (void *)SwigPyPacked_doc },
+ { 0, NULL }
+ };
+ PyType_Spec spec = {
diff --git a/contrib/tools/swig/swig_lib.cpp b/contrib/tools/swig/swig_lib.cpp
new file mode 100644
index 00000000000..75b98501e88
--- /dev/null
+++ b/contrib/tools/swig/swig_lib.cpp
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _STR(a) #a
+#define STR(a) _STR(a)
+
+static const char* ArcadiaRoot() {
+ const char* root = getenv("ARCADIA_ROOT_DISTBUILD");
+ return root ? root : STR(ARCADIA_ROOT);
+}
+
+#ifdef _MSC_VER
+static int setenv(const char* name, const char* value, int overwrite) {
+ return (overwrite || !getenv(name)) ? _putenv_s(name, value) : 0;
+}
+#endif
+
+static void InitSwigLib() {
+ const char* root = ArcadiaRoot();
+ const char* lib = STR(SWIG_LIB_ARCPATH);
+ char* s = new char[strlen(root) + 1 + strlen(lib) + 1];
+ sprintf(s, "%s/%s", root, lib);
+ setenv("SWIG_LIB", s, false);
+ delete[] s;
+}
+
+static int initSwigLib = (InitSwigLib(), 0);
diff --git a/contrib/tools/swig/ya.make b/contrib/tools/swig/ya.make
new file mode 100644
index 00000000000..6650cd196aa
--- /dev/null
+++ b/contrib/tools/swig/ya.make
@@ -0,0 +1,124 @@
+# Generated by devtools/yamaker from nixpkgs 24.05.
+
+PROGRAM(swig)
+
+LICENSE(
+ Custom-swig AND
+ GPL-3.0-only AND
+ GPL-3.0-or-later AND
+ LicenseRef-scancode-other-copyleft
+)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+VERSION(4.3.1)
+
+ORIGINAL_SOURCE(https://github.com/swig/swig/archive/v4.3.1.tar.gz)
+
+PEERDIR(
+ contrib/libs/pcre2
+)
+
+ADDINCL(
+ contrib/libs/pcre2
+ contrib/tools/swig/Source/CParse
+ contrib/tools/swig/Source/DOH
+ contrib/tools/swig/Source/Doxygen
+ contrib/tools/swig/Source/Include
+ contrib/tools/swig/Source/Modules
+ contrib/tools/swig/Source/Preprocessor
+ contrib/tools/swig/Source/Swig
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+CFLAGS(
+ -DSWIG_LIB_ARCPATH=contrib/tools/swig/Lib
+ -DHAVE_CONFIG_H
+)
+
+BISON_GEN_C()
+
+SRCS(
+ Source/CParse/cscanner.c
+ Source/CParse/parser.y
+ Source/CParse/templ.c
+ Source/CParse/util.c
+ Source/DOH/base.c
+ Source/DOH/file.c
+ Source/DOH/fio.c
+ Source/DOH/hash.c
+ Source/DOH/list.c
+ Source/DOH/memory.c
+ Source/DOH/string.c
+ Source/DOH/void.c
+ Source/Doxygen/csharpdoc.cxx
+ Source/Doxygen/doxyentity.cxx
+ Source/Doxygen/doxyparser.cxx
+ Source/Doxygen/doxytranslator.cxx
+ Source/Doxygen/javadoc.cxx
+ Source/Doxygen/pydoc.cxx
+ Source/Modules/allocate.cxx
+ Source/Modules/c.cxx
+ Source/Modules/contract.cxx
+ Source/Modules/csharp.cxx
+ Source/Modules/d.cxx
+ Source/Modules/directors.cxx
+ Source/Modules/emit.cxx
+ Source/Modules/go.cxx
+ Source/Modules/guile.cxx
+ Source/Modules/interface.cxx
+ Source/Modules/java.cxx
+ Source/Modules/javascript.cxx
+ Source/Modules/lang.cxx
+ Source/Modules/lua.cxx
+ Source/Modules/main.cxx
+ Source/Modules/mzscheme.cxx
+ Source/Modules/nested.cxx
+ Source/Modules/ocaml.cxx
+ Source/Modules/octave.cxx
+ Source/Modules/overload.cxx
+ Source/Modules/perl5.cxx
+ Source/Modules/php.cxx
+ Source/Modules/python.cxx
+ Source/Modules/r.cxx
+ Source/Modules/ruby.cxx
+ Source/Modules/scilab.cxx
+ Source/Modules/swigmain.cxx
+ Source/Modules/tcl8.cxx
+ Source/Modules/typepass.cxx
+ Source/Modules/utils.cxx
+ Source/Modules/xml.cxx
+ Source/Preprocessor/cpp.c
+ Source/Preprocessor/expr.c
+ Source/Swig/cwrap.c
+ Source/Swig/deprecate.c
+ Source/Swig/error.c
+ Source/Swig/extend.c
+ Source/Swig/fragment.c
+ Source/Swig/getopt.c
+ Source/Swig/include.c
+ Source/Swig/misc.c
+ Source/Swig/naming.c
+ Source/Swig/parms.c
+ Source/Swig/scanner.c
+ Source/Swig/stype.c
+ Source/Swig/symbol.c
+ Source/Swig/tree.c
+ Source/Swig/typemap.c
+ Source/Swig/typeobj.c
+ Source/Swig/typesys.c
+ Source/Swig/wrapfunc.c
+ swig_lib.cpp
+)
+
+END()
+
+RECURSE(
+ Lib/go
+ Lib/java
+ Lib/perl5
+ Lib/python
+)