diff --git a/COPYRIGHT b/COPYRIGHT index 3f4711a47..28b7f1f0d 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -15,7 +15,9 @@ Active SWIG Developers: Olly Betts (olly@survex.com) (PHP) Joseph Wang (joequant@gmail.com) (R) Xavier Delacour (xavier.delacour@gmail.com) (Octave) - David Nadlinger (code@klickverbot.at) (D) + David Nadlinger (code@klickverbot.at) + Oliver Buchtala (oliver.buchtala@gmail.com) (Javascript) + Neha Narang (narangneha03@gmail.com) (Javascript) Past SWIG developers and major contributors include: Dave Beazley (dave-swig@dabeaz.com) (SWIG core, Python, Tcl, Perl) diff --git a/Doc/Manual/style.css b/Doc/Manual/style.css index 02329e56f..7eabf91ae 100644 --- a/Doc/Manual/style.css +++ b/Doc/Manual/style.css @@ -25,7 +25,7 @@ div.indent { margin-right: 4em; } -div.code { +div.code, div:not(.code) pre { border-style: solid; border-width: 1px; padding: 2pt; @@ -82,3 +82,7 @@ div.indent p { margin-right: 0; } +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + text-decoration:none; + color: #000000; +} diff --git a/Examples/Makefile.in b/Examples/Makefile.in index df754427c..a2a211cbd 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -664,6 +664,82 @@ android_clean: rm -f `find $(PACKAGEDIR) -name \*.java | grep -v $(PROJECTNAME).java` rm -rf obj +################################################################## +##### JAVASCRIPT ###### +################################################################## + +ROOT_DIR = @ROOT_DIR@ +JSCFLAGS = @JSCFLAGS@ +JSCXXFLAGS = @JSCXXFLAGS@ +JSINCLUDES = @JSCOREINC@ @JSV8INC@ +JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@ +JSLIBRARYPREFIX = @JSLIBRARYPREFIX@ +JSSO =@JSSO@ +JSLDSHARED = @JSLDSHARED@ +JSCXXSHARED = @JSCXXSHARED@ + +# ---------------------------------------------------------------- +# Compile a custom javascript interpreter +# ---------------------------------------------------------------- +# +# Note: +# There is no common CLI Javascript interpreter. +# V8 comes with one 'd8' which however does not provide a means +# to load extensions. Therefore, by default we use nodejs as +# environment. +# For testing native v8 and jsc extensions we provide our own +# interpreter (see 'Tools/javascript'). +# ---------------------------------------------------------------- + +JS_INTERPRETER_SRC_DIR = $(ROOT_DIR)/Tools/javascript + +# These settings are provided by 'configure' (see '/configure.in') +ifeq (1, @JSV8ENABLED@) + JS_INTERPRETER_SRC_V8 = $(JS_INTERPRETER_SRC_DIR)/v8_shell.cxx + JS_INTERPRETER_CXXFLAGS_V8 = -DENABLE_V8 +endif + +ifeq (1, @JSCENABLED@) + JS_INTERPRETER_SRC_JSC = $(JS_INTERPRETER_SRC_DIR)/jsc_shell.cxx + JS_INTERPRETER_CXXFLAGS_JSC = -DENABLE_JSC +endif + +JS_INTERPRETER_CXXFLAGS = $(JS_INTERPRETER_CXXFLAGS_JSC) $(JS_INTERPRETER_CXXFLAGS_V8) +JS_INTERPRETER_SRC = \ + $(JS_INTERPRETER_SRC_DIR)/javascript.cxx $(JS_INTERPRETER_SRC_DIR)/js_shell.cxx $(JS_INTERPRETER_SRC_JSC) $(JS_INTERPRETER_SRC_V8) + +# TODO: improve: +# - exe suffix +# - '-ldl' should come from configure +javascript_exe: $(SRCS) + $(CXX) $(CXXFLAGS) $(JS_INTERPRETER_CXXFLAGS) $(JSINCLUDES) $(JS_INTERPRETER_SRC) -ldl $(LIBS) $(JSDYNAMICLINKING) -o $(JS_INTERPRETER_SRC_DIR)/javascript + +SWIGJS = $(SWIG) -javascript + +# ---------------------------------------------------------------- +# Run the javascript executable +# ---------------------------------------------------------------- + +javascript: $(SRCS) + $(SWIGJS) $(SWIGOPT) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CFLAGS) $(JSCFLAGS) $(ISRCS) $(SRCS) $(INCLUDES) $(JSINCLUDES) + $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +javascript_cpp: $(SRCS) + $(SWIGJS) -c++ $(SWIGOPT) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CFLAGS) $(JSCFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(JSINCLUDES) + $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +# ----------------------------------------------------------------- +# Cleaning the javascript examples +# ----------------------------------------------------------------- + +javascript_clean: + rm -rf build + rm -f *_wrap* runme + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@JSSO@ + ################################################################## ##### MODULA3 ###### ################################################################## @@ -1539,7 +1615,7 @@ endif r_cpp: $(CXXSRCS) $(SWIG) -c++ -r $(SWIGOPT) -o $(RCXXSRCS) $(INTERFACEPATH) ifneq ($(CXXSRCS),) - $(CXX) -g -c $(CFLAGS) $(R_CFLAGS) $(CXXSRCS) $(INCLUDES) + $(CXX) -g -c $(CFLAGS) $(R_CFLAGS) $(CXXSRCS) $(INCLUDES) endif +( PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 5d6a4730a..1dc7992f5 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -95,6 +95,7 @@ C_TEST_BROKEN += \ # C++ test cases. (Can be run individually using: make testcase.cpptest) +ifndef SKIP_CPP_CASES CPP_TEST_CASES += \ abstract_access \ abstract_inherit \ @@ -475,6 +476,7 @@ CPP_TEST_CASES += \ voidtest \ wallkw \ wrapmacro +endif # # Put all the heavy STD/STL cases here, where they can be skipped if needed @@ -507,6 +509,7 @@ endif # C test cases. (Can be run individually using: make testcase.ctest) +ifndef SKIP_C_CASES C_TEST_CASES += \ arrays \ bom_utf8 \ @@ -554,9 +557,10 @@ C_TEST_CASES += \ typemap_subst \ union_parameter \ unions - +endif # Multi-module C++ test cases . (Can be run individually using make testcase.multicpptest) +ifndef SKIP_MULTI_CPP_CASES MULTI_CPP_TEST_CASES += \ clientdata_prop \ imports \ @@ -565,6 +569,7 @@ MULTI_CPP_TEST_CASES += \ mod \ template_typedef_import \ multi_import +endif # Custom tests - tests with additional commandline options wallkw.cpptest: SWIGOPT += -Wallkw diff --git a/Examples/test-suite/constructor_copy.i b/Examples/test-suite/constructor_copy.i index f6bdcb240..6a0e90c71 100644 --- a/Examples/test-suite/constructor_copy.i +++ b/Examples/test-suite/constructor_copy.i @@ -73,7 +73,7 @@ public: %include "std_vector.i" -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY) || defined(SWIGJAVASCRIPT) #define SWIG_GOOD_VECTOR %ignore std::vector::vector(size_type); %ignore std::vector::resize(size_type); diff --git a/Examples/test-suite/director_nspace.i b/Examples/test-suite/director_nspace.i index 121a06f1f..ed144f212 100644 --- a/Examples/test-suite/director_nspace.i +++ b/Examples/test-suite/director_nspace.i @@ -40,7 +40,7 @@ namespace TopLevel %include // nspace feature only supported by these languages -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGJAVASCRIPT) %nspace TopLevel::Bar::Foo; %nspace TopLevel::Bar::FooBar; #else diff --git a/Examples/test-suite/infinity.i b/Examples/test-suite/infinity.i new file mode 100644 index 000000000..41741eb94 --- /dev/null +++ b/Examples/test-suite/infinity.i @@ -0,0 +1,48 @@ +%module infinity + +#include + +/* C99 defines INFINITY + Because INFINITY may be defined by compiler built-ins, we can't use #define. + Instead, expose the variable MYINFINITY and then use %rename to make it INFINITY in the scripting language. +*/ +%rename(INFINITY) MYINFINITY; + + +%inline %{ +#include + +/* C99 math.h defines INFINITY. If not available, this is the fallback. */ +#ifndef INFINITY + #ifdef _MSC_VER + union MSVC_EVIL_FLOAT_HACK + { + unsigned __int8 Bytes[4]; + float Value; + }; + static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; + #define INFINITY (INFINITY_HACK.Value) + #endif + + #ifdef __GNUC__ + #define INFINITY (__builtin_inf()) + #elif defined(__clang__) + #if __has_builtin(__builtin_inf) + #define INFINITY (__builtin_inf()) + #endif + #endif + + #ifndef INFINITY + #define INFINITY (1e1000) + #endif +#endif + +/* This will allow us to bind the real INFINITY value through SWIG via MYINFINITY. Use %rename to fix the name. */ +const double MYINFINITY = INFINITY; + +/* Use of float is intentional because the original bug was in the float conversion due to overflow checking. */ +float use_infinity(float inf_val) +{ + return inf_val; +} +%} diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in new file mode 100755 index 000000000..49652f0bd --- /dev/null +++ b/Examples/test-suite/javascript/Makefile.in @@ -0,0 +1,181 @@ +####################################################################### +# Makefile for javascript test-suite +####################################################################### + +LANGUAGE = javascript +SCRIPTSUFFIX = _runme.js +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +SWIG = $(top_builddir)/preinst_swig + +ifneq (, $(ENGINE)) + JSENGINE=$(ENGINE) +else + JSENGINE=node +endif + +# Note: the javascript generator is not ready yet for the real game. +# To be able keep the behavior continously tested that is expected to work already +# we have a 'light' version of the test-suite +# This will be removed and replaced by a list of 'BROKEN_TEST_CASES' when +# the number gets smaller (currently we have about 65 broken tests for JSC, and 85 for V8) + +ifneq (,$(SMOKE)) + +C_TEST_CASES = \ + preproc \ + preproc_include + +CPP_TEST_CASES = \ + abstract_access \ + abstract_typedef \ + abstract_typedef2 \ + abstract_virtual \ + arrays_global \ + array_member \ + char_binary \ + class_ignore \ + class_scope_weird \ + complextest \ + constover \ + constructor_copy \ + cpp_enum \ + cpp_namespace \ + cpp_static \ + enum_template \ + namespace_virtual_method \ + nspace \ + nspace_extend \ + overload_copy \ + rename_simple \ + rename_scope \ + ret_by_value \ + struct_value \ + template_static \ + typedef_class \ + typedef_inherit \ + typedef_scope \ + typemap_arrays \ + typemap_delete \ + typemap_namespace \ + typemap_ns_using \ + using1 \ + using2 \ + javascript_unicode + +SKIP_CPP_CASES = @SKIP_CPP_CASES@ +SKIP_C_CASES = @SKIP_C_CASES@ +SKIP_CPP_STD_CASES = @SKIP_CPP_STD_CASES@ +SKIP_MULTI_CPP_CASES = @SKIP_MULTI_CPP_CASES@ + +endif + +include $(srcdir)/../common.mk + +_setup = \ + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + echo "$(ACTION)ing testcase $* (with run test) under javascript ($(JSENGINE))" ; \ + else \ + echo "$(ACTION)ing testcase $* under javascript ($(JSENGINE))" ; \ + fi; + +ifneq (jsc,$(ENGINE)) + + # This test can not be run with v8 as it uses v8 API incompatible output typemaps + typemap_variables.cpptest: + echo "skipping testcase typemap_variables under javascript ($(JSENGINE))." + + # with v8 we have to generate C++ wrappers only + # these tests did raise warnings which are ignored + nested.ctest: SWIGOPT += -w312,-325 + nested_structs.ctest: SWIGOPT += -w312,-325 + unions.ctest: SWIGOPT += -w312,-325 + +endif + +ifeq (node,$(JSENGINE)) + + SWIGOPT += -v8 -DBUILDING_NODE_EXTENSION=1 + + # shut up some warnings + # contract macro has an empty 'else' at the end... + aggregate.cpptest: GYP_CFLAGS = \"-Wno-empty-body\" + contract.cpptest: GYP_CFLAGS = \"-Wno-empty-body\" + + # dunno... ignoring generously + apply_signed_char.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" + constant_pointers.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" + enum_thorough.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" + + __setup = \ + sh ./setup_test.sh $* $(GYP_CFLAGS); \ + $(SWIG) -c++ -javascript $(SWIGOPT) ../$*.i; + + nodejs_swig_and_compile = \ + node-gyp --loglevel=silent --directory $* configure build 1>>/dev/null + + run_testcase = \ + if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \ + node $(srcdir)/$*$(SCRIPTSUFFIX); \ + fi + + %.cpptest: + $(_setup) + $(__setup) + $(nodejs_swig_and_compile) + $(run_testcase) + + %.ctest: + $(_setup) + $(__setup) + $(nodejs_swig_and_compile) + $(run_testcase) + + %.multicpptest: + $(_setup) + +else + + SWIGOPT += -$(JSENGINE) + + run_testcase = \ + if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \ + $(top_srcdir)/Tools/javascript/javascript -$(JSENGINE) $(srcdir)/$*$(SCRIPTSUFFIX); \ + fi + + %.cpptest: + $(_setup) + +$(swig_and_compile_cpp) + $(run_testcase) + + %.multicpptest: + $(_setup) + +$(swig_and_compile_multi_cpp) + $(run_testcase) + +endif + +ifeq (v8,$(ENGINE)) + %.ctest: + $(_setup) + +$(swig_and_compile_cpp) + $(run_testcase) + +endif + +ifeq (jsc,$(ENGINE)) + %.ctest: + $(_setup) + +$(swig_and_compile_c) + $(run_testcase) +endif + +%.clean: + rm -rf $* + +clean: + rm -f *_wrap.cxx + rm -f *_wrap.c + rm -f *.so + rm -f *.o diff --git a/Examples/test-suite/javascript/abstract_access_runme.js b/Examples/test-suite/javascript/abstract_access_runme.js new file mode 100644 index 000000000..8f87d2105 --- /dev/null +++ b/Examples/test-suite/javascript/abstract_access_runme.js @@ -0,0 +1,6 @@ +var abstract_access = require("./abstract_access"); + +var d = new abstract_access.D() +if (d.do_x() != 1) { + throw "Error"; +} diff --git a/Examples/test-suite/javascript/abstract_inherit_runme.js b/Examples/test-suite/javascript/abstract_inherit_runme.js new file mode 100644 index 000000000..3af2eae74 --- /dev/null +++ b/Examples/test-suite/javascript/abstract_inherit_runme.js @@ -0,0 +1,40 @@ +var abstract_inherit = require("./abstract_inherit"); + +// Shouldn't be able to instantiate any of these classes +// since none of them implements the pure virtual function +// declared in the base class (Foo). +var Foo = abstract_inherit.Foo; +var Bar = abstract_inherit.Bar; +var Spam = abstract_inherit.Spam; + +var caughtException = false; +try { + new Foo(); +} catch (err) { + caughtException = true; +} +if (!caughtException) { + throw new Error("Foo should be instantiated as it is abstract"); +} + +caughtException = false; +try { + new Bar(); +} catch (err) { + caughtException = true; +} + +if (!caughtException) { + throw new Error("Bar should be instantiated as it is abstract"); +} + +caughtException = false; +try { + new Spam(); +} catch (err) { + caughtException = true; +} + +if (!caughtException) { + throw new Error("Spam should be instantiated as it is abstract"); +} diff --git a/Examples/test-suite/javascript/abstract_typedef2_runme.js b/Examples/test-suite/javascript/abstract_typedef2_runme.js new file mode 100644 index 000000000..c177e49c3 --- /dev/null +++ b/Examples/test-suite/javascript/abstract_typedef2_runme.js @@ -0,0 +1,6 @@ +var abstract_typedef2 = require("./abstract_typedef2"); + +var a = new abstract_typedef2.A_UF(); + +if (a == undefined) + throw "Error"; diff --git a/Examples/test-suite/javascript/abstract_typedef_runme.js b/Examples/test-suite/javascript/abstract_typedef_runme.js new file mode 100644 index 000000000..abcfc581d --- /dev/null +++ b/Examples/test-suite/javascript/abstract_typedef_runme.js @@ -0,0 +1,8 @@ +var abstract_typedef = require("./abstract_typedef"); + +var e = new abstract_typedef.Engine(); +var a = new abstract_typedef.A() + +if (a.write(e) != 1) { + throw "Error"; +} diff --git a/Examples/test-suite/javascript/abstract_virtual_runme.js b/Examples/test-suite/javascript/abstract_virtual_runme.js new file mode 100644 index 000000000..9e2814e41 --- /dev/null +++ b/Examples/test-suite/javascript/abstract_virtual_runme.js @@ -0,0 +1,11 @@ +var abstract_virtual = require("./abstract_virtual"); + +d = new abstract_virtual.D() + +if (d == undefined) + throw "Error"; + +e = new abstract_virtual.E() + +if (e == undefined) + throw "Error"; diff --git a/Examples/test-suite/javascript/array_member_runme.js b/Examples/test-suite/javascript/array_member_runme.js new file mode 100644 index 000000000..8c4ef1da5 --- /dev/null +++ b/Examples/test-suite/javascript/array_member_runme.js @@ -0,0 +1,22 @@ +var array_member = require("./array_member"); + +var f = new array_member.Foo(); +f.data = array_member.global_data; + +for (var i=0; i<8; i++) { + if (array_member.get_value(f.data,i) != array_member.get_value(array_member.global_data,i)) { + throw "Bad array assignment (1)"; + } +} + +for (var i=0; i<8; i++) { + array_member.set_value(f.data,i,-i); +} + +array_member.global_data = f.data; + +for (var i=0; i<8; i++){ + if (array_member.get_value(f.data,i) != array_member.get_value(array_member.global_data,i)) { + throw "Bad array assignment (2)"; + } +} diff --git a/Examples/test-suite/javascript/arrays_global_runme.js b/Examples/test-suite/javascript/arrays_global_runme.js new file mode 100644 index 000000000..fdb365f83 --- /dev/null +++ b/Examples/test-suite/javascript/arrays_global_runme.js @@ -0,0 +1,18 @@ +var arrays_global = require("./arrays_global"); + +arrays_global.array_i = arrays_global.array_const_i; + +arrays_global.BeginString_FIX44a; +arrays_global.BeginString_FIX44b; +arrays_global.BeginString_FIX44c; +arrays_global.BeginString_FIX44d; +arrays_global.BeginString_FIX44d; +arrays_global.BeginString_FIX44b = "12"+'\0'+"45"; +arrays_global.BeginString_FIX44b; +arrays_global.BeginString_FIX44d; +arrays_global.BeginString_FIX44e; +arrays_global.BeginString_FIX44f; + +arrays_global.test_a("hello","hi","chello","chi"); + +arrays_global.test_b("1234567","hi"); diff --git a/Examples/test-suite/javascript/callback_runme.js b/Examples/test-suite/javascript/callback_runme.js new file mode 100644 index 000000000..9b1ef01a3 --- /dev/null +++ b/Examples/test-suite/javascript/callback_runme.js @@ -0,0 +1,30 @@ +var callback = require("./callback"); + +if (callback.foo(2) !== 2) { + throw new Error("Failed."); +} +if (callback.A_bar(2) !== 4) { + throw new Error("Failed."); +} +if (callback.foobar(3, callback.foo) != callback.foo(3)) { + throw new Error("Failed."); +} +if (callback.foobar(3, foo) != callback.foo(3)) { + throw new Error("Failed."); +} +if (callback.foobar(3, callback.A_bar) != callback.A_bar(3)) { + throw new Error("Failed."); +} +if (callback.foobar(3, callback.foof) != callback.foof(3)) { + throw new Error("Failed."); +} +if (callback.foobar_i(3, callback.foo_i) != callback.foo_i(3)) { + throw new Error("Failed."); +} +if (callback.foobar_d(3.5, callback.foo_d) != callback.foo_d(3.5)) { + throw new Error("Failed."); +} +var a = new callback.A(); +if (callback.foobarm(3, a, callback.A.foom_cb_ptr) != a.foom(3)) { + throw new Error("Failed."); +} diff --git a/Examples/test-suite/javascript/char_binary_runme.js b/Examples/test-suite/javascript/char_binary_runme.js new file mode 100644 index 000000000..42abe6060 --- /dev/null +++ b/Examples/test-suite/javascript/char_binary_runme.js @@ -0,0 +1,38 @@ +var char_binary = require("./char_binary"); + +var t = new char_binary.Test(); +if (t.strlen('hile') != 4) { + print(t.strlen('hile')); + throw("bad multi-arg typemap 1"); +} + +if (t.strlen('hil\0') != 4) { + throw("bad multi-arg typemap 2"); +} + +/* + * creating a raw char* + */ +var pc = char_binary.new_pchar(5); +char_binary.pchar_setitem(pc, 0, 'h'); +char_binary.pchar_setitem(pc, 1, 'o'); +char_binary.pchar_setitem(pc, 2, 'l'); +char_binary.pchar_setitem(pc, 3, 'a'); +char_binary.pchar_setitem(pc, 4, 0); + + +if (t.strlen(pc) != 4) { + throw("bad multi-arg typemap (3)"); +} + +char_binary.var_pchar = pc; +if (char_binary.var_pchar != "hola") { + print(char_binary.var_pchar); + throw("bad pointer case (1)"); +} + +char_binary.var_namet = pc; +if (char_binary.var_namet != "hola") { + throw("bad pointer case (2)"); +} +char_binary.delete_pchar(pc); diff --git a/Examples/test-suite/javascript/char_strings_runme.js b/Examples/test-suite/javascript/char_strings_runme.js new file mode 100644 index 000000000..cca50d851 --- /dev/null +++ b/Examples/test-suite/javascript/char_strings_runme.js @@ -0,0 +1,11 @@ +var char_strings = require("./char_strings"); + +var assertIsEqual = function(expected, actual) { + if (expected !== actual) { + throw new Error("Expected "+expected+", was "+actual); + } +}; + +assertIsEqual("hi there", char_strings.CharPingPong("hi there")); +assertIsEqual("hi there", char_strings.CharArrayPingPong("hi there")); +assertIsEqual("hi there", char_strings.CharArrayDimsPingPong("hi there")); diff --git a/Examples/test-suite/javascript/class_ignore_runme.js b/Examples/test-suite/javascript/class_ignore_runme.js new file mode 100644 index 000000000..f0a32a1c4 --- /dev/null +++ b/Examples/test-suite/javascript/class_ignore_runme.js @@ -0,0 +1,6 @@ +var class_ignore = require("./class_ignore"); + +a = new class_ignore.Bar(); + +if (class_ignore.do_blah(a) != "Bar::blah") + throw "Error"; diff --git a/Examples/test-suite/javascript/class_scope_weird_runme.js b/Examples/test-suite/javascript/class_scope_weird_runme.js new file mode 100644 index 000000000..ac745d023 --- /dev/null +++ b/Examples/test-suite/javascript/class_scope_weird_runme.js @@ -0,0 +1,6 @@ +var class_scope_weird = require("./class_scope_weird"); + +f = new class_scope_weird.Foo(); +g = new class_scope_weird.Foo(3); +if (f.bar(3) != 3) + throw RuntimeError; diff --git a/Examples/test-suite/javascript/complextest_runme.js b/Examples/test-suite/javascript/complextest_runme.js new file mode 100644 index 000000000..1fcc97648 --- /dev/null +++ b/Examples/test-suite/javascript/complextest_runme.js @@ -0,0 +1,22 @@ +var complextest = require("./complextest"); + +a = [-1,2]; + +expected = [-1, -2]; + +a_c = complextest.Conj(a); +if (a_c.toString() != expected.toString()) + throw "Error in Conj(a)"; + +a_c_f = complextest.Conjf(a); +if (a_c_f.toString() != expected.toString()) + throw "Error in Conjf(a)"; + +v = new complextest.VectorStdCplx(); +v.add([1,2]); +v.add([2,3]); +v.add([4,3]); +v.add(1); + +// TODO: how to check validity? +complextest.Copy_h(v); diff --git a/Examples/test-suite/javascript/constover_runme.js b/Examples/test-suite/javascript/constover_runme.js new file mode 100644 index 000000000..764d8b328 --- /dev/null +++ b/Examples/test-suite/javascript/constover_runme.js @@ -0,0 +1,33 @@ +var constover = require("./constover"); + +p = constover.test("test"); +if (p != "test") { + throw "test failed!"; +} + +p = constover.test_pconst("test"); +if (p != "test_pconst") { + throw "test_pconst failed!"; +} + +f = new constover.Foo(); + +p = f.test("test"); +if (p != "test") { + throw "member-test failed!"; +} + +p = f.test_pconst("test"); +if (p != "test_pconst") { + throw "member-test_pconst failed!"; +} + +p = f.test_constm("test"); +if (p != "test_constmethod") { + throw "member-test_constm failed!"; +} + +p = f.test_pconstm("test"); +if (p != "test_pconstmethod") { + throw "member-test_pconstm failed!"; +} diff --git a/Examples/test-suite/javascript/constructor_copy_runme.js b/Examples/test-suite/javascript/constructor_copy_runme.js new file mode 100644 index 000000000..39dce52ce --- /dev/null +++ b/Examples/test-suite/javascript/constructor_copy_runme.js @@ -0,0 +1,42 @@ +var constructor_copy = require("./constructor_copy"); + +f1 = new constructor_copy.Foo1(3); +f11 = new constructor_copy.Foo1(f1); + +if (f1.x != f11.x) { + throw "error in ctor copy for Foo1"; +} + +var good = 0; + +f8 = new constructor_copy.Foo8() +try { + f81 = new constructor_copy.Foo8(f8); + good = 0; +} catch (err) { + good = 1; +} + +if (good == 0) { + throw "Error: should not allow calling copy ctor for Foo8"; +} + + +bi = new constructor_copy.Bari(5); +bc = new constructor_copy.Bari(bi); + +if (bi.x != bc.x) { + throw "Error in copy ctor of Bari"; +} + +bd = new constructor_copy.Bard(5); +try { + bc = new constructor_copy.Bard(bd); + good = 0; +} catch (err) { + good = 1; +} + +if (good == 0) { + throw "Error: should not allow calling copy ctor for Bard"; +} diff --git a/Examples/test-suite/javascript/cpp_enum_runme.js b/Examples/test-suite/javascript/cpp_enum_runme.js new file mode 100644 index 000000000..35f7c60ac --- /dev/null +++ b/Examples/test-suite/javascript/cpp_enum_runme.js @@ -0,0 +1,28 @@ +var cpp_enum = require("./cpp_enum"); + +var f = new cpp_enum.Foo() + +if(f.hola != cpp_enum.Hello){ + print(f.hola); + throw "Error"; +} + +f.hola = cpp_enum.Foo.Hi +if(f.hola != cpp_enum.Foo.Hi){ + print(f.hola); + throw "Error"; +} + +f.hola = cpp_enum.Hello + +if(f.hola != cpp_enum.Hello){ + print(f.hola); + throw "Error"; +} + +cpp_enum.Foo.hi = cpp_enum.Hello +if(cpp_enum.Foo.hi != cpp_enum.Hello){ + print(cpp_enum.Foo.hi); + throw "Error"; +} + diff --git a/Examples/test-suite/javascript/cpp_namespace_runme.js b/Examples/test-suite/javascript/cpp_namespace_runme.js new file mode 100644 index 000000000..3bdfef3e9 --- /dev/null +++ b/Examples/test-suite/javascript/cpp_namespace_runme.js @@ -0,0 +1,47 @@ +var cpp_namespace = require("./cpp_namespace"); + +var n = cpp_namespace.fact(4); +if (n != 24){ + throw ("Bad return value error!"); +} +if (cpp_namespace.Foo != 42){ + throw ("Bad variable value error!"); +} + +t = new cpp_namespace.Test(); +if (t.method() != "Test::method"){ + throw ("Bad method return value error!"); +} +if (cpp_namespace.do_method(t) != "Test::method"){ + throw ("Bad return value error!"); +} + +if (cpp_namespace.do_method2(t) != "Test::method"){ + throw ("Bad return value error!"); +} +cpp_namespace.weird("hello", 4); +delete t; + +t2 = new cpp_namespace.Test2(); +t3 = new cpp_namespace.Test3(); +t4 = new cpp_namespace.Test4(); +t5 = new cpp_namespace.Test5(); +if (cpp_namespace.foo3(42) != 42){ + throw ("Bad return value error!"); +} + +if (cpp_namespace.do_method3(t2,40) != "Test2::method"){ + throw ("Bad return value error!"); +} + +if (cpp_namespace.do_method3(t3,40) != "Test3::method"){ + throw ("Bad return value error!"); +} + +if (cpp_namespace.do_method3(t4,40) != "Test4::method"){ + throw ("Bad return value error!"); +} + +if (cpp_namespace.do_method3(t5,40) != "Test5::method"){ + throw ("Bad return value error!"); +} diff --git a/Examples/test-suite/javascript/cpp_static_runme.js b/Examples/test-suite/javascript/cpp_static_runme.js new file mode 100644 index 000000000..2579aeafe --- /dev/null +++ b/Examples/test-suite/javascript/cpp_static_runme.js @@ -0,0 +1,9 @@ +var cpp_static = require("./cpp_static"); + +cpp_static.StaticFunctionTest.static_func(); +cpp_static.StaticFunctionTest.static_func_2(1); +cpp_static.StaticFunctionTest.static_func_3(1,2); +cpp_static.StaticMemberTest.static_int = 10; +if (cpp_static.StaticMemberTest.static_int != 10) +throw "error"; + diff --git a/Examples/test-suite/javascript/director_alternating_runme.js b/Examples/test-suite/javascript/director_alternating_runme.js new file mode 100644 index 000000000..a0411eace --- /dev/null +++ b/Examples/test-suite/javascript/director_alternating_runme.js @@ -0,0 +1,5 @@ +var director_alternating = require("./director_alternating"); + +id = director_alternating.getBar().id(); +if (id != director_alternating.idFromGetBar()) + throw ("Error, Got wrong id: " + str(id)); diff --git a/Examples/test-suite/javascript/disown_runme.js b/Examples/test-suite/javascript/disown_runme.js new file mode 100644 index 000000000..a4a6fd880 --- /dev/null +++ b/Examples/test-suite/javascript/disown_runme.js @@ -0,0 +1,22 @@ +var disown = require("./disown"); + +var a = new disown.A(); +var tmp = a.thisown; +a.thisown = 0 +if (a.thisown) { + throw new Error("Failed."); +} +a.thisown = 1 +if (!a.thisown) { + throw new Error("Failed."); +} +a.thisown = tmp +if (a.thisown != tmp) { + throw new Error("Failed."); +} + +var b = new disown.B(); +b.acquire(a); +if (a.thisown) { + throw new Error("Failed."); +} diff --git a/Examples/test-suite/javascript/dynamic_cast_runme.js b/Examples/test-suite/javascript/dynamic_cast_runme.js new file mode 100644 index 000000000..0029cb0f8 --- /dev/null +++ b/Examples/test-suite/javascript/dynamic_cast_runme.js @@ -0,0 +1,12 @@ +var dynamic_cast = require("./dynamic_cast"); + +var f = new dynamic_cast.Foo(); +var b = new dynamic_cast.Bar(); + +var x = f.blah(); +var y = b.blah(); + +var a = dynamic_cast.do_test(y); +if (a != "Bar::test") { + throw new Error("Failed."); +} diff --git a/Examples/test-suite/javascript/empty_runme.js b/Examples/test-suite/javascript/empty_runme.js new file mode 100644 index 000000000..db06b3902 --- /dev/null +++ b/Examples/test-suite/javascript/empty_runme.js @@ -0,0 +1 @@ +var empty = require("./empty"); \ No newline at end of file diff --git a/Examples/test-suite/javascript/enum_template_runme.js b/Examples/test-suite/javascript/enum_template_runme.js new file mode 100644 index 000000000..20f8c3482 --- /dev/null +++ b/Examples/test-suite/javascript/enum_template_runme.js @@ -0,0 +1,8 @@ +var enum_template = require("./enum_template"); + +if (enum_template.MakeETest() != 1) + throw "RuntimeError"; + +if (enum_template.TakeETest(0) != null) + throw "RuntimeError"; + diff --git a/Examples/test-suite/javascript/infinity_runme.js b/Examples/test-suite/javascript/infinity_runme.js new file mode 100644 index 000000000..1dcf366c6 --- /dev/null +++ b/Examples/test-suite/javascript/infinity_runme.js @@ -0,0 +1,4 @@ +var infinity = require("./infinity"); + +var my_infinity = infinity.INFINTY; +var ret_val = infinity.use_infinity(my_infinity); diff --git a/Examples/test-suite/javascript/javascript_unicode_runme.js b/Examples/test-suite/javascript/javascript_unicode_runme.js new file mode 100644 index 000000000..f5f747aa7 --- /dev/null +++ b/Examples/test-suite/javascript/javascript_unicode_runme.js @@ -0,0 +1,9 @@ +var javascript_unicode = require("./javascript_unicode"); + +var str = "olé"; + +var copy = javascript_unicode.copy_string(str); + +if (str !== copy) { + print("Error: copy is not equal: original="+str+", copy="+copy); +} diff --git a/Examples/test-suite/javascript/namespace_virtual_method_runme.js b/Examples/test-suite/javascript/namespace_virtual_method_runme.js new file mode 100644 index 000000000..24d3bd487 --- /dev/null +++ b/Examples/test-suite/javascript/namespace_virtual_method_runme.js @@ -0,0 +1,3 @@ +var namespace_virtual_method = require("./namespace_virtual_method"); + +x = new namespace_virtual_method.Spam(); diff --git a/Examples/test-suite/javascript/node_template/binding.gyp.in b/Examples/test-suite/javascript/node_template/binding.gyp.in new file mode 100644 index 000000000..209774ae0 --- /dev/null +++ b/Examples/test-suite/javascript/node_template/binding.gyp.in @@ -0,0 +1,30 @@ +{ + "targets": [ + { + "target_name": "$testcase", + "sources":[ "../$testcase_wrap.cxx" ], + "include_dirs": ["../.."], + 'defines': [ + 'BUILDING_NODE_EXTENSION=1', + ], + 'conditions': [ + ['OS=="mac"', + { + 'xcode_settings': { + 'GCC_ENABLE_CPP_RTTI': 'YES', + 'GCC_ENABLE_CPP_EXCEPTIONS' : 'YES' + } + } + ], + ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', + { + 'cflags': [ "-Wno-unused-variable", "-Wno-unused-but-set-variable", "-Wno-unused-but-set-parameter", $cflags], + 'cflags_cc': [ "-Wno-unused-variable", "-Wno-unused-but-set-variable", "-Wno-unused-but-set-parameter", $cflags], + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions', '-fno-rtti' ] + } + ] + ], + } + ], +} diff --git a/Examples/test-suite/javascript/node_template/index.js.in b/Examples/test-suite/javascript/node_template/index.js.in new file mode 100644 index 000000000..72330499d --- /dev/null +++ b/Examples/test-suite/javascript/node_template/index.js.in @@ -0,0 +1 @@ +module.exports = require('./build/Release/$testcase'); diff --git a/Examples/test-suite/javascript/nspace_extend_runme.js b/Examples/test-suite/javascript/nspace_extend_runme.js new file mode 100644 index 000000000..ab81c19d3 --- /dev/null +++ b/Examples/test-suite/javascript/nspace_extend_runme.js @@ -0,0 +1,27 @@ +var nspace_extend = require("./nspace_extend"); + +// constructors and destructors +var color1 = new nspace_extend.Outer.Inner1.Color(); +var color = new nspace_extend.Outer.Inner1.Color(color1); +delete color1; + +// class methods +color.colorInstanceMethod(20.0); +nspace_extend.Outer.Inner1.Color.colorStaticMethod(20.0); +var created = nspace_extend.Outer.Inner1.Color.create(); + + +// constructors and destructors +var color2 = new nspace_extend.Outer.Inner2.Color(); +color = new nspace_extend.Outer.Inner2.Color(color2); +delete color2; + +// class methods +color.colorInstanceMethod(20.0); +nspace_extend.Outer.Inner2.Color.colorStaticMethod(20.0); +created = nspace_extend.Outer.Inner2.Color.create(); + +// Same class different namespaces +var col1 = new nspace_extend.Outer.Inner1.Color(); +var col2 = nspace_extend.Outer.Inner2.Color.create(); +col2.colors(col1, col1, col2, col2, col2); diff --git a/Examples/test-suite/javascript/nspace_runme.js b/Examples/test-suite/javascript/nspace_runme.js new file mode 100644 index 000000000..929a6b21d --- /dev/null +++ b/Examples/test-suite/javascript/nspace_runme.js @@ -0,0 +1,77 @@ +var nspace = require("./nspace"); + +var color1 = new nspace.Outer.Inner1.Color(); +var color = new nspace.Outer.Inner1.Color(color1); +delete color1; + +// class methods +color.colorInstanceMethod(20.0); +nspace.Outer.Inner1.Color.colorStaticMethod(20.0); +var created = nspace.Outer.Inner1.Color.create(); + +// class enums +var someClass = new nspace.Outer.SomeClass(); +var channel = someClass.GetInner1ColorChannel(); +if (channel != nspace.Outer.Inner1.Color.Transmission) { + throw new Error("Failed."); +} + +// class anonymous enums +var val1 = nspace.Outer.Inner1.Color.ColorEnumVal1; +var val2 = nspace.Outer.Inner1.Color.ColorEnumVal2; +if (val1 !== 0 || val2 !== 0x22) { + throw new Error("Failed."); +} + +// instance member variables +color.instanceMemberVariable = 123; +if (color.instanceMemberVariable !== 123) { + throw new Error("Failed."); +} + +// static member variables +nspace.Outer.Inner1.Color.staticMemberVariable = 789; +if (nspace.Outer.Inner1.Color.staticMemberVariable !== 789) { + throw new Error("Failed."); +} + +if (nspace.Outer.Inner1.Color.staticConstMemberVariable !== 222) { + throw new Error("Failed."); +} + +if (nspace.Outer.Inner1.Color.staticConstEnumMemberVariable !== nspace.Outer.Inner1.Color.Transmission) { + throw new Error("Failed."); +} + +// Same class different namespaces +var col1 = new nspace.Outer.Inner1.Color(); +var col2 = nspace.Outer.Inner2.Color.create(); +col2.colors(col1, col1, col2, col2, col2); + +// TODO: why isn't it scoped in the namespace??? +nspace.namespaceFunction(color); +nspace.Outer.Inner1.namespaceVar = 111; +if (nspace.Outer.Inner1.namespaceVar !== 111) { + throw new Error("Failed."); +} + +// global enums +var outerChannel1 = someClass.GetInner1Channel(); +if (outerChannel1 != nspace.Outer.Inner1.Transmission1) { + throw new Error("Failed."); +} + +var outerChannel2 = someClass.GetInner2Channel(); +if (outerChannel2 !== nspace.Outer.Inner2.Transmission2) { + throw new Error("Failed."); +} + +// turn feature off / ignoring +var ns = new nspace.Outer.namespce(); +var nons = new nspace.NoNSpacePlease(); + +// Derived class +var blue3 = new nspace.Outer.Inner3.Blue(); +blue3.blueInstanceMethod(); +var blue4 = new nspace.Outer.Inner4.Blue(); +blue4.blueInstanceMethod(); diff --git a/Examples/test-suite/javascript/overload_copy_runme.js b/Examples/test-suite/javascript/overload_copy_runme.js new file mode 100644 index 000000000..1039ffda1 --- /dev/null +++ b/Examples/test-suite/javascript/overload_copy_runme.js @@ -0,0 +1,4 @@ +var overload_copy = require("./overload_copy"); + +f = new overload_copy.Foo(); +g = new overload_copy.Foo(f); diff --git a/Examples/test-suite/javascript/preproc_include_runme.js b/Examples/test-suite/javascript/preproc_include_runme.js new file mode 100644 index 000000000..4b827fbcc --- /dev/null +++ b/Examples/test-suite/javascript/preproc_include_runme.js @@ -0,0 +1,23 @@ +var preproc_include = require("./preproc_include"); + +if (preproc_include.multiply10(10) != 100) + throw "RuntimeError"; + +if (preproc_include.multiply20(10) != 200) + throw "RuntimeError"; + +if (preproc_include.multiply30(10) != 300) + throw "RuntimeError"; + +if (preproc_include.multiply40(10) != 400) + throw "RuntimeError"; + +if (preproc_include.multiply50(10) != 500) + throw "RuntimeError"; + +if (preproc_include.multiply60(10) != 600) + throw "RuntimeError"; + +if (preproc_include.multiply70(10) != 700) + throw "RuntimeError"; + diff --git a/Examples/test-suite/javascript/preproc_runme.js b/Examples/test-suite/javascript/preproc_runme.js new file mode 100644 index 000000000..669f9d1f0 --- /dev/null +++ b/Examples/test-suite/javascript/preproc_runme.js @@ -0,0 +1,14 @@ +var preproc = require("./preproc"); + +if (preproc.endif != 1) + throw "RuntimeError"; + +if (preproc.define != 1) + throw "RuntimeError"; + +if (preproc.defined != 1) + throw "RuntimeError"; + +if (2*preproc.one != preproc.two) + throw "RuntimeError"; + diff --git a/Examples/test-suite/javascript/rename1_runme.js b/Examples/test-suite/javascript/rename1_runme.js new file mode 100644 index 000000000..8374e6a89 --- /dev/null +++ b/Examples/test-suite/javascript/rename1_runme.js @@ -0,0 +1,68 @@ +var rename = require("./rename1"); + +function part1() { + var xyz = new rename.XYZInt(); + notxyz = new rename.NotXYZInt(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother2(); + xyz.opT2(); + xyz.tMethod2(0); + xyz.tMethodNotXYZ2(notxyz); + xyz.opNotXYZ2(); + xyz.opXYZ2(); +} + +function part2() { + var xyz = new rename.XYZDouble(); + var notxyz = new rename.NotXYZDouble(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother1(); + xyz.opT1(); + xyz.tMethod1(0); + xyz.tMethodNotXYZ1(notxyz); + xyz.opNotXYZ1(); + xyz.opXYZ1(); +} + +function part3(){ + var xyz = new rename.XYZKlass(); + var notxyz = new rename.NotXYZKlass(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother3(); + xyz.opT3(); + xyz.tMethod3(new rename.Klass()); + xyz.tMethodNotXYZ3(notxyz); + xyz.opNotXYZ3(); + xyz.opXYZ3(); +} + +function part4() { + var xyz = new rename.XYZEnu(); + var notxyz = new rename.NotXYZEnu(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother4(); + xyz.opT4(); + xyz.tMethod4(rename.En1); + xyz.tMethodNotXYZ4(notxyz); + xyz.opNotXYZ4(); + xyz.opXYZ4(); +} + +function part5() { + var abc = new rename.ABC(); + abc.methodABC(abc); + var k = new rename.Klass(); + abc.methodKlass(k); + var a = abc.opABC(); + k = abc.opKlass(); +} + +part1(); +part2(); +part3(); +part4(); +part5(); diff --git a/Examples/test-suite/javascript/rename2_runme.js b/Examples/test-suite/javascript/rename2_runme.js new file mode 100644 index 000000000..bc6a95a59 --- /dev/null +++ b/Examples/test-suite/javascript/rename2_runme.js @@ -0,0 +1,68 @@ +var rename = require("./rename2"); + +function part1() { + var xyz = new rename.XYZInt(); + notxyz = new rename.NotXYZInt(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother2(); + xyz.opT2(); + xyz.tMethod2(0); + xyz.tMethodNotXYZ2(notxyz); + xyz.opNotXYZ2(); + xyz.opXYZ2(); +} + +function part2() { + var xyz = new rename.XYZDouble(); + var notxyz = new rename.NotXYZDouble(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother1(); + xyz.opT1(); + xyz.tMethod1(0); + xyz.tMethodNotXYZ1(notxyz); + xyz.opNotXYZ1(); + xyz.opXYZ1(); +} + +function part3(){ + var xyz = new rename.XYZKlass(); + var notxyz = new rename.NotXYZKlass(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother3(); + xyz.opT3(); + xyz.tMethod3(new rename.Klass()); + xyz.tMethodNotXYZ3(notxyz); + xyz.opNotXYZ3(); + xyz.opXYZ3(); +} + +function part4() { + var xyz = new rename.XYZEnu(); + var notxyz = new rename.NotXYZEnu(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother4(); + xyz.opT4(); + xyz.tMethod4(rename.En1); + xyz.tMethodNotXYZ4(notxyz); + xyz.opNotXYZ4(); + xyz.opXYZ4(); +} + +function part5() { + var abc = new rename.ABC(); + abc.methodABC(abc); + var k = new rename.Klass(); + abc.methodKlass(k); + var a = abc.opABC(); + k = abc.opKlass(); +} + +part1(); +part2(); +part3(); +part4(); +part5(); diff --git a/Examples/test-suite/javascript/rename3_runme.js b/Examples/test-suite/javascript/rename3_runme.js new file mode 100644 index 000000000..9e57e80ea --- /dev/null +++ b/Examples/test-suite/javascript/rename3_runme.js @@ -0,0 +1,68 @@ +var rename = require("./rename3"); + +function part1() { + var xyz = new rename.XYZInt(); + notxyz = new rename.NotXYZInt(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother2(); + xyz.opT2(); + xyz.tMethod2(0); + xyz.tMethodNotXYZ2(notxyz); + xyz.opNotXYZ2(); + xyz.opXYZ2(); +} + +function part2() { + var xyz = new rename.XYZDouble(); + var notxyz = new rename.NotXYZDouble(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother1(); + xyz.opT1(); + xyz.tMethod1(0); + xyz.tMethodNotXYZ1(notxyz); + xyz.opNotXYZ1(); + xyz.opXYZ1(); +} + +function part3(){ + var xyz = new rename.XYZKlass(); + var notxyz = new rename.NotXYZKlass(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother3(); + xyz.opT3(); + xyz.tMethod3(new rename.Klass()); + xyz.tMethodNotXYZ3(notxyz); + xyz.opNotXYZ3(); + xyz.opXYZ3(); +} + +function part4() { + var xyz = new rename.XYZEnu(); + var notxyz = new rename.NotXYZEnu(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother4(); + xyz.opT4(); + xyz.tMethod4(rename.En1); + xyz.tMethodNotXYZ4(notxyz); + xyz.opNotXYZ4(); + xyz.opXYZ4(); +} + +function part5() { + var abc = new rename.ABC(); + abc.methodABC(abc); + var k = new rename.Klass(); + abc.methodKlass(k); + var a = abc.opABC(); + k = abc.opKlass(); +} + +part1(); +part2(); +part3(); +part4(); +part5(); diff --git a/Examples/test-suite/javascript/rename4_runme.js b/Examples/test-suite/javascript/rename4_runme.js new file mode 100644 index 000000000..d651fc7a1 --- /dev/null +++ b/Examples/test-suite/javascript/rename4_runme.js @@ -0,0 +1,68 @@ +var rename = require("./rename4"); + +function part1() { + var xyz = new rename.XYZInt(); + notxyz = new rename.NotXYZInt(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother2(); + xyz.opT2(); + xyz.tMethod2(0); + xyz.tMethodNotXYZ2(notxyz); + xyz.opNotXYZ2(); + xyz.opXYZ2(); +} + +function part2() { + var xyz = new rename.XYZDouble(); + var notxyz = new rename.NotXYZDouble(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother1(); + xyz.opT1(); + xyz.tMethod1(0); + xyz.tMethodNotXYZ1(notxyz); + xyz.opNotXYZ1(); + xyz.opXYZ1(); +} + +function part3(){ + var xyz = new rename.XYZKlass(); + var notxyz = new rename.NotXYZKlass(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother3(); + xyz.opT3(); + xyz.tMethod3(new rename.Klass()); + xyz.tMethodNotXYZ3(notxyz); + xyz.opNotXYZ3(); + xyz.opXYZ3(); +} + +function part4() { + var xyz = new rename.XYZEnu(); + var notxyz = new rename.NotXYZEnu(); + xyz.opIntPtrA(); + xyz.opIntPtrB(); + xyz.opAnother4(); + xyz.opT4(); + xyz.tMethod4(rename.En1); + xyz.tMethodNotXYZ4(notxyz); + xyz.opNotXYZ4(); + xyz.opXYZ4(); +} + +function part5() { + var abc = new rename.ABC(); + abc.methodABC(abc); + var k = new rename.Klass(); + abc.methodKlass(k); + var a = abc.opABC(); + k = abc.opKlass(); +} + +part1(); +part2(); +part3(); +part4(); +part5(); diff --git a/Examples/test-suite/javascript/rename_scope_runme.js b/Examples/test-suite/javascript/rename_scope_runme.js new file mode 100644 index 000000000..c0226df69 --- /dev/null +++ b/Examples/test-suite/javascript/rename_scope_runme.js @@ -0,0 +1,17 @@ +var rename_scope = require("./rename_scope"); + +var a = new rename_scope.Natural_UP(); +var b = new rename_scope.Natural_BP(); + +if (a.rtest() !== 1) { + throw new Error("a.rtest(): Expected 1, was " + a.rtest()); +} + +if (b.rtest() !== 1) { + throw new Error("b.rtest(): Expected 1, was " + b.rtest()); +} + +var f = rename_scope.equals; +if (f === undefined) { + throw new Error("Equality operator has not been renamed."); +} diff --git a/Examples/test-suite/javascript/rename_simple_runme.js b/Examples/test-suite/javascript/rename_simple_runme.js new file mode 100644 index 000000000..918dd68a5 --- /dev/null +++ b/Examples/test-suite/javascript/rename_simple_runme.js @@ -0,0 +1,50 @@ +var rename_simple = require("./rename_simple"); +var NewStruct = rename_simple.NewStruct; + +var s = new NewStruct(); + +// renamed instance variable +if (s.NewInstanceVariable !== 111) { + throw new Error("NewInstanceVariable: Expected 111, was " + s.NewInstanceVariable); +} + +// renamed instance method +if (s.NewInstanceMethod() !== 222) { + throw new Error("NewInstanceMethod(): Expected 222, was " + s.NewInstanceMethod()); +} + +// renamed static method +if (NewStruct.NewStaticMethod() !== 333) { + throw new Error("NewInstanceMethod(): Expected 333, was " + NewStruct.NewStaticMethod()); +} + +// renamed static variable +if (NewStruct.NewStaticVariable !== 444) { + throw new Error("NewInstanceMethod(): Expected 444, was " + NewStruct.NewStaticVariable); +} + +// renamed global function +if (rename_simple.NewFunction() !== 555) { + throw new Error("rename_simple.NewFunction(): Expected 555, was " + rename_simple.NewFunction()); +} + +// renamed global variable +if (rename_simple.NewGlobalVariable !== 666) { + throw new Error("rename_simple.NewGlobalVariable: Expected 666, was " + rename_simple.NewGlobalVariable); +} + +// setting renamed variables +s.NewInstanceVariable = 1111; +if (s.NewInstanceVariable !== 1111) { + throw new Error("NewInstanceVariable: Expected 1111, was " + s.NewInstanceVariable); +} + +NewStruct.NewStaticVariable = 4444; +if (NewStruct.NewStaticVariable !== 4444) { + throw new Error("NewInstanceMethod(): Expected 4444, was " + NewStruct.NewStaticVariable); +} + +rename_simple.NewGlobalVariable = 6666; +if (rename_simple.NewGlobalVariable !== 6666) { + throw new Error("rename_simple.NewGlobalVariable: Expected 6666, was " + rename_simple.NewGlobalVariable); +} diff --git a/Examples/test-suite/javascript/ret_by_value_runme.js b/Examples/test-suite/javascript/ret_by_value_runme.js new file mode 100644 index 000000000..d9a77a20b --- /dev/null +++ b/Examples/test-suite/javascript/ret_by_value_runme.js @@ -0,0 +1,8 @@ +var ret_by_value = require("./ret_by_value"); + +a = ret_by_value.get_test(); +if (a.myInt != 100) + throw "RuntimeError"; + +if (a.myShort != 200) + throw "RuntimeError"; diff --git a/Examples/test-suite/javascript/setup_test.sh b/Examples/test-suite/javascript/setup_test.sh new file mode 100644 index 000000000..913a74c4b --- /dev/null +++ b/Examples/test-suite/javascript/setup_test.sh @@ -0,0 +1,6 @@ +#!/bin/sh +if [ ! -d $1 ]; then + mkdir $1; +fi +sed -e "s/\$testcase/$1/" -e "s/\$cflags/$2/" < node_template/binding.gyp.in > $1/binding.gyp +sed s/\$testcase/$1/ node_template/index.js.in > $1/index.js diff --git a/Examples/test-suite/javascript/struct_value_runme.js b/Examples/test-suite/javascript/struct_value_runme.js new file mode 100644 index 000000000..d6b26f726 --- /dev/null +++ b/Examples/test-suite/javascript/struct_value_runme.js @@ -0,0 +1,11 @@ +var struct_value = require("./struct_value"); + +b = new struct_value.Bar(); + +b.a.x = 3; +if (b.a.x != 3) +throw "RuntimeError"; + +b.b.x = 3; +if (b.b.x != 3) +throw "RuntimeError" diff --git a/Examples/test-suite/javascript/template_static_runme.js b/Examples/test-suite/javascript/template_static_runme.js new file mode 100644 index 000000000..477d97249 --- /dev/null +++ b/Examples/test-suite/javascript/template_static_runme.js @@ -0,0 +1,3 @@ +var template_static = require("./template_static"); + +template_static.Foo.bar_double(1); diff --git a/Examples/test-suite/javascript/typedef_class_runme.js b/Examples/test-suite/javascript/typedef_class_runme.js new file mode 100644 index 000000000..3e4dc9093 --- /dev/null +++ b/Examples/test-suite/javascript/typedef_class_runme.js @@ -0,0 +1,7 @@ +var typedef_class = require("./typedef_class"); + +a = new typedef_class.RealA(); +a.a = 3; + +b = new typedef_class.B(); +b.testA(a); diff --git a/Examples/test-suite/javascript/typedef_inherit_runme.js b/Examples/test-suite/javascript/typedef_inherit_runme.js new file mode 100644 index 000000000..4abcc2536 --- /dev/null +++ b/Examples/test-suite/javascript/typedef_inherit_runme.js @@ -0,0 +1,23 @@ +var typedef_inherit = require("./typedef_inherit"); + +a = new typedef_inherit.Foo(); +b = new typedef_inherit.Bar(); + +x = typedef_inherit.do_blah(a); +if (x != "Foo::blah") + print("Whoa! Bad return" + x); + +x = typedef_inherit.do_blah(b); +if (x != "Bar::blah") + print("Whoa! Bad return" + x); + +c = new typedef_inherit.Spam(); +d = new typedef_inherit.Grok(); + +x = typedef_inherit.do_blah2(c); +if (x != "Spam::blah") + print("Whoa! Bad return" + x); + +x = typedef_inherit.do_blah2(d); +if (x != "Grok::blah") + print ("Whoa! Bad return" + x); diff --git a/Examples/test-suite/javascript/typedef_scope_runme.js b/Examples/test-suite/javascript/typedef_scope_runme.js new file mode 100644 index 000000000..0ac56884c --- /dev/null +++ b/Examples/test-suite/javascript/typedef_scope_runme.js @@ -0,0 +1,12 @@ +var typedef_scope = require("./typedef_scope"); + +b = new typedef_scope.Bar(); +x = b.test1(42,"hello"); +if (x != 42) + print("Failed!!"); + +x = b.test2(42,"hello"); +if (x != "hello") + print("Failed!!"); + + diff --git a/Examples/test-suite/javascript/typemap_arrays_runme.js b/Examples/test-suite/javascript/typemap_arrays_runme.js new file mode 100644 index 000000000..cd6827ac9 --- /dev/null +++ b/Examples/test-suite/javascript/typemap_arrays_runme.js @@ -0,0 +1,5 @@ +var typemap_arrays = require("./typemap_arrays"); + +if (typemap_arrays.sumA(null) != 60) + throw "RuntimeError, Sum is wrong"; + diff --git a/Examples/test-suite/javascript/typemap_delete_runme.js b/Examples/test-suite/javascript/typemap_delete_runme.js new file mode 100644 index 000000000..4b3174956 --- /dev/null +++ b/Examples/test-suite/javascript/typemap_delete_runme.js @@ -0,0 +1,5 @@ +var typemap_delete = require("./typemap_delete"); + +r = new typemap_delete.Rect(123); +if (r.val != 123) + throw "RuntimeError"; diff --git a/Examples/test-suite/javascript/typemap_namespace_runme.js b/Examples/test-suite/javascript/typemap_namespace_runme.js new file mode 100644 index 000000000..614e0ffeb --- /dev/null +++ b/Examples/test-suite/javascript/typemap_namespace_runme.js @@ -0,0 +1,7 @@ +var typemap_namespace = require("./typemap_namespace"); + +if (typemap_namespace.test1("hello") != "hello") + throw "RuntimeError"; + +if (typemap_namespace.test2("hello") != "hello") + throw "RuntimeError"; diff --git a/Examples/test-suite/javascript/typemap_ns_using_runme.js b/Examples/test-suite/javascript/typemap_ns_using_runme.js new file mode 100644 index 000000000..9115c16ae --- /dev/null +++ b/Examples/test-suite/javascript/typemap_ns_using_runme.js @@ -0,0 +1,4 @@ +var typemap_ns_using = require("./typemap_ns_using"); + +if (typemap_ns_using.spam(37) != 37) + throw "RuntimeError"; diff --git a/Examples/test-suite/javascript/using1_runme.js b/Examples/test-suite/javascript/using1_runme.js new file mode 100644 index 000000000..a2e37fcb6 --- /dev/null +++ b/Examples/test-suite/javascript/using1_runme.js @@ -0,0 +1,4 @@ +var using1 = require("./using1"); + +if (using1.spam(37) != 37) + throw "RuntimeError"; diff --git a/Examples/test-suite/javascript/using2_runme.js b/Examples/test-suite/javascript/using2_runme.js new file mode 100644 index 000000000..aa5e9b15f --- /dev/null +++ b/Examples/test-suite/javascript/using2_runme.js @@ -0,0 +1,4 @@ +var using2 = require("./using2"); + +if (using2.spam(37) != 37) + throw "RuntimeError"; diff --git a/Examples/test-suite/javascript/varargs_runme.js b/Examples/test-suite/javascript/varargs_runme.js new file mode 100644 index 000000000..69d761e63 --- /dev/null +++ b/Examples/test-suite/javascript/varargs_runme.js @@ -0,0 +1,44 @@ +var varargs = require("./varargs"); + +if (varargs.test("Hello") != "Hello") { + throw new Error("Failed"); +} + +var f = new varargs.Foo("Greetings") +if (f.str != "Greetings") { + throw new Error("Failed"); +} + +if (f.test("Hello") != "Hello") { + throw new Error("Failed"); +} + +if (varargs.test_def("Hello",1) != "Hello") { + throw new Error("Failed"); +} + +if (varargs.test_def("Hello") != "Hello") { + throw new Error("Failed"); +} + +if (varargs.test_plenty("Hello") != "Hello") { + throw new Error("Failed"); +} + +if (varargs.test_plenty("Hello", 1) != "Hello") { + throw new Error("Failed"); +} + +if (varargs.test_plenty("Hello", 1, 2) != "Hello") { + throw new Error("Failed"); +} + +var thrown = false; +try { + varargs.test_plenty("Hello", 1, 2, 3); +} catch (err) { + thrown = true; +} +if (!thrown) { + throw new Error("Failed"); +} diff --git a/Examples/test-suite/javascript_unicode.i b/Examples/test-suite/javascript_unicode.i new file mode 100644 index 000000000..516eee5dd --- /dev/null +++ b/Examples/test-suite/javascript_unicode.i @@ -0,0 +1,10 @@ +%module javascript_unicode + +%newobject copy_string; + +%inline %{ +#include +const char* copy_string(const char* str) { + return strdup(str); +} +%} diff --git a/Examples/test-suite/nspace.i b/Examples/test-suite/nspace.i index 2e10542d3..9bffc21ff 100644 --- a/Examples/test-suite/nspace.i +++ b/Examples/test-suite/nspace.i @@ -2,7 +2,7 @@ %module nspace // nspace feature only supported by these languages -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGJAVASCRIPT) #if defined(SWIGJAVA) SWIG_JAVABODY_PROXY(public, public, SWIGTYPE) diff --git a/Examples/test-suite/nspace_extend.i b/Examples/test-suite/nspace_extend.i index 1965ef8f6..7c1b075ed 100644 --- a/Examples/test-suite/nspace_extend.i +++ b/Examples/test-suite/nspace_extend.i @@ -2,7 +2,7 @@ %module nspace_extend // nspace feature only supported by these languages -#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGJAVASCRIPT) #if defined(SWIGJAVA) SWIG_JAVABODY_PROXY(public, public, SWIGTYPE) diff --git a/Lib/javascript/jsc/arrays_javascript.i b/Lib/javascript/jsc/arrays_javascript.i new file mode 100644 index 000000000..b9199d86b --- /dev/null +++ b/Lib/javascript/jsc/arrays_javascript.i @@ -0,0 +1,123 @@ +/* ----------------------------------------------------------------------------- + * arrays_javascript.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 JavaScript and vice versa. The JavaScript array is expected to be the same size as the C array. + * An exception is thrown if they are not. + * + * Example usage: + * Wrapping: + * + * %include + * %inline %{ + * extern int FiddleSticks[3]; + * %} + * + * Use from JavaScript like this: + * + * var fs = [10, 11, 12]; + * example.FiddleSticks = fs; + * fs = example.FiddleSticks; + * ----------------------------------------------------------------------------- */ + +%fragment("SWIG_JSCGetIntProperty", "header", fragment=SWIG_AsVal_frag(int)) {} +%fragment("SWIG_JSCGetNumberProperty", "header", fragment=SWIG_AsVal_frag(double)) {} + +%typemap(in, fragment="SWIG_JSCGetIntProperty") int[], int[ANY] + (int length = 0, JSObjectRef array, JSValueRef jsvalue, int i = 0, int res = 0, $*1_ltype temp) { + if (JSValueIsObject(context, $input)) + { + // Convert into Array + array = JSValueToObject(context, $input, NULL); + + length = $1_dim0; + + $1 = ($*1_ltype *)malloc(sizeof($*1_ltype) * length); + + // Get each element from array + for (i = 0; i < length; i++) + { + jsvalue = JSObjectGetPropertyAtIndex(context, array, i, NULL); + + // Get primitive value from JSObject + res = SWIG_AsVal(int)(jsvalue, &temp); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ERROR, "Failed to convert $input to double"); + } + arg$argnum[i] = temp; + } + + } + else + { + SWIG_exception_fail(SWIG_ERROR, "$input is not JSObjectRef"); + } +} + +%typemap(freearg) int[], int[ANY] { + free($1); +} + +%typemap(out, fragment=SWIG_From_frag(int)) int[], int[ANY] (int length = 0, int i = 0) +{ + length = $1_dim0; + JSValueRef values[length]; + + for (i = 0; i < length; i++) + { + values[i] = SWIG_From(int)($1[i]); + } + + $result = JSObjectMakeArray(context, length, values, NULL); +} + +%typemap(in, fragment="SWIG_JSCGetNumberProperty") double[], double[ANY] + (int length = 0, JSObjectRef array, JSValueRef jsvalue, int i = 0, int res = 0, $*1_ltype temp) { + if (JSValueIsObject(context, $input)) + { + // Convert into Array + array = JSValueToObject(context, $input, NULL); + + length = $1_dim0; + + $1 = ($*1_ltype *)malloc(sizeof($*1_ltype) * length); + + // Get each element from array + for (i = 0; i < length; i++) + { + jsvalue = JSObjectGetPropertyAtIndex(context, array, i, NULL); + + // Get primitive value from JSObject + res = SWIG_AsVal(double)(jsvalue, &temp); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ERROR, "Failed to convert $input to double"); + } + arg$argnum[i] = temp; + } + + } + else + { + SWIG_exception_fail(SWIG_ERROR, "$input is not JSObjectRef"); + } +} + +%typemap(freearg) double[], double[ANY] { + free($1); +} + +%typemap(out, fragment=SWIG_From_frag(double)) double[], double[ANY] (int length = 0, int i = 0) +{ + length = $1_dim0; + JSValueRef values[length]; + + for (i = 0; i < length; i++) + { + values[i] = SWIG_From(double)($1[i]); + } + + $result = JSObjectMakeArray(context, length, values, NULL); +} diff --git a/Lib/javascript/jsc/ccomplex.i b/Lib/javascript/jsc/ccomplex.i new file mode 100644 index 000000000..50f0f95fe --- /dev/null +++ b/Lib/javascript/jsc/ccomplex.i @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------------- + * ccomplex.i + * + * C complex typemaps + * ISO C99: 7.3 Complex arithmetic + * ----------------------------------------------------------------------------- */ + + +%include + +%{ +#include +%} + + +/* 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/Lib/javascript/jsc/cdata.i b/Lib/javascript/jsc/cdata.i new file mode 100644 index 000000000..367965990 --- /dev/null +++ b/Lib/javascript/jsc/cdata.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/jsc/complex.i b/Lib/javascript/jsc/complex.i new file mode 100644 index 000000000..4c3b3c5e2 --- /dev/null +++ b/Lib/javascript/jsc/complex.i @@ -0,0 +1,6 @@ +#ifdef __cplusplus +%include +#else +%include +#endif + diff --git a/Lib/javascript/jsc/exception.i b/Lib/javascript/jsc/exception.i new file mode 100644 index 000000000..0246cfde8 --- /dev/null +++ b/Lib/javascript/jsc/exception.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/jsc/javascript.swg b/Lib/javascript/jsc/javascript.swg new file mode 100644 index 000000000..3a83b6495 --- /dev/null +++ b/Lib/javascript/jsc/javascript.swg @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * javascript.swg + * + * Javascript typemaps + * ----------------------------------------------------------------------------- */ + +%include + +%include + +%include + +%include + +%include + +%include + +%include diff --git a/Lib/javascript/jsc/javascriptcode.swg b/Lib/javascript/jsc/javascriptcode.swg new file mode 100644 index 000000000..60c52b2b3 --- /dev/null +++ b/Lib/javascript/jsc/javascriptcode.swg @@ -0,0 +1,418 @@ +/* ----------------------------------------------------------------------------- + * js_ctor: template for wrapping a ctor. + * - $jswrapper: wrapper of called ctor + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * - $jsargcount: number of arguments + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor", "templates") +%{ +JSObjectRef $jswrapper(JSContextRef context, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + $jslocals + if(argc != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + + $jscode + return SWIG_JSC_NewPointerObj(context, result, SWIGTYPE_$jsmangledtype, SWIG_POINTER_OWN); + goto fail; + fail: + return NULL; +} +%} + +/* ----------------------------------------------------------------------------- + * js_veto_ctor: a vetoing ctor for abstract classes + * - $jswrapper: name of wrapper + * - $jsname: class name + * ----------------------------------------------------------------------------- */ +%fragment ("js_veto_ctor", "templates") +%{ +JSObjectRef $jswrapper(JSContextRef context, JSObjectRef ctorObject, + size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + SWIG_exception(SWIG_ERROR, "Class $jsname can not be instantiated"); + return 0; +} +%} + +/* ----------------------------------------------------------------------------- + * js_ctor_dispatcher: dispatcher for overloaded constructors + * - $jswrapper: name of wrapper + * - $jsname: class name + * - $jsdispatchcases: part containing code for dispatching + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor_dispatcher", "templates") +%{ +JSObjectRef $jswrapper(JSContextRef context, JSObjectRef ctorObject, + size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + JSObjectRef thisObject = NULL; + + // switch all cases by means of series of if-returns. + $jsdispatchcases + + // default: + SWIG_exception_fail(SWIG_ERROR, "Illegal arguments for contruction of $jsname"); + + fail: + return thisObject; +} +%} + +/* ----------------------------------------------------------------------------- + * js_overloaded_ctor: template for wrapping a ctor. + * - $jswrapper: wrapper of called ctor + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * - $jsargcount: number of arguments + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ +%fragment ("js_overloaded_ctor", "templates") +%{ +JSObjectRef $jswrapper(JSContextRef context, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + $jslocals + $jscode + return SWIG_JSC_NewPointerObj(context, result, SWIGTYPE_$jsmangledtype, SWIG_POINTER_OWN); + + goto fail; + fail: + return NULL; +} +%} + +/* ----------------------------------------------------------------------------- + * js_ctor_dispatch_case: template for a dispatch case for calling an overloaded ctor. + * - $jsargcount: number of arguments of called ctor + * - $jswrapper: wrapper of called ctor + * + * Note: a try-catch-like mechanism is used to switch cases + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor_dispatch_case", "templates") +%{ + if(argc == $jsargcount) { + thisObject = $jswrapper(context, NULL, argc, argv, exception); + if(thisObject != NULL) { *exception=0; return thisObject; } /* reset exception and return */ + } +%} + + +/* ----------------------------------------------------------------------------- + * js_dtor: template for a destructor wrapper + * - $jsmangledname: mangled class name + * - $jstype: class type + * ----------------------------------------------------------------------------- */ +%fragment ("js_dtor", "templates") +%{ +void $jswrapper(JSObjectRef thisObject) +{ + SwigPrivData* t = (SwigPrivData*) JSObjectGetPrivate(thisObject); + if(t && t->swigCMemOwn) free (($jstype)t->swigCObject); + if(t) free(t); +} +%} + +/* ----------------------------------------------------------------------------- + * js_dtor: template for a destructor wrapper + * - $jsmangledname: mangled class name + * - $jstype: class type + * - ${destructor_action}: The custom destructor action to invoke. + * ----------------------------------------------------------------------------- */ +%fragment ("js_dtoroverride", "templates") +%{ +void $jswrapper(JSObjectRef thisObject) +{ + SwigPrivData* t = (SwigPrivData*) JSObjectGetPrivate(thisObject); + if(t && t->swigCMemOwn) { + $jstype arg1 = ($jstype)t->swigCObject; + ${destructor_action} + } + if(t) free(t); +} +%} + +/* ----------------------------------------------------------------------------- + * js_getter: template for getter function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_getter", "templates") +%{ +JSValueRef $jswrapper(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + $jslocals + JSValueRef jsresult; + + $jscode + return jsresult; + + goto fail; + fail: + return NULL; +} +%} + +/* ----------------------------------------------------------------------------- + * js_setter: template for setter function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_setter", "templates") +%{ +bool $jswrapper(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) +{ + $jslocals + $jscode + + return true; + + goto fail; + fail: + return false; +} +%} + +/* ----------------------------------------------------------------------------- + * js_function: template for function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_function", "templates") +%{ +JSValueRef $jswrapper(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + $jslocals + JSValueRef jsresult; + + if(argc != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + + $jscode + return jsresult; + + goto fail; + fail: + return NULL; +} +%} + +/* ----------------------------------------------------------------------------- + * js_function_dispatcher: template for a function dispatcher for overloaded functions + * - $jswrapper: wrapper function name + * - $jsname: name of the wrapped function + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_function_dispatcher", "templates") +%{ +JSValueRef $jswrapper(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + $jslocals + JSValueRef jsresult; + int res; + $jscode + + SWIG_exception_fail(SWIG_ERROR, "Illegal arguments for function $jsname."); + return jsresult; + + goto fail; + fail: + return NULL; +} +%} + +/* ----------------------------------------------------------------------------- + * js_overloaded_function: template for a overloaded function + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_overloaded_function", "templates") +%{ +int $jswrapper(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception, JSValueRef* p_result) +{ + $jslocals + JSValueRef jsresult; + + if(argc != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + + $jscode + *p_result = jsresult; + return SWIG_OK; + + goto fail; + fail: + return SWIG_TypeError; +} +%} + +/* ----------------------------------------------------------------------------- + * js_function_dispatch_case: template for a case used in the function dispatcher + * - $jswrapper: wrapper function name + * - $jsargcount: number of arguments of overloaded function + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_function_dispatch_case", "templates") +%{ + if(argc == $jsargcount) { + res = $jswrapper(context, function, thisObject, argc, argv, exception, &jsresult); + if(res == SWIG_OK) { *exception = 0; return jsresult; } + } +%} + +/* ----------------------------------------------------------------------------- + * jsc_variable_declaration: template for a variable table entry + * - $jsname: name of the variable + * - $jsgetter: wrapper of getter function + * - $jssetter: wrapper of setter function + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_variable_declaration", "templates") +%{ + {"$jsname", $jsgetter, $jssetter, kJSPropertyAttributeNone}, +%} + + +/* ----------------------------------------------------------------------------- + * jsc_function_declaration: template for a function table entry + * - $jsname: name of the variable + * - $jswrapper: wrapper function + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_function_declaration", "templates") +%{ + {"$jsname", $jswrapper, kJSPropertyAttributeNone}, +%} + +/* ----------------------------------------------------------------------------- + * jsc_classtemplate_declaration: template for a namespace declaration + * - $jsmangledname: mangled class name + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_class_declaration", "templates") +%{ +JSClassDefinition $jsmangledname_classDefinition; + +JSClassDefinition $jsmangledname_objectDefinition; + +JSClassRef $jsmangledname_classRef; +%} + +/* ----------------------------------------------------------------------------- + * jsc_class_tables: template for a namespace declaration + * - $jsmangledname: mangled class name + * - $jsstaticclassvariables: list of static variable entries + * - $jsstaticclassfunctions: list of static function entries + * - $jsclassvariables: list of member variable entries + * - $jsclassfunctions: list of member function entries + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_class_tables", "templates") +%{ +JSStaticValue $jsmangledname_staticValues[] = { + $jsstaticclassvariables + { 0, 0, 0, 0 } +}; + +JSStaticFunction $jsmangledname_staticFunctions[] = { + $jsstaticclassfunctions + { 0, 0, 0 } +}; + +JSStaticValue $jsmangledname_values[] = { + $jsclassvariables + { 0, 0, 0, 0 } +}; + +JSStaticFunction $jsmangledname_functions[] = { + $jsclassfunctions + { 0, 0, 0 } +}; +%} + +/* ----------------------------------------------------------------------------- + * jsc_define_class_template: template for defining a class template + * - $jsmangledname: mangled class name + * - $jsmangledtype: mangled class type + * - $jsctor: wrapper of ctor + * - $jsbaseclass: mangled name of base class + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_class_definition", "templates") +%{ + $jsmangledname_classDefinition.staticFunctions = $jsmangledname_staticFunctions; + $jsmangledname_classDefinition.staticValues = $jsmangledname_staticValues; + $jsmangledname_classDefinition.callAsConstructor = $jsctor; + $jsmangledname_classDefinition.finalize = $jsdtor; + $jsmangledname_objectDefinition.staticValues = $jsmangledname_values; + $jsmangledname_objectDefinition.staticFunctions = $jsmangledname_functions; + $jsclass_inheritance + JSClassRef $jsmangledname_classRef = JSClassCreate(&$jsmangledname_objectDefinition); + SWIGTYPE_$jsmangledtype->clientdata = $jsmangledname_classRef; +%} + +%fragment ("jsc_class_inherit", templates) +%{ + if (SWIGTYPE_p$jsbaseclassmangled != NULL) { + $jsmangledname_objectDefinition.parentClass = (JSClassRef) SWIGTYPE_p$jsbaseclassmangled->clientdata; + } +%} + +%fragment ("jsc_class_noinherit", templates) +%{ + $jsmangledname_objectDefinition.parentClass = _SwigObject_classRef; +%} + + +/* ----------------------------------------------------------------------------- + * jsc_register_class: template for registration of a class + * - $jsname: class name + * - $jsmangledname: mangled class name + * - $jsnspace: mangled name of namespace + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_class_registration", "templates") +%{ + JS_registerClass(context, $jsnspace_object, "$jsname", &$jsmangledname_classDefinition); +%} + + +/* ----------------------------------------------------------------------------- + * jsc_nspace_declaration: template for a namespace declaration + * - $jsnspace: mangled name of the namespace + * - $jsglobalvariables: list of variable entries + * - $jsglobalfunctions: list if fuction entries + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_nspace_declaration", "templates") +%{ +JSStaticValue $jsnspace_values[] = { + $jsglobalvariables + { 0, 0, 0, 0 } +}; + +JSStaticFunction $jsnspace_functions[] = { + $jsglobalfunctions + { 0, 0, 0 } +}; + +JSClassDefinition $jsnspace_classDefinition; +%} + +/* ----------------------------------------------------------------------------- + * jsc_nspace_definition: template for definition of a namespace object + * - $jsmangledname: mangled name of namespace + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_nspace_definition", "templates") +%{ + $jsmangledname_classDefinition.staticFunctions = $jsmangledname_functions; + $jsmangledname_classDefinition.staticValues = $jsmangledname_values; + JSObjectRef $jsmangledname_object = JSObjectMake(context, JSClassCreate(&$jsmangledname_classDefinition), NULL); +%} + +/* ----------------------------------------------------------------------------- + * jsc_nspace_registration: template for registration of a namespace object + * - $jsname: name of namespace + * - $jsmangledname: mangled name of namespace + * - $jsparent: mangled name of parent namespace + * ----------------------------------------------------------------------------- */ +%fragment ("jsc_nspace_registration", "templates") +%{ + JS_registerNamespace(context, $jsmangledname_object, $jsparent_object, "$jsname"); +%} diff --git a/Lib/javascript/jsc/javascriptcomplex.swg b/Lib/javascript/jsc/javascriptcomplex.swg new file mode 100644 index 000000000..7d165dce4 --- /dev/null +++ b/Lib/javascript/jsc/javascriptcomplex.swg @@ -0,0 +1,146 @@ +/* + 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 concret examples. +*/ + +/* the common from converter */ +%define %swig_fromcplx_conv(Type, Real, Imag) +%fragment(SWIG_From_frag(Type),"header", + fragment=SWIG_From_frag(double)) +{ +SWIGINTERNINLINE JSObjectRef +SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) +{ + JSValueRef vals[2]; + vals[0] = SWIG_From(double)(Real(c)); + vals[1] = SWIG_From(double)(Imag(c)); + return JSObjectMakeArray(context, 2, vals, NULL); +} +} +%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_dec(Type) (JSValueRef o, Type* val) +{ + if (JSValueIsObject(context, o)) { + JSObjectRef array; + JSValueRef exception, js_re, js_im; + double re, im; + int res; + + exception = 0; + res = 0; + + array = JSValueToObject(context, o, &exception); + if(exception != 0) + return SWIG_TypeError; + + js_re = JSObjectGetPropertyAtIndex(context, array, 0, &exception); + if(exception != 0) + return SWIG_TypeError; + + js_im = JSObjectGetPropertyAtIndex(context, array, 1, &exception); + if(exception != 0) + return SWIG_TypeError; + + res = SWIG_AsVal(double)(js_re, &re); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + res = SWIG_AsVal(double)(js_im, &im); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + if (val) *val = Constructor(re, im); + 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_dec(Type)(JSValueRef o, Type *val) +{ + if (JSValueIsObject(context, o)) { + JSObjectRef array; + JSValueRef exception, js_re, js_im; + double re, im; + int res; + + exception = 0; + res = 0; + + array = JSValueToObject(context, o, &exception); + if(exception != 0) + return SWIG_TypeError; + + js_re = JSObjectGetPropertyAtIndex(context, array, 0, &exception); + if(exception != 0) + return SWIG_TypeError; + + js_im = JSObjectGetPropertyAtIndex(context, array, 1, &exception); + if(exception != 0) + return SWIG_TypeError; + + res = SWIG_AsVal(double)(js_re, &re); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + res = SWIG_AsVal(double)(js_im, &im); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + 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.0); + 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/Lib/javascript/jsc/javascriptfragments.swg b/Lib/javascript/jsc/javascriptfragments.swg new file mode 100644 index 000000000..4778bf033 --- /dev/null +++ b/Lib/javascript/jsc/javascriptfragments.swg @@ -0,0 +1,23 @@ +/* + + Create a file with this name, 'javascriptfragments.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) + { + ; + } + } + + this will replace the code used to retrieve an integer value for all + the typemaps that need it, including: + + int, std::vector, std::list >, etc. + + +*/ diff --git a/Lib/javascript/jsc/javascripthelpers.swg b/Lib/javascript/jsc/javascripthelpers.swg new file mode 100644 index 000000000..820075ca6 --- /dev/null +++ b/Lib/javascript/jsc/javascripthelpers.swg @@ -0,0 +1,69 @@ +%insert(wrapper) %{ + +bool JS_registerClass(JSGlobalContextRef context, JSObjectRef parentObject, + const char* className, + JSClassDefinition* definition) { + + JSStringRef js_className = JSStringCreateWithUTF8CString(className); + JSObjectRef classObject = JSObjectMake(context, JSClassCreate(definition), NULL); + JSObjectSetProperty(context, parentObject, + js_className, classObject, + kJSPropertyAttributeNone, NULL); + JSStringRelease(js_className); + + return true; +} + +bool JS_registerNamespace(JSGlobalContextRef context, + JSObjectRef namespaceObj, JSObjectRef parentNamespace, + const char* name) +{ + JSStringRef js_name = JSStringCreateWithUTF8CString(name); + JSObjectSetProperty(context, parentNamespace, + js_name, namespaceObj, + kJSPropertyAttributeNone, NULL); + JSStringRelease(js_name); + + return true; +} + + +bool JS_registerFunction(JSGlobalContextRef context, JSObjectRef object, + const char* functionName, JSObjectCallAsFunctionCallback callback) +{ + JSStringRef js_functionName = JSStringCreateWithUTF8CString(functionName); + JSObjectSetProperty(context, object, js_functionName, + JSObjectMakeFunctionWithCallback(context, js_functionName, callback), + kJSPropertyAttributeNone, NULL); + JSStringRelease(js_functionName); + return true; +} + +bool JS_veto_set_variable(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) +{ + char buffer[256]; + char msg[512]; + int res; + + JSStringGetUTF8CString(propertyName, buffer, 256); + res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); + + if(res<0) { + SWIG_exception(SWIG_ERROR, "Tried to write read-only variable."); + } else { + SWIG_exception(SWIG_ERROR, msg); + } + + return false; +} + +JSValueRef JS_CharPtrToJSValue(JSContextRef context, char* cstr) { + JSValueRef val; + + JSStringRef jsstring = JSStringCreateWithUTF8CString((char*) cstr); + val = JSValueMakeString(context, jsstring); + JSStringRelease(jsstring); + + return val; +} +%} diff --git a/Lib/javascript/jsc/javascriptinit.swg b/Lib/javascript/jsc/javascriptinit.swg new file mode 100644 index 000000000..a32ba336c --- /dev/null +++ b/Lib/javascript/jsc/javascriptinit.swg @@ -0,0 +1,67 @@ +%insert(init) %{ +SWIGRUNTIME void +SWIG_JSC_SetModule(swig_module_info *swig_module) {} + +SWIGRUNTIME swig_module_info * +SWIG_JSC_GetModule(void) { + return 0; +} + +#define SWIG_GetModule(clientdata) SWIG_JSC_GetModule() +#define SWIG_SetModule(clientdata, pointer) SWIG_JSC_SetModule(pointer) +%} + +%insert(init) "swiginit.swg" + +%fragment ("js_initializer_define", "templates") %{ +#define SWIGJSC_INIT $jsname_initialize +%} + +// Open the initializer function +%insert(init) +%{ + +#ifdef __cplusplus +extern "C" { +#endif + +bool SWIGJSC_INIT (JSGlobalContextRef context, JSObjectRef *exports) { + SWIG_InitializeModule(0); +%} + +/* ----------------------------------------------------------------------------- + * js_initializer: template for the module initializer function + * - $jsname: module name + * - $jscreatenamespaces: part with code for creating namespace objects + * - $jscreateclasses: part with code for creating classes + * - $jsregisternamespaces: part with code for registration of namespaces + * ----------------------------------------------------------------------------- */ +%fragment ("js_initializer", "templates") %{ + /* Initialize the base swig type object */ + _SwigObject_objectDefinition.staticFunctions = _SwigObject_functions; + _SwigObject_objectDefinition.staticValues = _SwigObject_values; + _SwigObject_classRef = JSClassCreate(&_SwigObject_objectDefinition); + + /* Initialize the PackedData class */ + _SwigPackedData_objectDefinition.staticFunctions = _SwigPackedData_functions; + _SwigPackedData_objectDefinition.staticValues = _SwigPackedData_values; + _SwigPackedData_objectDefinition.finalize = _wrap_SwigPackedData_delete; + _SwigPackedData_classRef = JSClassCreate(&_SwigPackedData_objectDefinition); + + /* Create objects for namespaces */ + $jscreatenamespaces + + /* Register classes */ + $jsregisterclasses + + /* Register namespaces */ + $jsregisternamespaces + + *exports = exports_object; + + return true; +} +#ifdef __cplusplus +} +#endif +%} diff --git a/Lib/javascript/jsc/javascriptkw.swg b/Lib/javascript/jsc/javascriptkw.swg new file mode 100644 index 000000000..c3c118391 --- /dev/null +++ b/Lib/javascript/jsc/javascriptkw.swg @@ -0,0 +1,40 @@ +#ifndef JAVASCRIPT_JAVASCRIPTKW_SWG_ +#define JAVASCRIPT_JAVASCRIPTKW_SWG_ + +/* Warnings for Java keywords */ +#define JAVASCRIPTKW(x) %keywordwarn("'" `x` "' is a javascript keyword, renaming to '_"`x`"'",rename="_%s") `x` + +/* Taken from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Reserved_Words */ + +JAVASCRIPTKW(break); +JAVASCRIPTKW(case); +JAVASCRIPTKW(catch); +JAVASCRIPTKW(continue); +JAVASCRIPTKW(default); +JAVASCRIPTKW(delete); +JAVASCRIPTKW(do); +JAVASCRIPTKW(else); +JAVASCRIPTKW(finally); +JAVASCRIPTKW(for); +JAVASCRIPTKW(function); +JAVASCRIPTKW(if); +JAVASCRIPTKW(in); +JAVASCRIPTKW(instanceof); +JAVASCRIPTKW(new); +JAVASCRIPTKW(return); +JAVASCRIPTKW(switch); +JAVASCRIPTKW(this); +JAVASCRIPTKW(throw); +JAVASCRIPTKW(try); +JAVASCRIPTKW(typeof); +JAVASCRIPTKW(var); +JAVASCRIPTKW(void); +JAVASCRIPTKW(while); +JAVASCRIPTKW(with); + +/* others bad names if any*/ +// for example %namewarn("321:clone() is a javascript bad method name") *::clone(); + +#undef JAVASCRIPTKW + +#endif //JAVASCRIPT_JAVASCRIPTKW_SWG_ diff --git a/Lib/javascript/jsc/javascriptprimtypes.swg b/Lib/javascript/jsc/javascriptprimtypes.swg new file mode 100644 index 000000000..7e9898a24 --- /dev/null +++ b/Lib/javascript/jsc/javascriptprimtypes.swg @@ -0,0 +1,182 @@ +/* ------------------------------------------------------------ + * Primitive Types + * ------------------------------------------------------------ */ + +/* boolean */ + +%fragment(SWIG_From_frag(bool),"header") { +SWIGINTERNINLINE +JSValueRef SWIG_From_dec(bool)(bool value) +{ + return JSValueMakeBoolean(context, value); +} +} + +%fragment(SWIG_AsVal_frag(bool),"header", + fragment=SWIG_AsVal_frag(long)) { +SWIGINTERN +int SWIG_AsVal_dec(bool)(JSValueRef obj, bool *val) +{ + if(!JSValueIsBoolean(context, obj)) { + return SWIG_ERROR; + } + if (val) *val = JSValueToBoolean(context, obj); + return SWIG_OK; +} +} + +/* int */ + +%fragment(SWIG_From_frag(int),"header") { +SWIGINTERNINLINE JSValueRef + SWIG_From_dec(int)(int value) +{ + return JSValueMakeNumber(context, value); +} +} + +/* long */ + +%fragment(SWIG_From_frag(long),"header") { +SWIGINTERNINLINE JSValueRef +SWIG_From_dec(long)(long value) +{ + return JSValueMakeNumber(context, value); +} +} + +%fragment(SWIG_AsVal_frag(long),"header", + fragment="SWIG_CanCastAsInteger") { +SWIGINTERN int +SWIG_AsVal_dec(long)(JSValueRef obj, long* val) +{ + if (!JSValueIsNumber(context, obj)) { + return SWIG_TypeError; + } + if(val) *val = (long) JSValueToNumber(context, obj, NULL); + + return SWIG_OK; +} +} + +/* unsigned long */ + +%fragment(SWIG_From_frag(unsigned long),"header", + fragment=SWIG_From_frag(long)) { +SWIGINTERNINLINE JSValueRef +SWIG_From_dec(unsigned long)(unsigned long value) +{ + return (value > LONG_MAX) ? + JSValueMakeNumber(context, value) : JSValueMakeNumber(context, %numeric_cast(value,long)); +} +} + +%fragment(SWIG_AsVal_frag(unsigned long),"header", + fragment="SWIG_CanCastAsInteger") { +SWIGINTERN int +SWIG_AsVal_dec(unsigned long)(JSValueRef obj, unsigned long *val) +{ + if(!JSValueIsNumber(context, obj)) { + return SWIG_TypeError; + } + + long longVal = (long) JSValueToNumber(context, obj, NULL); + + if(longVal < 0) { + return SWIG_OverflowError; + } + + if(val) *val = longVal; + + return SWIG_OK; +} +} + +/* long long */ +// Note: these are copied from 'long' and probably need fixing + +%fragment(SWIG_From_frag(long long),"header", + fragment=SWIG_From_frag(long), + fragment="") { +SWIGINTERNINLINE JSValueRef +SWIG_From_dec(long long)(long long value) +{ + return JSValueMakeNumber(context, value); +} +} + +%fragment(SWIG_AsVal_frag(long long),"header", + fragment=SWIG_AsVal_frag(long), + fragment="SWIG_CanCastAsInteger", + fragment="") { +SWIGINTERN int +SWIG_AsVal_dec(long long)(JSValueRef obj, long long* val) +{ + if (!JSValueIsNumber(context, obj)) { + return SWIG_TypeError; + } + if(val) *val = (long long) JSValueToNumber(context, obj, NULL); + + return SWIG_OK; +} +} + +/* unsigned long long */ +// Note: these are copied from 'unsigned long' and probably need fixing + +%fragment(SWIG_From_frag(unsigned long long),"header", + fragment=SWIG_From_frag(long long), + fragment="") { +SWIGINTERN JSValueRef +SWIG_From_dec(unsigned long long)(unsigned long long value) +{ + return (value > LONG_MAX) ? + JSValueMakeNumber(context, value) : JSValueMakeNumber(context, %numeric_cast(value,long)); +} +} + +%fragment(SWIG_AsVal_frag(unsigned long long),"header", + fragment=SWIG_AsVal_frag(unsigned long), + fragment="SWIG_CanCastAsInteger", + fragment="") { +SWIGINTERN int +SWIG_AsVal_dec(unsigned long long)(JSValueRef obj, unsigned long long *val) +{ + if(!JSValueIsNumber(context, obj)) { + return SWIG_TypeError; + } + + long long longVal = (unsigned long long) JSValueToNumber(context, obj, NULL); + + if(longVal < 0) { + return SWIG_OverflowError; + } + + if(val) *val = longVal; + + return SWIG_OK; +} +} + +/* double */ + +%fragment(SWIG_From_frag(double),"header") { +SWIGINTERN JSValueRef +SWIG_From_dec(double) (double val) +{ + return JSValueMakeNumber(context, val); +} +} + +%fragment(SWIG_AsVal_frag(double),"header") { +SWIGINTERN int +SWIG_AsVal_dec(double)(JSValueRef obj, double *val) +{ + if(!JSValueIsNumber(context, obj)) { + return SWIG_TypeError; + } + if(val) *val = JSValueToNumber(context, obj, NULL); + + return SWIG_OK; +} +} diff --git a/Lib/javascript/jsc/javascriptrun.swg b/Lib/javascript/jsc/javascriptrun.swg new file mode 100644 index 000000000..3463d2351 --- /dev/null +++ b/Lib/javascript/jsc/javascriptrun.swg @@ -0,0 +1,298 @@ +/* ---------------------------------------------------------------------------- + * Errors and exceptions + * + * ---------------------------------------------------------------------------*/ + +#define SWIG_Error(code, msg) SWIG_JSC_exception(context, exception, code, msg) +#define SWIG_exception(code, msg) SWIG_JSC_exception(context, exception, code, msg) +#define SWIG_fail goto fail + +void SWIG_Javascript_Raise(JSContextRef context, JSValueRef *exception, const char* type) { + JSStringRef message = JSStringCreateWithUTF8CString(type); + *exception = JSValueMakeString(context, message); + JSStringRelease(message); +} + +void SWIG_JSC_exception(JSContextRef context, JSValueRef *exception, int code, const char* msg) { + SWIG_Javascript_Raise(context, exception, msg); +} + +/* ---------------------------------------------------------------------------- + * The parent class of all Proxies + * + * ---------------------------------------------------------------------------*/ + +typedef struct { + bool swigCMemOwn; + void *swigCObject; + swig_type_info *info; +} SwigPrivData; + +JSValueRef _wrap_SwigObject_disown(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + JSValueRef jsresult; + + JSObjectRef obj = JSValueToObject(context, thisObject, NULL); + SwigPrivData *cdata = (SwigPrivData *) JSObjectGetPrivate(obj); + + cdata->swigCMemOwn = false; + + jsresult = JSValueMakeUndefined(context); + return jsresult; +} + +JSValueRef _wrap_SwigObject_getCPtr(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + JSValueRef jsresult; + long result; + + JSObjectRef obj = JSValueToObject(context, thisObject, NULL); + SwigPrivData *cdata = (SwigPrivData*) JSObjectGetPrivate(obj); + + result = (long) cdata->swigCObject; + jsresult = JSValueMakeNumber(context, result); + + return jsresult; +} + +JSValueRef _wrap_SwigObject_equals(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + JSValueRef jsresult; + bool result; + + JSObjectRef obj = JSValueToObject(context, thisObject, NULL); + SwigPrivData *cdata = (SwigPrivData*) JSObjectGetPrivate(obj); + + JSObjectRef obj2 = JSValueToObject(context, argv[0], NULL); + SwigPrivData *cdata2 = (SwigPrivData*) JSObjectGetPrivate(obj2); + + result = (cdata->swigCObject == cdata2->swigCObject); + jsresult = JSValueMakeBoolean(context, result); + + return jsresult; +} + +JSStaticValue _SwigObject_values[] = { + { + 0, 0, 0, 0 + } +}; + +JSStaticFunction _SwigObject_functions[] = { + { + "disown",_wrap_SwigObject_disown, kJSPropertyAttributeNone + }, + { + "equals",_wrap_SwigObject_equals, kJSPropertyAttributeNone + }, + { + "getCPtr",_wrap_SwigObject_getCPtr, kJSPropertyAttributeNone + }, + { + 0, 0, 0 + } +}; + +JSClassDefinition _SwigObject_objectDefinition; + +JSClassRef _SwigObject_classRef; + + +int SWIG_JSC_ConvertInstancePtr(JSContextRef context, JSObjectRef objRef, void** ptr, swig_type_info *info, int flags) { + SwigPrivData *cdata = (SwigPrivData *) JSObjectGetPrivate(objRef); + if(cdata == NULL) { + return SWIG_ERROR; + } + if(cdata->info != info) { + bool type_valid = false; + swig_cast_info *t = info->cast; + while(t != NULL) { + if(t->type == cdata->info) { + type_valid = true; + break; + } + t = t->next; + } + if(!type_valid) { + return SWIG_TypeError; + } + } + + *ptr = cdata->swigCObject; + + if(flags & SWIG_POINTER_DISOWN) { + cdata->swigCMemOwn = false; + } + + return SWIG_OK; +} + +int SWIG_JSC_ConvertPtr(JSContextRef context, JSValueRef valRef, void** ptr, swig_type_info *info, int flags) { + if(!JSValueIsObject(context, valRef)) { + return SWIG_TypeError; + } + + JSObjectRef objRef = JSValueToObject(context, valRef, NULL); + if(objRef == NULL) { + return SWIG_ERROR; + } + + return SWIG_JSC_ConvertInstancePtr(context, objRef, ptr, info, flags); +} + +JSObjectRef SWIG_JSC_NewPointerObj(JSContextRef context, void *ptr, swig_type_info *info, int flags) { + + JSClassRef classRef; + if(info->clientdata == NULL) { + classRef = _SwigObject_classRef; + } else { + classRef = (JSClassRef) info->clientdata; + } + + JSObjectRef result = JSObjectMake(context, classRef, NULL); + + SwigPrivData* cdata = (SwigPrivData*) malloc(sizeof(SwigPrivData)); + cdata->swigCObject = ptr; + cdata->swigCMemOwn = (flags & SWIG_POINTER_OWN) ? 1 : 0; + cdata->info = info; + + JSObjectSetPrivate(result, cdata); + + return result; +} + +#define SWIG_ConvertPtr(obj, ptr, info, flags) SWIG_JSC_ConvertPtr(context, obj, ptr, info, flags) +#define SWIG_NewPointerObj(ptr, info, flags) SWIG_JSC_NewPointerObj(context, ptr, info, flags) + +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_JSC_ConvertInstancePtr(context, obj, pptr, type, flags) +#define SWIG_NewInstanceObj(thisvalue, type, flags) SWIG_JSC_NewPointerObj(context, thisvalue, type, flags) + +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_JSC_ConvertPtr(context, obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_JSC_NewPointerObj(context, ptr, type, 0) + +/* ---------------------------------------------------------------------------- + * A class for packed data + * + * ---------------------------------------------------------------------------*/ + +typedef struct { + void *data; + size_t size; + swig_type_info *type; +} SwigPackedData; + +JSStaticValue _SwigPackedData_values[] = { + { + 0, 0, 0, 0 + } +}; +JSStaticFunction _SwigPackedData_functions[] = { + { + 0, 0, 0 + } +}; +JSClassDefinition _SwigPackedData_objectDefinition; +JSClassRef _SwigPackedData_classRef; + +SWIGRUNTIMEINLINE +int SwigJSCPacked_Check(JSContextRef context, JSValueRef valRef) { + return JSValueIsObjectOfClass(context, valRef, _SwigPackedData_classRef); +} + +SWIGRUNTIME +swig_type_info* SwigJSCPacked_UnpackData(JSContextRef context, JSValueRef valRef, void *ptr, size_t size) { + if (SwigJSCPacked_Check(context, valRef)) { + JSObjectRef objRef = JSValueToObject(context, valRef, NULL); + SwigPackedData *sobj = (SwigPackedData *) JSObjectGetPrivate(objRef); + if (sobj->size != size) return 0; + memcpy(ptr, sobj->data, size); + return sobj->type; + } else { + return 0; + } +} + +SWIGRUNTIME +int SWIG_JSC_ConvertPacked(JSContextRef context, JSValueRef valRef, void *ptr, size_t sz, swig_type_info *ty) { + swig_type_info *to = SwigJSCPacked_UnpackData(context, valRef, 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; +} + +SWIGRUNTIME +JSValueRef SWIG_JSC_NewPackedObj(JSContextRef context, void *data, size_t size, swig_type_info *type) { + + JSClassRef classRef = _SwigObject_classRef; + JSObjectRef result = JSObjectMake(context, classRef, NULL); + + SwigPackedData* cdata = (SwigPackedData*) malloc(sizeof(SwigPackedData)); + cdata->data = data; + cdata->size = size; + cdata->type = type; + + JSObjectSetPrivate(result, cdata); + + return result; +} + +/* SwigPackedData wrappers */ + +void _wrap_SwigPackedData_delete(JSObjectRef obj) +{ + SwigPackedData* cdata = (SwigPackedData*) JSObjectGetPrivate(obj); + if (cdata) { + free(cdata->data); + } +} + +/* for C++ member pointers, ie, member methods */ + +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_JSC_ConvertPacked(context, obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_JSC_NewPackedObj(context, ptr, sz, type) + + +/* --------------------------------------------------------------------------- + * Support for IN/OUTPUT typemaps (see Lib/typemaps/inoutlist.swg) + * + * ---------------------------------------------------------------------------*/ + +unsigned int SWIGJSC_ArrayLength(JSContextRef context, JSObjectRef arr) { + static JSStringRef LENGTH = 0; + JSValueRef exception = NULL; + JSValueRef js_length; + double length; + + if (LENGTH == 0) { + LENGTH = JSStringCreateWithUTF8CString("length"); + } + + js_length = JSObjectGetProperty(context, arr, LENGTH, &exception); + if (exception == 0 && JSValueIsNumber(context, js_length)) { + length = JSValueToNumber(context, js_length, 0); + return (unsigned int) length; + } else { + return 0; + } +} + +SWIGRUNTIME +JSValueRef SWIGJSC_AppendOutput(JSContextRef context, JSValueRef value, JSValueRef obj) { + JSObjectRef arr; + unsigned int length; + + if (JSValueIsUndefined(context, value)) { + arr = JSObjectMakeArray(context, 0, 0, 0); + } else { + arr = JSValueToObject(context, value, 0); + } + + length = SWIGJSC_ArrayLength(context, arr); + JSObjectSetPropertyAtIndex(context, arr, length, obj, 0); +} diff --git a/Lib/javascript/jsc/javascriptruntime.swg b/Lib/javascript/jsc/javascriptruntime.swg new file mode 100644 index 000000000..8f8390890 --- /dev/null +++ b/Lib/javascript/jsc/javascriptruntime.swg @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * javascriptruntime.swg + * + * Javascript support code + * ----------------------------------------------------------------------------- */ + +%insert(runtime) %{ +#include +#include +#include +#include +#include +#include +%} + +%insert(runtime) "swigrun.swg"; /* SWIG API */ +%insert(runtime) "swigerrors.swg"; /* SWIG errors */ + +%insert(runtime) "javascriptrun.swg"; /* SWIG errors */ diff --git a/Lib/javascript/jsc/javascriptstrings.swg b/Lib/javascript/jsc/javascriptstrings.swg new file mode 100644 index 000000000..26908d9da --- /dev/null +++ b/Lib/javascript/jsc/javascriptstrings.swg @@ -0,0 +1,182 @@ +/* ------------------------------------------------------------ + * utility methods for char strings + * ------------------------------------------------------------ */ +%fragment("SWIG_AsCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") { +SWIGINTERN int +SWIG_JSC_AsCharPtrAndSize(JSContextRef context, JSValueRef valRef, char** cptr, size_t* psize, int *alloc) +{ + if(JSValueIsString(context, valRef)) { + JSStringRef js_str = JSValueToStringCopy(context, valRef, NULL); + size_t len = JSStringGetMaximumUTF8CStringSize(js_str); + char* cstr = (char*) malloc(len * sizeof(char)); + /* JSStringGetUTF8CString returns the length including 0-terminator */ + len = JSStringGetUTF8CString(js_str, cstr, len); + + if(alloc) *alloc = SWIG_NEWOBJ; + if(psize) *psize = len; + if(cptr) *cptr = cstr; + + return SWIG_OK; + } else { + if(JSValueIsObject(context, valRef)) { + JSObjectRef obj = JSValueToObject(context, valRef, NULL); + // try if the object is a wrapped char[] + 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; + } else { + return SWIG_TypeError; + } + } +} +} + +%fragment("SWIG_FromCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") { +SWIGINTERNINLINE JSValueRef +SWIG_JSC_FromCharPtrAndSize(JSContextRef context, const char* carray, size_t size) +{ + if (carray) { + if (size > INT_MAX) { + // TODO: handle extra long strings + //swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + //return pchar_descriptor ? + // SWIG_InternalNewPointerObj(%const_cast(carray,char *), pchar_descriptor, 0) : SWIG_Py_Void(); + return JSValueMakeUndefined(context); + } else { + JSStringRef jsstring; + if(size < 2) { + char c[size+1]; + int i; + for(i=0;i + +/* Look for user fragments file. */ +%include + +/* Javascript fragments for fundamental types */ +%include + +/* Javascript fragments for char* strings */ +%include + +/* ------------------------------------------------------------ + * Unified typemap section + * ------------------------------------------------------------ */ + +#define SWIG_Object JSValueRef +#define VOID_Object JSValueMakeUndefined(context) + +/* append output */ +#define SWIG_AppendOutput(result, obj) SWIGJSC_AppendOutput(context, result, obj) + +/* set constant */ +#define SWIG_SetConstant(name, obj) + +/* raise */ +#define SWIG_Raise(obj, type, desc) SWIG_Javascript_Raise(context, exception, type) + +%insert("runtime") %{ +#define SWIG_JSC_FROM_DECL_ARGS(arg1) (JSContextRef context, arg1) +#define SWIG_JSC_FROM_CALL_ARGS(arg1) (context, arg1) +#define SWIG_JSC_AS_DECL_ARGS(arg1, arg2) (JSContextRef context, arg1, arg2) +#define SWIG_JSC_AS_CALL_ARGS(arg1, arg2) (context, arg1, arg2) +%} + +/* Include the unified typemap library */ +%include diff --git a/Lib/javascript/jsc/std_common.i b/Lib/javascript/jsc/std_common.i new file mode 100755 index 000000000..cee11e8ca --- /dev/null +++ b/Lib/javascript/jsc/std_common.i @@ -0,0 +1,5 @@ +%include + +%apply size_t { std::size_t }; +%apply const size_t& { const std::size_t& }; + diff --git a/Lib/javascript/jsc/std_complex.i b/Lib/javascript/jsc/std_complex.i new file mode 100644 index 000000000..088a4fe7b --- /dev/null +++ b/Lib/javascript/jsc/std_complex.i @@ -0,0 +1,19 @@ +/* + * STD C++ complex typemaps + */ + +%include + +%{ +#include +%} + +/* defining the complex as/from converters */ + +%swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) +%swig_cplxflt_convn(std::complex, std::complex, std::real, std::imag) + +/* defining the typemaps */ + +%typemaps_primitive(%checkcode(CPLXDBL), std::complex); +%typemaps_primitive(%checkcode(CPLXFLT), std::complex); diff --git a/Lib/javascript/jsc/std_deque.i b/Lib/javascript/jsc/std_deque.i new file mode 100644 index 000000000..cb98f6c2f --- /dev/null +++ b/Lib/javascript/jsc/std_deque.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/jsc/std_except.i b/Lib/javascript/jsc/std_except.i new file mode 100644 index 000000000..af98428f6 --- /dev/null +++ b/Lib/javascript/jsc/std_except.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/jsc/std_map.i b/Lib/javascript/jsc/std_map.i new file mode 100755 index 000000000..e7812f38a --- /dev/null +++ b/Lib/javascript/jsc/std_map.i @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------- + * std_map.i + * + * SWIG typemaps for std::map + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::map +// ------------------------------------------------------------------------ + +%{ +#include +#include +#include +%} + +// exported class + +namespace std { + + template class map { + // add typemaps here + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + map(); + map(const map &); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map::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) { + (*self)[key] = x; + } + void del(const K& key) throw (std::out_of_range) { + std::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 K& key) { + std::map::iterator i = self->find(key); + return i != self->end(); + } + } + }; + +// Legacy macros (deprecated) +%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) +#warning "specialize_std_map_on_key ignored - macro is deprecated and no longer necessary" +%enddef + +%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) +#warning "specialize_std_map_on_value ignored - macro is deprecated and no longer necessary" +%enddef + +%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) +#warning "specialize_std_map_on_both ignored - macro is deprecated and no longer necessary" +%enddef + +} diff --git a/Lib/javascript/jsc/std_pair.i b/Lib/javascript/jsc/std_pair.i new file mode 100755 index 000000000..fe45ee676 --- /dev/null +++ b/Lib/javascript/jsc/std_pair.i @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------------- + * std_pair.i + * + * SWIG typemaps for std::pair + * ----------------------------------------------------------------------------- */ + +%include +%include + +// ------------------------------------------------------------------------ +// std::pair +// ------------------------------------------------------------------------ + +%{ +#include +%} + +namespace std { + + template struct pair { + + pair(); + pair(T first, U second); + pair(const pair& p); + + template pair(const pair &p); + + T first; + U second; + }; + + // add specializations here + +} diff --git a/Lib/javascript/jsc/std_string.i b/Lib/javascript/jsc/std_string.i new file mode 100755 index 000000000..fb1bd62b5 --- /dev/null +++ b/Lib/javascript/jsc/std_string.i @@ -0,0 +1,69 @@ +/* ----------------------------------------------------------------------------- + * std_string.i + * + * Typemaps for const std::string&. + * To use non-const std::string references use the following %apply: + * %apply const std::string & {std::string &}; + * + * ----------------------------------------------------------------------------- */ + +%{ +#include + +std::string SWIGJSC_valueToString(JSContextRef context, JSValueRef value) { + JSStringRef jsstring = JSValueToStringCopy(context, value, /* JSValueRef *exception */ 0); + unsigned int length = JSStringGetLength(jsstring); + char *cstr = new char[length + 1]; + JSStringGetUTF8CString(jsstring, cstr, length + 1); + + // create a copy + std::string result(cstr); + + JSStringRelease(jsstring); + delete[] cstr; + + return result; +} + +JSValueRef SWIGJSC_stringToValue(JSContextRef context, const std::string& s) +{ + JSValueRef result; + JSStringRef jsstring = JSStringCreateWithUTF8CString(s.c_str()); + result = JSValueMakeString(context, jsstring); + JSStringRelease(jsstring); + return result; +} +%} + +namespace std { + %naturalvar string; + + class string; + + + %typemap(in) string + %{ + $1 = SWIGJSC_valueToString(context, $input); + %} + + %typemap(in) const string & + %{ + $1 = new std::string(SWIGJSC_valueToString(context, $input)); + %} + + %typemap(freearg) const string & + %{ + delete $1; + %} + + %typemap(out) string + %{ + $result = SWIGJSC_stringToValue(context, $1); + %} + + %typemap(out) const string & + %{ + $result = SWIGJSC_stringToValue(context, *$1); + %} + +} diff --git a/Lib/javascript/jsc/std_vector.i b/Lib/javascript/jsc/std_vector.i new file mode 100755 index 000000000..3f29b19c7 --- /dev/null +++ b/Lib/javascript/jsc/std_vector.i @@ -0,0 +1,85 @@ +/* ----------------------------------------------------------------------------- + * std_vector.i + * ----------------------------------------------------------------------------- */ + +%include + +%{ +#include +#include +%} + +namespace std { + + template class vector { + public: + typedef size_t size_type; + typedef T value_type; + typedef const value_type& const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %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 && isize()); + if (i>=0 && i class vector { + public: + typedef size_t size_type; + typedef bool value_type; + typedef bool const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %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 && isize()); + if (i>=0 && i +%include +%include +%include +%include + diff --git a/Lib/javascript/jsc/typemaps.i b/Lib/javascript/jsc/typemaps.i new file mode 100644 index 000000000..d3d8afb19 --- /dev/null +++ b/Lib/javascript/jsc/typemaps.i @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- + * 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 + double fadd(double *INPUT, double *INPUT); + +or you can use the %apply directive : + + %include + %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).K: + + double modf(double x, double *ip); + +You could wrap it with SWIG as follows : + + %include + double modf(double x, double *OUTPUT); + +or you can use the %apply directive : + + %include + %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 + void neg(double *INOUT); + +or you can use the %apply directive : + + %include + %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) + +Note : previous versions of SWIG used the symbol 'BOTH' to mark +input/output arguments. This is still supported, but will be slowly +phased out in future releases. + +*/ + +%include diff --git a/Lib/javascript/v8/arrays_javascript.i b/Lib/javascript/v8/arrays_javascript.i new file mode 100644 index 000000000..22b50be8f --- /dev/null +++ b/Lib/javascript/v8/arrays_javascript.i @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------- + * arrays_javascript.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 JavaScript and vice versa. The JavaScript array is expected to be the same size as the C array. + * An exception is thrown if they are not. + * + * Example usage: + * Wrapping: + * + * %include + * %inline %{ + * extern int FiddleSticks[3]; + * %} + * + * Use from JavaScript like this: + * + * var fs = [10, 11, 12]; + * example.FiddleSticks = fs; + * fs = example.FiddleSticks; + * ----------------------------------------------------------------------------- */ + +%fragment("SWIG_JSCGetIntProperty", "header", fragment=SWIG_AsVal_frag(int)) {} +%fragment("SWIG_JSCGetNumberProperty", "header", fragment=SWIG_AsVal_frag(double)) {} + +%typemap(in, fragment="SWIG_JSCGetIntProperty") int[], int[ANY] + (int length = 0, v8::Local array, v8::Local jsvalue, int i = 0, int res = 0, $*1_ltype temp) { + if ($input->IsArray()) + { + // Convert into Array + array = v8::Local::Cast($input); + + length = $1_dim0; + + $1 = ($*1_ltype *)malloc(sizeof($*1_ltype) * length); + + // Get each element from array + for (i = 0; i < length; i++) + { + jsvalue = array->Get(i); + + // Get primitive value from JSObject + res = SWIG_AsVal(int)(jsvalue, &temp); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ERROR, "Failed to convert $input to double"); + } + arg$argnum[i] = temp; + } + + } + else + { + SWIG_exception_fail(SWIG_ERROR, "$input is not JSObjectRef"); + } +} + +%typemap(freearg) int[], int[ANY] { + free($1); +} + +%typemap(out, fragment=SWIG_From_frag(int)) int[], int[ANY] (int length = 0, int i = 0) +{ + length = $1_dim0; + v8::Local array = v8::Array::New(length); + + for (i = 0; i < length; i++) + { + array->Set(i, SWIG_From(int)($1[i])); + } + + + $result = array; +} + +%typemap(in, fragment="SWIG_JSCGetNumberProperty") double[], double[ANY] + (int length = 0, v8::Local array, v8::Local jsvalue, int i = 0, int res = 0, $*1_ltype temp) { + if ($input->IsArray()) + { + // Convert into Array + array = v8::Local::Cast($input); + + length = $1_dim0; + + $1 = ($*1_ltype *)malloc(sizeof($*1_ltype) * length); + + // Get each element from array + for (i = 0; i < length; i++) + { + jsvalue = array->Get(i); + + // Get primitive value from JSObject + res = SWIG_AsVal(double)(jsvalue, &temp); + if (!SWIG_IsOK(res)) + { + SWIG_exception_fail(SWIG_ERROR, "Failed to convert $input to double"); + } + arg$argnum[i] = temp; + } + + } + else + { + SWIG_exception_fail(SWIG_ERROR, "$input is not JSObjectRef"); + } +} + +%typemap(freearg) double[], double[ANY] { + free($1); +} + +%typemap(out, fragment=SWIG_From_frag(double)) double[], double[ANY] (int length = 0, int i = 0) +{ + length = $1_dim0; + v8::Local array = v8::Array::New(length); + + for (i = 0; i < length; i++) + { + array->Set(i, SWIG_From(double)($1[i])); + } + + + $result = array; +} diff --git a/Lib/javascript/v8/ccomplex.i b/Lib/javascript/v8/ccomplex.i new file mode 100644 index 000000000..8eda920bb --- /dev/null +++ b/Lib/javascript/v8/ccomplex.i @@ -0,0 +1,26 @@ +/* ----------------------------------------------------------------------------- + * ccomplex.i + * + * C complex typemaps + * ISO C99: 7.3 Complex arithmetic + * ----------------------------------------------------------------------------- */ + + +%include + +%{ +#include +%} + + +/* 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/Lib/javascript/v8/cdata.i b/Lib/javascript/v8/cdata.i new file mode 100644 index 000000000..367965990 --- /dev/null +++ b/Lib/javascript/v8/cdata.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/v8/complex.i b/Lib/javascript/v8/complex.i new file mode 100644 index 000000000..4c3b3c5e2 --- /dev/null +++ b/Lib/javascript/v8/complex.i @@ -0,0 +1,6 @@ +#ifdef __cplusplus +%include +#else +%include +#endif + diff --git a/Lib/javascript/v8/exception.i b/Lib/javascript/v8/exception.i new file mode 100644 index 000000000..0246cfde8 --- /dev/null +++ b/Lib/javascript/v8/exception.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/v8/javascript.swg b/Lib/javascript/v8/javascript.swg new file mode 100644 index 000000000..3a83b6495 --- /dev/null +++ b/Lib/javascript/v8/javascript.swg @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * javascript.swg + * + * Javascript typemaps + * ----------------------------------------------------------------------------- */ + +%include + +%include + +%include + +%include + +%include + +%include + +%include diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg new file mode 100644 index 000000000..9bcb33176 --- /dev/null +++ b/Lib/javascript/v8/javascriptcode.swg @@ -0,0 +1,468 @@ +/* ----------------------------------------------------------------------------- + * js_ctor: template for wrapping a ctor. + * - $jswrapper: wrapper of called ctor + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * - $jsargcount: number of arguments + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ + +%fragment("js_ctor", "templates") %{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args) { + v8::HandleScope scope; + v8::Handle self = args.Holder(); + $jslocals + if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + $jscode + + SWIGV8_SetPrivateData(self, result, SWIGTYPE_$jsmangledtype, SWIG_POINTER_OWN); + SWIGV8_RETURN(self); + + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_veto_ctor: a vetoing ctor for abstract classes + * - $jswrapper: name of wrapper + * - $jsname: class name + * ----------------------------------------------------------------------------- */ +%fragment ("js_veto_ctor", "templates") +%{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args) { + v8::HandleScope scope; + SWIG_exception(SWIG_ERROR, "Class $jsname can not be instantiated"); + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_ctor_dispatcher: dispatcher for overloaded constructors + * - $jswrapper: name of wrapper + * - $jsname: class name + * - $jsdispatchcases: part containing code for dispatching + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor_dispatcher", "templates") +%{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args) { + v8::HandleScope scope; + OverloadErrorHandler errorHandler; + v8::Handle self; + + // switch all cases by means of series of if-returns. + $jsdispatchcases + + // default: + SWIG_exception_fail(SWIG_ERROR, "Illegal arguments for contruction of $jsmangledname"); + +fail: + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_overloaded_ctor: template for wrapping a ctor. + * - $jswrapper: wrapper of called ctor + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * - $jsargcount: number of arguments + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ +%fragment("js_overloaded_ctor", "templates") %{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args, V8ErrorHandler& SWIGV8_ErrorHandler) { + v8::HandleScope scope; + v8::Handle self = args.Holder(); + $jslocals + if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + $jscode + + SWIGV8_SetPrivateData(self, result, SWIGTYPE_$jsmangledtype, SWIG_POINTER_OWN); + SWIGV8_RETURN(self); + + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_ctor_dispatch_case: template for a dispatch case for calling an overloaded ctor. + * - $jsargcount: number of arguments of called ctor + * - $jswrapper: wrapper of called ctor + * + * Note: a try-catch-like mechanism is used to switch cases + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor_dispatch_case", "templates") +%{ + if(args.Length() == $jsargcount) { + errorHandler.err.Clear(); +#if SWIG_V8_VERSION < 0x031900 + self = $jswrapper(args, errorHandler); + if(errorHandler.err.IsEmpty()) { + return scope.Close(self); + } +#else + $jswrapper(args, errorHandler); + if(errorHandler.err.IsEmpty()) { + return; + } +#endif + } +%} + +/* ----------------------------------------------------------------------------- + * js_dtor: template for a destructor wrapper + * - $jsmangledname: mangled class name + * - $jstype: class type + * ----------------------------------------------------------------------------- */ +%fragment ("js_dtor", "templates") +%{ + +#if (SWIG_V8_VERSION < 0x031900) +void $jswrapper(v8::Persistent< v8::Value > object, void *parameter) +{ + SWIGV8_Proxy *proxy = static_cast(parameter); +#else +void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object > * object, SWIGV8_Proxy *proxy) +{ +#endif + + if(proxy->swigCMemOwn && proxy->swigCObject) { +#ifdef SWIGRUNTIME_DEBUG + printf("Deleting wrapped instance: %s\n", proxy->info->name); +#endif + $jsfree proxy->swigCObject; + } + delete proxy; + + object.Clear(); +#if (SWIG_V8_VERSION < 0x031900) + object.Dispose(); +#elif (SWIG_V8_VERSION < 0x032100) + object->Dispose(isolate); +#else + object->Dispose(); +#endif +} +%} + +/* ----------------------------------------------------------------------------- + * js_dtoroverride: template for a destructor wrapper + * - $jsmangledname: mangled class name + * - $jstype: class type + * - ${destructor_action}: The custom destructor action to invoke. + * ----------------------------------------------------------------------------- */ +%fragment ("js_dtoroverride", "templates") +%{ +#if (SWIG_V8_VERSION < 0x031900) +void $jswrapper(v8::Persistent< v8::Value > object, void *parameter) +{ + SWIGV8_Proxy *proxy = static_cast(parameter); +#else +void $jswrapper(v8::Isolate *isolate, v8::Persistent< v8::Object > * object, SWIGV8_Proxy *proxy) +{ +#endif + if(proxy->swigCMemOwn && proxy->swigCObject) { + $jstype arg1 = ($jstype)proxy->swigCObject; + ${destructor_action} + } + delete proxy; + +#if (SWIG_V8_VERSION < 0x031900) + object.Dispose(); +#elif (SWIG_V8_VERSION < 0x032100) + object->Dispose(isolate); +#else + object->Dispose(); +#endif +} +%} + +/* ----------------------------------------------------------------------------- + * js_getter: template for getter function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_getter", "templates") +%{ +SwigV8ReturnValue $jswrapper(v8::Local property, const SwigV8PropertyCallbackInfo& info) { + v8::HandleScope scope; + v8::Handle jsresult; + $jslocals + $jscode + SWIGV8_RETURN_INFO(jsresult, info); + + goto fail; +fail: + SWIGV8_RETURN_INFO(v8::Undefined(), info); +} +%} + +/* ----------------------------------------------------------------------------- + * js_setter: template for setter function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_setter", "templates") +%{ +void $jswrapper(v8::Local property, v8::Local value, + const SwigV8PropertyCallbackInfoVoid& info) { + v8::HandleScope scope; + $jslocals + $jscode + goto fail; +fail: + return; +} +%} + +/* ----------------------------------------------------------------------------- + * js_function: template for function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_function", "templates") +%{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args) { + v8::HandleScope scope; + v8::Handle jsresult; + $jslocals + if(args.Length() != $jsargcount) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + + $jscode + SWIGV8_RETURN(jsresult); + + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_function_dispatcher: template for a function dispatcher for overloaded functions + * - $jswrapper: wrapper function name + * - $jsname: name of the wrapped function + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_function_dispatcher", "templates") +%{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args) { + v8::HandleScope scope; + v8::Handle jsresult; + OverloadErrorHandler errorHandler; + $jscode + + SWIG_exception_fail(SWIG_ERROR, "Illegal arguments for function $jsname."); + + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_overloaded_function: template for a overloaded function + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_overloaded_function", "templates") +%{ +SwigV8ReturnValue $jswrapper(const SwigV8Arguments& args, V8ErrorHandler& SWIGV8_ErrorHandler) +{ + v8::HandleScope scope; + v8::Handle jsresult; + $jslocals + $jscode + SWIGV8_RETURN(jsresult); + + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} +%} + +/* ----------------------------------------------------------------------------- + * js_function_dispatch_case: template for a case used in the function dispatcher + * - $jswrapper: wrapper function name + * - $jsargcount: number of arguments of overloaded function + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_function_dispatch_case", "templates") +%{ + + if(args.Length() == $jsargcount) { + errorHandler.err.Clear(); +#if (SWIG_V8_VERSION < 0x031900) + jsresult = $jswrapper(args, errorHandler); + if(errorHandler.err.IsEmpty()) { + return scope.Close(jsresult); + } +#else + $jswrapper(args, errorHandler); + if(errorHandler.err.IsEmpty()) { + return; + } +#endif + } +%} + +/* ----------------------------------------------------------------------------- + * jsv8_declare_class_template: template for a class template declaration. + * - $jsmangledname: mangled class name + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_declare_class_template", "templates") +%{ + SWIGV8_ClientData $jsmangledname_clientData; +%} + +/* ----------------------------------------------------------------------------- + * jsv8_define_class_template: template for a class template definition. + * - $jsmangledname: mangled class name + * - $jsmangledtype: mangled class type + * - $jsdtor: the dtor wrapper + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_define_class_template", "templates") +%{ + v8::Handle $jsmangledname_class = SWIGV8_CreateClassTemplate("$jsmangledname"); +#if (SWIG_V8_VERSION < 0x031900) + $jsmangledname_clientData.class_templ = v8::Persistent::New($jsmangledname_class); +#else + $jsmangledname_clientData.class_templ.Reset(v8::Isolate::GetCurrent(), $jsmangledname_class); +#endif + $jsmangledname_clientData.dtor = $jsdtor; + if (SWIGTYPE_$jsmangledtype->clientdata == 0) { + SWIGTYPE_$jsmangledtype->clientdata = &$jsmangledname_clientData; + } +%} + + +/* ----------------------------------------------------------------------------- + * jsv8_inherit: template for an class inherit statement. + * - $jsmangledname: mangled class name + * - $jsbaseclass: mangled name of the base class + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_inherit", "templates") +%{ + if (SWIGTYPE_p$jsbaseclass->clientdata && !(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ.IsEmpty())) + { +#if (SWIG_V8_VERSION < 0x031900) + $jsmangledname_class->Inherit(static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ); +#else + $jsmangledname_class->Inherit( + v8::Handle::New( + v8::Isolate::GetCurrent(), + static_cast(SWIGTYPE_p$jsbaseclass->clientdata)->class_templ) + ); +#endif + +#ifdef SWIGRUNTIME_DEBUG + printf("Inheritance successful $jsmangledname $jsbaseclass\n"); +#endif + } else { +#ifdef SWIGRUNTIME_DEBUG + printf("Unable to inherit baseclass, it didn't exist $jsmangledname $jsbaseclass\n"); +#endif + } +%} + +/* ----------------------------------------------------------------------------- + * jsv8_create_class_instance: template for creating an class object. + * - $jsname: class name + * - $jsmangledname: mangled class name + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_create_class_instance", "templates") +%{ + v8::Handle $jsmangledname_class_0 = SWIGV8_CreateClassTemplate("$jsname"); + $jsmangledname_class_0->SetCallHandler($jsctor); + $jsmangledname_class_0->Inherit($jsmangledname_class); + $jsmangledname_class_0->SetHiddenPrototype(true); + v8::Handle $jsmangledname_obj = $jsmangledname_class_0->GetFunction(); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_register_class: template for a statement that registers a class in a parent namespace. + * - $jsname: class name + * - $jsmangledname: mangled class name + * - $jsparent: mangled name of parent namespace + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_register_class", "templates") +%{ + $jsparent_obj->Set(v8::String::NewSymbol("$jsname"), $jsmangledname_obj); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_create_namespace: template for a statement that creates a namespace object. + * - $jsmangledname: mangled namespace name + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_create_namespace", "templates") +%{ + v8::Handle $jsmangledname_obj = v8::Object::New(); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_register_namespace: template for a statement that registers a namespace in a parent namespace. + * - $jsname: name of namespace + * - $jsmangledname: mangled name of namespace + * - $jsparent: mangled name of parent namespace + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_register_namespace", "templates") +%{ + $jsparent_obj->Set(v8::String::NewSymbol("$jsname"), $jsmangledname_obj); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_register_member_function: template for a statement that registers a member function. + * - $jsmangledname: mangled class name + * - $jsname: name of the function + * - $jswrapper: wrapper of the member function + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_register_member_function", "templates") +%{ + SWIGV8_AddMemberFunction($jsmangledname_class, "$jsname", $jswrapper); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_register_member_variable: template for a statement that registers a member variable. + * - $jsmangledname: mangled class name + * - $jsname: name of the function + * - $jsgetter: wrapper of the getter function + * - $jssetter: wrapper of the setter function + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_register_member_variable", "templates") +%{ + SWIGV8_AddMemberVariable($jsmangledname_class, "$jsname", $jsgetter, $jssetter); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_register_static_function: template for a statement that registers a static class function. + * - $jsname: function name + * - $jswrapper: wrapper of the function + * - $jsparent: mangled name of parent namespace + * + * Note: this template is also used for global functions. + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_register_static_function", "templates") +%{ + SWIGV8_AddStaticFunction($jsparent_obj, "$jsname", $jswrapper); +%} + +/* ----------------------------------------------------------------------------- + * jsv8_register_static_variable: template for a statement that registers a static variable. + * - $jsname: variable name + * - $jsparent: mangled name of parent namespace + * - $jsgetter: wrapper of the getter function + * - $jssetter: wrapper of the setter function + * + * Note: this template is also used for global variables. + * ----------------------------------------------------------------------------- */ +%fragment("jsv8_register_static_variable", "templates") +%{ + SWIGV8_AddStaticVariable($jsparent_obj, "$jsname", $jsgetter, $jssetter); +%} diff --git a/Lib/javascript/v8/javascriptcomplex.swg b/Lib/javascript/v8/javascriptcomplex.swg new file mode 100644 index 000000000..70c5baffb --- /dev/null +++ b/Lib/javascript/v8/javascriptcomplex.swg @@ -0,0 +1,123 @@ +/* + 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 concret examples. +*/ + +/* the common from converter */ +%define %swig_fromcplx_conv(Type, Real, Imag) +%fragment(SWIG_From_frag(Type),"header", + fragment=SWIG_From_frag(double)) +{ +SWIGINTERNINLINE v8::Handle +SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) +{ + v8::HandleScope scope; + v8::Local vals = v8::Array::New(2); + + vals->Set(0, SWIG_From(double)(Real(c))); + vals->Set(1, SWIG_From(double)(Imag(c))); + return scope.Close(vals); +} +} +%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_dec(Type) (v8::Handle o, Type* val) +{ + v8::HandleScope scope; + + if (o->IsArray()) { + v8::Handle array = v8::Handle::Cast(o); + + if(array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2]."); + double re, im; + int res; + + res = SWIG_AsVal(double)(array->Get(0), &re); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + res = SWIG_AsVal(double)(array->Get(1), &im); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + if (val) *val = Constructor(re, im); + return SWIG_OK; + } else if(o->IsNumber()){ + 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_dec(Type) (v8::Handle o, Type* val) +{ + v8::HandleScope scope; + + if (o->IsArray()) { + v8::Handle array = v8::Handle::Cast(o); + + if(array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2]."); + double re, im; + int res; + + res = SWIG_AsVal(double)(array->Get(0), &re); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + res = SWIG_AsVal(double)(array->Get(1), &im); + if(!SWIG_IsOK(res)) { + return SWIG_TypeError; + } + + 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 if(o->IsNumber()){ + float re; + int res = SWIG_AddCast(SWIG_AsVal(float)(o, &re)); + if (SWIG_IsOK(res)) { + if (val) *val = Constructor(re, 0.0); + 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/Lib/javascript/v8/javascriptfragments.swg b/Lib/javascript/v8/javascriptfragments.swg new file mode 100644 index 000000000..4778bf033 --- /dev/null +++ b/Lib/javascript/v8/javascriptfragments.swg @@ -0,0 +1,23 @@ +/* + + Create a file with this name, 'javascriptfragments.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) + { + ; + } + } + + this will replace the code used to retrieve an integer value for all + the typemaps that need it, including: + + int, std::vector, std::list >, etc. + + +*/ diff --git a/Lib/javascript/v8/javascripthelpers.swg b/Lib/javascript/v8/javascripthelpers.swg new file mode 100644 index 000000000..8da6627e2 --- /dev/null +++ b/Lib/javascript/v8/javascripthelpers.swg @@ -0,0 +1,87 @@ +%insert(runtime) %{ + +// Note: since 3.19 there are new CallBack types, since 03.21.9 the old ones have been removed +#if SWIG_V8_VERSION < 0x031900 +typedef v8::InvocationCallback SwigV8FunctionCallback; +typedef v8::AccessorGetter SwigV8AccessorGetterCallback; +typedef v8::AccessorSetter SwigV8AccessorSetterCallback; +typedef v8::AccessorInfo SwigV8PropertyCallbackInfoVoid; +#else +typedef v8::FunctionCallback SwigV8FunctionCallback; +typedef v8::AccessorGetterCallback SwigV8AccessorGetterCallback; +typedef v8::AccessorSetterCallback SwigV8AccessorSetterCallback; +typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfoVoid; +#endif + +/** + * Creates a class template for a class with specified initialization function. + */ +v8::Handle SWIGV8_CreateClassTemplate(const char* symbol) { + v8::HandleScope scope; + v8::Local class_templ = v8::FunctionTemplate::New(); + class_templ->SetClassName(v8::String::NewSymbol(symbol)); + + v8::Handle inst_templ = class_templ->InstanceTemplate(); + inst_templ->SetInternalFieldCount(1); + + v8::Handle equals_templ = class_templ->PrototypeTemplate(); + equals_templ->Set(v8::String::NewSymbol("equals"), v8::FunctionTemplate::New(_SWIGV8_wrap_equals)); + + v8::Handle cptr_templ = class_templ->PrototypeTemplate(); + cptr_templ->Set(v8::String::NewSymbol("getCPtr"), v8::FunctionTemplate::New(_wrap_getCPtr)); + + return scope.Close(class_templ); +} + +/** + * Registers a class method with given name for a given class template. + */ +void SWIGV8_AddMemberFunction(v8::Handle class_templ, const char* symbol, + SwigV8FunctionCallback _func) { + v8::Handle proto_templ = class_templ->PrototypeTemplate(); + proto_templ->Set(v8::String::NewSymbol(symbol), v8::FunctionTemplate::New(_func)); +} + +/** + * Registers a class property with given name for a given class template. + */ +void SWIGV8_AddMemberVariable(v8::Handle class_templ, const char* symbol, + SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) { + v8::Handle proto_templ = class_templ->InstanceTemplate(); + proto_templ->SetAccessor(v8::String::NewSymbol(symbol), getter, setter); +} + +/** + * Registers a class method with given name for a given object. + */ +void SWIGV8_AddStaticFunction(v8::Handle obj, const char* symbol, + const SwigV8FunctionCallback& _func) { + obj->Set(v8::String::NewSymbol(symbol), v8::FunctionTemplate::New(_func)->GetFunction()); +} + +/** + * Registers a class method with given name for a given object. + */ +void SWIGV8_AddStaticVariable(v8::Handle obj, const char* symbol, + SwigV8AccessorGetterCallback getter, SwigV8AccessorSetterCallback setter) { + obj->SetAccessor(v8::String::NewSymbol(symbol), getter, setter); +} + +void JS_veto_set_variable(v8::Local property, v8::Local value, + const SwigV8PropertyCallbackInfoVoid& info) +{ + char buffer[256]; + char msg[512]; + int res; + + property->WriteUtf8(buffer, 256); + res = sprintf(msg, "Tried to write read-only variable: %s.", buffer); + + if(res<0) { + SWIG_exception(SWIG_ERROR, "Tried to write read-only variable."); + } else { + SWIG_exception(SWIG_ERROR, msg); + } +} + +%} // v8_helper_functions diff --git a/Lib/javascript/v8/javascriptinit.swg b/Lib/javascript/v8/javascriptinit.swg new file mode 100644 index 000000000..de1fe91f4 --- /dev/null +++ b/Lib/javascript/v8/javascriptinit.swg @@ -0,0 +1,118 @@ +%insert(init) %{ + +#include + +SWIGRUNTIME void +SWIG_V8_SetModule(void *, swig_module_info *swig_module) { + v8::Local global_obj = v8::Context::GetCurrent()->Global(); + v8::Local mod = v8::External::New(swig_module); + assert(!mod.IsEmpty()); + global_obj->SetHiddenValue(v8::String::New("swig_module_info_data"), mod); +} + +SWIGRUNTIME swig_module_info * +SWIG_V8_GetModule(void *) { + v8::Local global_obj = v8::Context::GetCurrent()->Global(); + v8::Local moduleinfo = global_obj->GetHiddenValue(v8::String::New("swig_module_info_data")); + + if (moduleinfo.IsEmpty()) + { + // It's not yet loaded + return 0; + } + + v8::Local moduleinfo_extern = v8::Local::Cast(moduleinfo); + + if (moduleinfo_extern.IsEmpty()) + { + // Something's not right + return 0; + } + + void *ptr = moduleinfo_extern->Value(); + assert(ptr); + swig_module_info *retptr = static_cast(ptr); + assert(retptr); + return retptr; +} + +#define SWIG_GetModule(clientdata) SWIG_V8_GetModule(clientdata) +#define SWIG_SetModule(clientdata, pointer) SWIG_V8_SetModule(clientdata, pointer) + +%} + +%insert(init) "swiginit.swg" + +// Open the initializer function definition here + +%fragment ("js_initializer_define", "templates") %{ +#define SWIGV8_INIT $jsname_initialize +%} + +%insert(init) %{ +// Note: 'extern "C"'' disables name mangling which makes it easier to load the symbol manually +// TODO: is it ok to do that? +extern "C" +#if (NODE_MODULE_VERSION < 0x000C) +void SWIGV8_INIT (v8::Handle exports) +#else +void SWIGV8_INIT (v8::Handle exports, v8::Handle /*module*/) +#endif +{ + SWIG_InitializeModule(static_cast(&exports)); + + v8::HandleScope scope; + v8::Handle exports_obj = exports; +%} + + +/* ----------------------------------------------------------------------------- + * js_initializer: template for the module initializer function + * - $jsname: module name + * - $jsv8nspaces: part with code creating namespace objects + * - $jsv8classtemplates: part with code creating class templates + * - $jsv8wrappers: part with code that registers wrapper functions + * - $jsv8inheritance: part with inherit statements + * - $jsv8classinstances: part with code creating class objects + * - $jsv8staticwrappers: part with code adding static functions to class objects + * - $jsv8registerclasses: part with code that registers class objects in namespaces + * - $jsv8registernspaces: part with code that registers namespaces in parent namespaces + * ----------------------------------------------------------------------------- */ +%fragment("js_initializer", "templates") +%{ + // a class template for creating proxies of undefined types +#if (SWIG_V8_VERSION < 0x031900) + SWIGV8_SWIGTYPE_Proxy_class_templ = v8::Persistent::New(SWIGV8_CreateClassTemplate("SwigProxy")); +#else + SWIGV8_SWIGTYPE_Proxy_class_templ.Reset(v8::Isolate::GetCurrent(), SWIGV8_CreateClassTemplate("SwigProxy")); +#endif + + /* create objects for namespaces */ + $jsv8nspaces + + /* create class templates */ + $jsv8classtemplates + + /* register wrapper functions */ + $jsv8wrappers + + /* setup inheritances */ + $jsv8inheritance + + /* class instances */ + $jsv8classinstances + + /* add static class functions and variables */ + $jsv8staticwrappers + + /* register classes */ + $jsv8registerclasses + + /* create and register namespace objects */ + $jsv8registernspaces +} + +#if defined(BUILDING_NODE_EXTENSION) +NODE_MODULE($jsname, $jsname_initialize); +#endif +%} diff --git a/Lib/javascript/v8/javascriptkw.swg b/Lib/javascript/v8/javascriptkw.swg new file mode 100644 index 000000000..c3c118391 --- /dev/null +++ b/Lib/javascript/v8/javascriptkw.swg @@ -0,0 +1,40 @@ +#ifndef JAVASCRIPT_JAVASCRIPTKW_SWG_ +#define JAVASCRIPT_JAVASCRIPTKW_SWG_ + +/* Warnings for Java keywords */ +#define JAVASCRIPTKW(x) %keywordwarn("'" `x` "' is a javascript keyword, renaming to '_"`x`"'",rename="_%s") `x` + +/* Taken from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Reserved_Words */ + +JAVASCRIPTKW(break); +JAVASCRIPTKW(case); +JAVASCRIPTKW(catch); +JAVASCRIPTKW(continue); +JAVASCRIPTKW(default); +JAVASCRIPTKW(delete); +JAVASCRIPTKW(do); +JAVASCRIPTKW(else); +JAVASCRIPTKW(finally); +JAVASCRIPTKW(for); +JAVASCRIPTKW(function); +JAVASCRIPTKW(if); +JAVASCRIPTKW(in); +JAVASCRIPTKW(instanceof); +JAVASCRIPTKW(new); +JAVASCRIPTKW(return); +JAVASCRIPTKW(switch); +JAVASCRIPTKW(this); +JAVASCRIPTKW(throw); +JAVASCRIPTKW(try); +JAVASCRIPTKW(typeof); +JAVASCRIPTKW(var); +JAVASCRIPTKW(void); +JAVASCRIPTKW(while); +JAVASCRIPTKW(with); + +/* others bad names if any*/ +// for example %namewarn("321:clone() is a javascript bad method name") *::clone(); + +#undef JAVASCRIPTKW + +#endif //JAVASCRIPT_JAVASCRIPTKW_SWG_ diff --git a/Lib/javascript/v8/javascriptprimtypes.swg b/Lib/javascript/v8/javascriptprimtypes.swg new file mode 100644 index 000000000..706a799b7 --- /dev/null +++ b/Lib/javascript/v8/javascriptprimtypes.swg @@ -0,0 +1,198 @@ +/* ------------------------------------------------------------ + * Primitive Types + * ------------------------------------------------------------ */ + +/* boolean */ + +%fragment(SWIG_From_frag(bool),"header") { +SWIGINTERNINLINE +v8::Handle +SWIG_From_dec(bool)(bool value) +{ + return v8::Boolean::New(value); +} +} + +%fragment(SWIG_AsVal_frag(bool),"header", + fragment=SWIG_AsVal_frag(long)) { +SWIGINTERN +int SWIG_AsVal_dec(bool)(v8::Handle obj, bool *val) +{ + if(!obj->IsBoolean()) { + return SWIG_ERROR; + } + + if (val) *val = obj->BooleanValue(); + return SWIG_OK; +} +} + +/* int */ + +%fragment(SWIG_From_frag(int),"header") { +SWIGINTERNINLINE +v8::Handle SWIG_From_dec(int)(int value) +{ + return v8::Int32::New(value); +} +} + +%fragment(SWIG_AsVal_frag(int),"header") { +SWIGINTERN +int SWIG_AsVal_dec(int)(v8::Handle valRef, int* val) +{ + if (!valRef->IsNumber()) { + return SWIG_TypeError; + } + if(val) *val = valRef->IntegerValue(); + + return SWIG_OK; +} +} + +/* long */ + +%fragment(SWIG_From_frag(long),"header") { +SWIGINTERNINLINE +v8::Handle SWIG_From_dec(long)(long value) +{ + return v8::Number::New(value); +} +} + +%fragment(SWIG_AsVal_frag(long),"header", + fragment="SWIG_CanCastAsInteger") { +SWIGINTERN +int SWIG_AsVal_dec(long)(v8::Handle obj, long* val) +{ + if (!obj->IsNumber()) { + return SWIG_TypeError; + } + if(val) *val = (long) obj->IntegerValue(); + + return SWIG_OK; +} +} + +/* unsigned long */ + +%fragment(SWIG_From_frag(unsigned long),"header", + fragment=SWIG_From_frag(long)) { +SWIGINTERNINLINE +v8::Handle SWIG_From_dec(unsigned long)(unsigned long value) +{ + return (value > LONG_MAX) ? + v8::Integer::NewFromUnsigned(value) : v8::Integer::New(%numeric_cast(value,long)); +} +} + +%fragment(SWIG_AsVal_frag(unsigned long),"header", + fragment="SWIG_CanCastAsInteger") { +SWIGINTERN +int SWIG_AsVal_dec(unsigned long)(v8::Handle obj, unsigned long *val) +{ + if(!obj->IsNumber()) { + return SWIG_TypeError; + } + + long longVal = (long) obj->NumberValue(); + + if(longVal < 0) { + return SWIG_OverflowError; + } + + if(val) *val = longVal; + + return SWIG_OK; +} +} + +/* long long */ +// Note: these are copied from 'long' and probably need fixing + +%fragment(SWIG_From_frag(long long),"header", + fragment=SWIG_From_frag(long), + fragment="") { +SWIGINTERNINLINE +v8::Handle SWIG_From_dec(long long)(long long value) +{ + return v8::Number::New(value); +} +} + +%fragment(SWIG_AsVal_frag(long long),"header", + fragment=SWIG_AsVal_frag(long), + fragment="SWIG_CanCastAsInteger", + fragment="") { +SWIGINTERN +int SWIG_AsVal_dec(long long)(v8::Handle obj, long long* val) +{ + if (!obj->IsNumber()) { + return SWIG_TypeError; + } + if(val) *val = (long long) obj->IntegerValue(); + + return SWIG_OK; +} +} + +/* unsigned long long */ +// Note: these are copied from 'unsigned long' and probably need fixing + +%fragment(SWIG_From_frag(unsigned long long),"header", + fragment=SWIG_From_frag(long long), + fragment="") { +SWIGINTERNINLINE +v8::Handle SWIG_From_dec(unsigned long long)(unsigned long long value) +{ + return (value > LONG_MAX) ? + v8::Integer::NewFromUnsigned(value) : v8::Integer::New(%numeric_cast(value,long)); +} +} + +%fragment(SWIG_AsVal_frag(unsigned long long),"header", + fragment=SWIG_AsVal_frag(unsigned long), + fragment="SWIG_CanCastAsInteger", + fragment="") { +SWIGINTERN +int SWIG_AsVal_dec(unsigned long long)(v8::Handle obj, unsigned long long *val) +{ + if(!obj->IsNumber()) { + return SWIG_TypeError; + } + + long long longVal = (long long) obj->NumberValue(); + + if(longVal < 0) { + return SWIG_OverflowError; + } + + if(val) *val = longVal; + + return SWIG_OK; +} +} + +/* double */ + +%fragment(SWIG_From_frag(double),"header") { +SWIGINTERN +v8::Handle SWIG_From_dec(double) (double val) +{ + return v8::Number::New(val); +} +} + +%fragment(SWIG_AsVal_frag(double),"header") { +SWIGINTERN +int SWIG_AsVal_dec(double)(v8::Handle obj, double *val) +{ + if(!obj->IsNumber()) { + return SWIG_TypeError; + } + if(val) *val = obj->NumberValue(); + + return SWIG_OK; +} +} + diff --git a/Lib/javascript/v8/javascriptrun.swg b/Lib/javascript/v8/javascriptrun.swg new file mode 100644 index 000000000..2e0a46717 --- /dev/null +++ b/Lib/javascript/v8/javascriptrun.swg @@ -0,0 +1,462 @@ +/* --------------------------------------------------------------------------- + * Error handling + * + * ---------------------------------------------------------------------------*/ + +#define SWIG_Error(code, msg) SWIGV8_ErrorHandler.error(code, msg) +#define SWIG_exception(code, msg) SWIGV8_ErrorHandler.error(code, msg) +#define SWIG_fail goto fail +#define SWIGV8_OVERLOAD false + +void SWIG_V8_Raise(const char* msg) { + v8::ThrowException(v8::Exception::Error(v8::String::New(msg))); +} + +/* + Note: There are two contexts for handling errors. + A static V8ErrorHandler is used in not overloaded methods. + For overloaded methods the throwing type checking mechanism is used + during dispatching. As V8 exceptions can not be resetted properly + the trick is to use a dynamic ErrorHandler with same local name as the global + one. + + - See defintion of SWIG_Error above. + - See code templates 'JS_function_dispatcher', 'JS_functionwrapper_overload', + and 'JS_function_dispatch_case' in javascriptcode.swg + +*/ +class V8ErrorHandler { +public: + virtual ~V8ErrorHandler() {} + virtual void error(int code, const char* msg) { + SWIG_V8_Raise(msg); + } +}; +// this is used in usually +V8ErrorHandler SWIGV8_ErrorHandler; + +// instances of this are used in overloaded functions +class OverloadErrorHandler: public V8ErrorHandler { +public: + virtual void error(int code, const char* msg) { + err = v8::Exception::Error(v8::String::New(msg)); + if(code != SWIG_TypeError) { + v8::ThrowException(err); + } + } + v8::Handle err; +}; + +// Note: these typedefs and defines are used to deal with v8 API changes since version 3.19.00 + +#if (SWIG_V8_VERSION < 0x031900) +typedef v8::Handle SwigV8ReturnValue; +typedef v8::Arguments SwigV8Arguments; +typedef v8::AccessorInfo SwigV8PropertyCallbackInfo; +#define SWIGV8_RETURN(val) return scope.Close(val) +#define SWIGV8_RETURN_INFO(val, info) return scope.Close(val) +#else +typedef void SwigV8ReturnValue; +typedef v8::FunctionCallbackInfo SwigV8Arguments; +typedef v8::PropertyCallbackInfo SwigV8PropertyCallbackInfo; +#define SWIGV8_RETURN(val) args.GetReturnValue().Set(val); return +#define SWIGV8_RETURN_INFO(val, info) info.GetReturnValue().Set(val); return +#endif + + +/* --------------------------------------------------------------------------- + * Basic Proxy object + * + * ---------------------------------------------------------------------------*/ + +// Note: to trigger the v8 gc more often one can tell v8 about the memory consumption +// TODO: we could add a v8 specific parameter to control this value +#define SWIGV8_AVG_OBJ_SIZE 1000 + +class SWIGV8_Proxy { +public: + SWIGV8_Proxy(): swigCMemOwn(false), swigCObject(0), info(0) { + v8::V8::AdjustAmountOfExternalAllocatedMemory(SWIGV8_AVG_OBJ_SIZE); + }; + + ~SWIGV8_Proxy() { +#if (SWIG_V8_VERSION < 0x031900 || SWIG_V8_VERSION >= 0x032100) + handle.ClearWeak(); + handle.Dispose(); +#else + handle.ClearWeak(v8::Isolate::GetCurrent()); + handle.Dispose(v8::Isolate::GetCurrent()); +#endif + + handle.Clear(); + v8::V8::AdjustAmountOfExternalAllocatedMemory(-SWIGV8_AVG_OBJ_SIZE); + } + + bool swigCMemOwn; + void *swigCObject; + swig_type_info *info; + v8::Persistent handle; +}; + +class SWIGV8_ClientData { +public: + v8::Persistent class_templ; + +#if (SWIG_V8_VERSION < 0x031900) + void (*dtor) (v8::Persistent< v8::Value> object, void *parameter); +#else + void (*dtor) (v8::Isolate *isolate, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy); +#endif +}; + +v8::Persistent SWIGV8_SWIGTYPE_Proxy_class_templ; + +int SWIG_V8_ConvertInstancePtr(v8::Handle objRef, void** ptr, swig_type_info *info, int flags) { + v8::HandleScope scope; + + if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; + +#if (SWIG_V8_VERSION < 0x031900) + v8::Handle cdataRef = objRef->GetInternalField(0); + SWIGV8_Proxy *cdata = static_cast(v8::External::Unwrap(cdataRef)); +#else + SWIGV8_Proxy *cdata = static_cast(objRef->GetAlignedPointerFromInternalField(0)); +#endif + + if(cdata == NULL) { + return SWIG_ERROR; + } + if(cdata->info != info) { + swig_cast_info *tc = SWIG_TypeCheckStruct(cdata->info, info); + if (!tc && cdata->info->name) { + tc = SWIG_TypeCheck(cdata->info->name, info); + } + bool type_valid = tc != 0; + if(!type_valid) { + return SWIG_TypeError; + } + } + *ptr = cdata->swigCObject; + if(flags & SWIG_POINTER_DISOWN) { + cdata->swigCMemOwn = false; + } + return SWIG_OK; +} + +#if (SWIG_V8_VERSION < 0x031900) +void SWIGV8_Proxy_DefaultDtor(v8::Persistent< v8::Value > object, void *parameter) +#else +void SWIGV8_Proxy_DefaultDtor(v8::Isolate *, v8::Persistent< v8::Object > *object, SWIGV8_Proxy *proxy) +#endif +{ +#if (SWIG_V8_VERSION < 0x031900) + SWIGV8_Proxy *proxy = static_cast(parameter); +#endif + + delete proxy; +} + +int SWIG_V8_GetInstancePtr(v8::Handle valRef, void** ptr) { + if(!valRef->IsObject()) { + return SWIG_TypeError; + } + v8::Handle objRef = valRef->ToObject(); + + if(objRef->InternalFieldCount() < 1) return SWIG_ERROR; + +#if (SWIG_V8_VERSION < 0x031900) + v8::Handle cdataRef = objRef->GetInternalField(0); + SWIGV8_Proxy *cdata = static_cast(v8::External::Unwrap(cdataRef)); +#else + SWIGV8_Proxy *cdata = static_cast(objRef->GetAlignedPointerFromInternalField(0)); +#endif + + if(cdata == NULL) { + return SWIG_ERROR; + } + + *ptr = cdata->swigCObject; + + return SWIG_OK; +} + +void SWIGV8_SetPrivateData(v8::Handle obj, void* ptr, swig_type_info *info, int flags) { + SWIGV8_Proxy* cdata = new SWIGV8_Proxy(); + cdata->swigCObject = ptr; + cdata->swigCMemOwn = (flags & SWIG_POINTER_OWN) ? 1 : 0; + cdata->info = info; + +#if (SWIG_V8_VERSION < 0x031900) + obj->SetPointerInInternalField(0, cdata); + cdata->handle = v8::Persistent::New(obj); +#else + obj->SetAlignedPointerInInternalField(0, cdata); + cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); +#endif + +#if (SWIG_V8_VERSION < 0x031900) + // clientdata must be set for owned data as we need to register the dtor + if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { + cdata->handle.MakeWeak(cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); + } else { + cdata->handle.MakeWeak(cdata, SWIGV8_Proxy_DefaultDtor); + } + cdata->handle.MarkIndependent(); +#else + if(cdata->swigCMemOwn && (SWIGV8_ClientData*)info->clientdata) { + cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, ((SWIGV8_ClientData*)info->clientdata)->dtor); + } else { + cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, SWIGV8_Proxy_DefaultDtor); + } + +#if (SWIG_V8_VERSION < 0x032100) + cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); +#else + cdata->handle.MarkIndependent(); +#endif + +#endif +} + +int SWIG_V8_ConvertPtr(v8::Handle valRef, void** ptr, swig_type_info *info, int flags) { + v8::HandleScope scope; + + if(!valRef->IsObject()) { + return SWIG_TypeError; + } + v8::Handle objRef = valRef->ToObject(); + return SWIG_V8_ConvertInstancePtr(objRef, ptr, info, flags); +} + +v8::Handle SWIG_V8_NewPointerObj(void *ptr, swig_type_info *info, int flags) { + v8::HandleScope scope; + v8::Handle class_templ; + +#if (SWIG_V8_VERSION < 0x031900) + if(info->clientdata != 0) { + class_templ = ((SWIGV8_ClientData*) info->clientdata)->class_templ; + } else { + class_templ = SWIGV8_SWIGTYPE_Proxy_class_templ; + } +#else + v8::Isolate *iso = v8::Isolate::GetCurrent(); + + if(info->clientdata != 0) { + class_templ = v8::Handle::New(iso, ((SWIGV8_ClientData*) info->clientdata)->class_templ); + } else { + class_templ = v8::Handle::New(iso, SWIGV8_SWIGTYPE_Proxy_class_templ); + } +#endif + + v8::Handle result = class_templ->InstanceTemplate()->NewInstance(); + SWIGV8_SetPrivateData(result, ptr, info, flags); + + return scope.Close(result); +} + +#define SWIG_ConvertPtr(obj, ptr, info, flags) SWIG_V8_ConvertPtr(obj, ptr, info, flags) +#define SWIG_NewPointerObj(ptr, info, flags) SWIG_V8_NewPointerObj(ptr, info, flags) + +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_V8_ConvertInstancePtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(thisvalue, type, flags) SWIG_V8_NewPointerObj(thisvalue, type, flags) + +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_V8_ConvertPtr(obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_V8_NewPointerObj(ptr, type, 0) + +#define SWIG_GetInstancePtr(obj, ptr) SWIG_V8_GetInstancePtr(obj, ptr) + +#if (SWIG_V8_VERSION < 0x031900) +v8::Handle _SWIGV8_wrap_equals(const v8::Arguments &args) { +#else +void _SWIGV8_wrap_equals(const v8::FunctionCallbackInfo& args) { +#endif + v8::HandleScope scope; + v8::Handle jsresult; + void *arg1 = (void *) 0 ; + void *arg2 = (void *) 0 ; + bool result; + int res1; + int res2; + + if(args.Length() != 1) SWIG_exception_fail(SWIG_ERROR, "Illegal number of arguments for equals."); + + res1 = SWIG_GetInstancePtr(args.Holder(), &arg1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ERROR, "Could not get pointer from 'this' object for equals."); + } + res2 = SWIG_GetInstancePtr(args[0], &arg2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "equals" "', argument " "1"" of type '" "void *""'"); + } + + result = (bool)(arg1 == arg2); + jsresult = v8::Boolean::New(result); + + SWIGV8_RETURN(jsresult); + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} + +#if (SWIG_V8_VERSION < 0x031900) +v8::Handle _wrap_getCPtr(const v8::Arguments &args) { +#else +void _wrap_getCPtr(const v8::FunctionCallbackInfo& args) { +#endif + v8::HandleScope scope; + v8::Handle jsresult; + void *arg1 = (void *) 0 ; + long result; + int res1; + + res1 = SWIG_GetInstancePtr(args.Holder(), &arg1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "getCPtr" "', argument " "1"" of type '" "void *""'"); + } + + result = (long)arg1; + jsresult = v8::Number::New(result); + + SWIGV8_RETURN(jsresult); + goto fail; +fail: + SWIGV8_RETURN(v8::Undefined()); +} + +/* --------------------------------------------------------------------------- + * PackedData object + * + * ---------------------------------------------------------------------------*/ + +class SwigV8PackedData { +public: + SwigV8PackedData(void *data, size_t size, swig_type_info *type): data(data), size(size), type(type) {}; + + ~SwigV8PackedData() { + }; + + void* data; + size_t size; + swig_type_info *type; + + v8::Persistent handle; +}; + +SWIGRUNTIMEINLINE +int SwigV8Packed_Check(v8::Handle valRef) { + v8::HandleScope scope; + v8::Handle objRef = valRef->ToObject(); + if(objRef->InternalFieldCount() < 1) return false; + v8::Handle flag = objRef->GetHiddenValue(v8::String::New("__swig__packed_data__")); + return (flag->IsBoolean() && flag->BooleanValue()); +} + +SWIGRUNTIME +swig_type_info* SwigV8Packed_UnpackData(v8::Handle valRef, void *ptr, size_t size) { + if (SwigV8Packed_Check(valRef)) { + v8::HandleScope scope; + SwigV8PackedData *sobj; + + v8::Handle objRef = valRef->ToObject(); + +#if (SWIG_V8_VERSION < 0x031900) + v8::Handle cdataRef = objRef->GetInternalField(0); + sobj = static_cast(v8::External::Unwrap(cdataRef)); +#else + sobj = static_cast(objRef->GetAlignedPointerFromInternalField(0)); +#endif + if (sobj == NULL || sobj->size != size) return 0; + memcpy(ptr, sobj->data, size); + return sobj->type; + } else { + return 0; + } +} + +SWIGRUNTIME +int SWIGV8_ConvertPacked(v8::Handle valRef, void *ptr, size_t sz, swig_type_info *ty) { + swig_type_info *to = SwigV8Packed_UnpackData(valRef, 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; +} + +#if (SWIG_V8_VERSION < 0x031900) +void _wrap_SwigV8PackedData_delete(v8::Persistent< v8::Value > object, void *parameter) +{ + SwigV8PackedData *cdata = static_cast(parameter); +#else +void _wrap_SwigV8PackedData_delete(v8::Isolate *isolate, v8::Persistent< v8::Object > * object, SwigV8PackedData *cdata) +{ +#endif + + delete cdata; + +#if (SWIG_V8_VERSION < 0x031900) + object.Clear(); + object.Dispose(); +#elif (SWIG_V8_VERSION < 0x032100) + object->Dispose(isolate); +#else + object->Dispose(); +#endif +} + +SWIGRUNTIME +v8::Handle SWIGV8_NewPackedObj(void *data, size_t size, swig_type_info *type) { + v8::HandleScope scope; + + SwigV8PackedData* cdata = new SwigV8PackedData(data, size, type); + v8::Handle obj = v8::Object::New(); + + obj->SetHiddenValue(v8::String::New("__swig__packed_data__"), v8::Boolean::New(true)); + +#if (SWIG_V8_VERSION < 0x031900) + obj->SetPointerInInternalField(0, cdata); + cdata->handle = v8::Persistent::New(obj); +#else + obj->SetAlignedPointerInInternalField(0, cdata); + cdata->handle.Reset(v8::Isolate::GetCurrent(), obj); +#endif + +#if (SWIG_V8_VERSION < 0x031900) + cdata->handle.MakeWeak(cdata, _wrap_SwigV8PackedData_delete); + cdata->handle.MarkIndependent(); +#else + cdata->handle.MakeWeak(v8::Isolate::GetCurrent(), cdata, _wrap_SwigV8PackedData_delete); +# if (SWIG_V8_VERSION < 0x032100) + cdata->handle.MarkIndependent(v8::Isolate::GetCurrent()); +# else + cdata->handle.MarkIndependent(); +# endif +#endif + + return scope.Close(obj); +} + +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIGV8_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIGV8_NewPackedObj(ptr, sz, type) + + +/* --------------------------------------------------------------------------- + * Support for IN/OUTPUT typemaps (see Lib/typemaps/inoutlist.swg) + * + * ---------------------------------------------------------------------------*/ + +SWIGRUNTIME +v8::Handle SWIGV8_AppendOutput(v8::Handle result, v8::Handle obj) { + v8::HandleScope scope; + if (result->IsUndefined()) { + result = v8::Array::New(); + } + v8::Handle arr = v8::Handle::Cast(result); + arr->Set(arr->Length(), obj); + + return scope.Close(arr); +} diff --git a/Lib/javascript/v8/javascriptruntime.swg b/Lib/javascript/v8/javascriptruntime.swg new file mode 100644 index 000000000..2e18d19bf --- /dev/null +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------- + * javascriptruntime.swg + * + * ----------------------------------------------------------------------------- */ + +%define %swig_v8_define_version(version) +%insert("runtime") %{ +#ifndef SWIG_V8_VERSION +#define SWIG_V8_VERSION version +#endif +%} +%enddef + +#ifdef V8_VERSION +%swig_v8_define_version(V8_VERSION) +#else +// HACK: defining a default version +%swig_v8_define_version(0x031110) +#endif + +#ifdef BUILDING_NODE_EXTENSION +%insert("runtime") %{ +#include +%} +#endif + +%insert(runtime) %{ +#include + +#include +#include +#include +%} + +%insert(runtime) "swigrun.swg"; /* SWIG API */ +%insert(runtime) "swigerrors.swg"; /* SWIG errors */ + +%insert(runtime) "javascriptrun.swg" + diff --git a/Lib/javascript/v8/javascriptstrings.swg b/Lib/javascript/v8/javascriptstrings.swg new file mode 100644 index 000000000..69b6836a8 --- /dev/null +++ b/Lib/javascript/v8/javascriptstrings.swg @@ -0,0 +1,59 @@ + +/* ------------------------------------------------------------ + * utility methods for char strings + * ------------------------------------------------------------ */ +%fragment("SWIG_AsCharPtrAndSize", "header", fragment="SWIG_pchar_descriptor") { +SWIGINTERN int +SWIG_AsCharPtrAndSize(v8::Handle valRef, char** cptr, size_t* psize, int *alloc) +{ + if(valRef->IsString()) { + v8::Handle js_str = valRef->ToString(); + + size_t len = js_str->Utf8Length() + 1; + char* cstr = new char[len]; + js_str->WriteUtf8(cstr, len); + + if(alloc) *alloc = SWIG_NEWOBJ; + if(psize) *psize = len; + if(cptr) *cptr = cstr; + + return SWIG_OK; + } else { + if(valRef->IsObject()) { + v8::Handle obj = valRef->ToObject(); + // try if the object is a wrapped char[] + 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; + } else { + return SWIG_TypeError; + } + } +} +} + +%fragment("SWIG_FromCharPtrAndSize","header",fragment="SWIG_pchar_descriptor") { +SWIGINTERNINLINE v8::Handle +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + if (carray) { + if (size > INT_MAX) { + // TODO: handle extra long strings + return v8::Undefined(); + } else { + v8::Handle js_str = v8::String::New(carray, size); + return js_str; + } + } else { + return v8::Undefined(); + } +} +} diff --git a/Lib/javascript/v8/javascripttypemaps.swg b/Lib/javascript/v8/javascripttypemaps.swg new file mode 100644 index 000000000..90317a1c7 --- /dev/null +++ b/Lib/javascript/v8/javascripttypemaps.swg @@ -0,0 +1,43 @@ +/* ------------------------------------------------------------ + * Typemap specializations for Javascript + * ------------------------------------------------------------ */ + +/* ------------------------------------------------------------ + * Fragment section + * ------------------------------------------------------------ */ + +/* Include fundamental fragemt definitions */ +%include + +/* Look for user fragments file. */ +%include + +/* Javascript fragments for fundamental types */ +%include + +/* Javascript fragments for char* strings */ +%include + + +/* ------------------------------------------------------------ + * Unified typemap section + * ------------------------------------------------------------ */ + +/* Javascript types */ + +#define SWIG_Object v8::Handle +#define VOID_Object v8::Undefined() + +/* Overload of the output/constant/exception/dirout handling */ + +/* append output */ +#define SWIG_AppendOutput(result, obj) SWIGV8_AppendOutput(result, obj) + +/* set constant */ +#define SWIG_SetConstant(name, obj) + +/* raise */ +#define SWIG_Raise(obj, type, desc) SWIG_V8_Raise(type) + +/* Include the unified typemap library */ +%include diff --git a/Lib/javascript/v8/node.i b/Lib/javascript/v8/node.i new file mode 100644 index 000000000..8bf9ef061 --- /dev/null +++ b/Lib/javascript/v8/node.i @@ -0,0 +1,12 @@ +%insert("begin") %{ +#ifndef BUILDING_NODE_EXTENSION +#define BUILDING_NODE_EXTENSION +#endif +%} + +%insert("runtime") %{ +// we are including relative to the src folder because of issues +// with other files which might be named "node.h" +#include +%} + diff --git a/Lib/javascript/v8/std_common.i b/Lib/javascript/v8/std_common.i new file mode 100755 index 000000000..cee11e8ca --- /dev/null +++ b/Lib/javascript/v8/std_common.i @@ -0,0 +1,5 @@ +%include + +%apply size_t { std::size_t }; +%apply const size_t& { const std::size_t& }; + diff --git a/Lib/javascript/v8/std_complex.i b/Lib/javascript/v8/std_complex.i new file mode 100644 index 000000000..088a4fe7b --- /dev/null +++ b/Lib/javascript/v8/std_complex.i @@ -0,0 +1,19 @@ +/* + * STD C++ complex typemaps + */ + +%include + +%{ +#include +%} + +/* defining the complex as/from converters */ + +%swig_cplxdbl_convn(std::complex, std::complex, std::real, std::imag) +%swig_cplxflt_convn(std::complex, std::complex, std::real, std::imag) + +/* defining the typemaps */ + +%typemaps_primitive(%checkcode(CPLXDBL), std::complex); +%typemaps_primitive(%checkcode(CPLXFLT), std::complex); diff --git a/Lib/javascript/v8/std_deque.i b/Lib/javascript/v8/std_deque.i new file mode 100644 index 000000000..cb98f6c2f --- /dev/null +++ b/Lib/javascript/v8/std_deque.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/v8/std_except.i b/Lib/javascript/v8/std_except.i new file mode 100644 index 000000000..af98428f6 --- /dev/null +++ b/Lib/javascript/v8/std_except.i @@ -0,0 +1 @@ +%include diff --git a/Lib/javascript/v8/std_map.i b/Lib/javascript/v8/std_map.i new file mode 100755 index 000000000..e7812f38a --- /dev/null +++ b/Lib/javascript/v8/std_map.i @@ -0,0 +1,74 @@ +/* ----------------------------------------------------------------------------- + * std_map.i + * + * SWIG typemaps for std::map + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::map +// ------------------------------------------------------------------------ + +%{ +#include +#include +#include +%} + +// exported class + +namespace std { + + template class map { + // add typemaps here + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + map(); + map(const map &); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map::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) { + (*self)[key] = x; + } + void del(const K& key) throw (std::out_of_range) { + std::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 K& key) { + std::map::iterator i = self->find(key); + return i != self->end(); + } + } + }; + +// Legacy macros (deprecated) +%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) +#warning "specialize_std_map_on_key ignored - macro is deprecated and no longer necessary" +%enddef + +%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) +#warning "specialize_std_map_on_value ignored - macro is deprecated and no longer necessary" +%enddef + +%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) +#warning "specialize_std_map_on_both ignored - macro is deprecated and no longer necessary" +%enddef + +} diff --git a/Lib/javascript/v8/std_pair.i b/Lib/javascript/v8/std_pair.i new file mode 100755 index 000000000..8d6057223 --- /dev/null +++ b/Lib/javascript/v8/std_pair.i @@ -0,0 +1,33 @@ +/* ----------------------------------------------------------------------------- + * std_pair.i + * + * SWIG typemaps for std::pair + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::pair +// ------------------------------------------------------------------------ + +%{ +#include +%} + +namespace std { + + template struct pair { + + pair(); + pair(T first, U second); + pair(const pair& p); + + template pair(const pair &p); + + T first; + U second; + }; + + // add specializations here + +} diff --git a/Lib/javascript/v8/std_string.i b/Lib/javascript/v8/std_string.i new file mode 100755 index 000000000..5ad1ead27 --- /dev/null +++ b/Lib/javascript/v8/std_string.i @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------- + * std_string.i + * + * Typemaps for std::string and const std::string&. + * + * To use non-const std::string references use the following %apply: + * %apply const std::string & {std::string &}; + * + * ----------------------------------------------------------------------------- */ + +%{ +#include +%} + +%fragment("SWIGV8_valueToString", "header", fragment="SWIG_AsCharPtrAndSize") { +std::string* SWIGV8_valueToStringPtr(v8::Handle val) { + + if (!val->IsString()) return 0; + + int alloc; + size_t size; + char* chars; + int res = SWIG_AsCharPtrAndSize(val, &chars, &size, &alloc); + + if(res != SWIG_OK) { + v8::ThrowException(v8::Exception::TypeError(v8::String::New("Could not convert to string."))); + return 0; + } + + // copies the data (again) + std::string *str = new std::string(chars); + + if (alloc) delete[] chars; + + return str; +} +} + +%fragment("SWIGV8_stringToValue", "header", fragment="SWIG_FromCharPtrAndSize") { +v8::Handle SWIGV8_stringToValue(const std::string &str) { + return SWIG_FromCharPtrAndSize(str.c_str(), str.length()); +} +} + +namespace std { + %naturalvar string; + + class string; + + %typemap(in, fragment="SWIGV8_valueToString") string (std::string* tmp) + %{ + tmp = SWIGV8_valueToStringPtr($input); + $1 = *tmp; + if (tmp == 0) { v8::ThrowException(v8::Exception::TypeError(v8::String::New("Null pointer."))); goto fail; } + if (tmp) delete tmp; + %} + + %typemap(in, fragment="SWIGV8_valueToString") const string & + %{ + $1 = SWIGV8_valueToStringPtr($input); + if ($1 == 0) { v8::ThrowException(v8::Exception::TypeError(v8::String::New("Null pointer."))); goto fail; } + %} + + %typemap(freearg) const string & + %{ + if ($1) delete $1; + %} + + %typemap(out, fragment="SWIGV8_stringToValue") string + %{ + $result = SWIGV8_stringToValue($1); + %} + + %typemap(out, fragment="SWIGV8_stringToValue") const string & + %{ + $result = SWIGV8_stringToValue(*$1); + %} + +} diff --git a/Lib/javascript/v8/std_vector.i b/Lib/javascript/v8/std_vector.i new file mode 100755 index 000000000..3f29b19c7 --- /dev/null +++ b/Lib/javascript/v8/std_vector.i @@ -0,0 +1,85 @@ +/* ----------------------------------------------------------------------------- + * std_vector.i + * ----------------------------------------------------------------------------- */ + +%include + +%{ +#include +#include +%} + +namespace std { + + template class vector { + public: + typedef size_t size_type; + typedef T value_type; + typedef const value_type& const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %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 && isize()); + if (i>=0 && i class vector { + public: + typedef size_t size_type; + typedef bool value_type; + typedef bool const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %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 && isize()); + if (i>=0 && i +%include +%include +%include +%include + diff --git a/Lib/javascript/v8/typemaps.i b/Lib/javascript/v8/typemaps.i new file mode 100644 index 000000000..d3d8afb19 --- /dev/null +++ b/Lib/javascript/v8/typemaps.i @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- + * 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 + double fadd(double *INPUT, double *INPUT); + +or you can use the %apply directive : + + %include + %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).K: + + double modf(double x, double *ip); + +You could wrap it with SWIG as follows : + + %include + double modf(double x, double *OUTPUT); + +or you can use the %apply directive : + + %include + %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 + void neg(double *INOUT); + +or you can use the %apply directive : + + %include + %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) + +Note : previous versions of SWIG used the symbol 'BOTH' to mark +input/output arguments. This is still supported, but will be slowly +phased out in future releases. + +*/ + +%include diff --git a/Lib/typemaps/strings.swg b/Lib/typemaps/strings.swg index 55e9d2bb5..eea913b60 100644 --- a/Lib/typemaps/strings.swg +++ b/Lib/typemaps/strings.swg @@ -493,7 +493,7 @@ * --- String fragment methods --- * ------------------------------------------------------------ */ - +#ifndef %_typemap2_string %define %_typemap2_string(StringCode, CharCode, Char, CharName, SWIG_AsCharPtrAndSize, @@ -593,7 +593,7 @@ SWIG_AsVal_dec(Char)(SWIG_Object obj, Char *val) SWIG_DeleteCharArray) %enddef - +#endif /* ------------------------------------------------------------ * String typemaps and fragments, with default allocators diff --git a/Makefile.in b/Makefile.in index 0ac8c88f9..323743d9f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -77,6 +77,7 @@ skip-uffi = test -n "@SKIP_UFFI@" skip-r = test -n "@SKIP_R@" skip-go = test -n "@SKIP_GO@" skip-d = test -n "@SKIP_D@" +skip-javascript = test -n "@SKIP_JAVASCRIPT@" # Additional dependencies for some tests skip-gcj = test -n "@SKIP_GCJ@" @@ -119,6 +120,7 @@ check-aliveness: @$(skip-r) || ./$(TARGET) -r -help @$(skip-go) || ./$(TARGET) -go -help @$(skip-d) || ./$(TARGET) -d -help + @$(skip-javascript)|| ./$(TARGET) -d -help check-ccache: test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) check) @@ -186,7 +188,8 @@ check-examples: \ check-cffi-examples \ check-r-examples \ check-go-examples \ - check-d-examples + check-d-examples \ + check-javascript-examples tcl_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/tcl/check.list) perl5_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/perl5/check.list) @@ -211,6 +214,7 @@ cffi_examples := r_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/r/check.list) go_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/go/check.list) d_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/d/check.list) +javascript_examples:=$(shell sed '/^\#/d' $(srcdir)/Examples/javascript/check.list) # all examples check-%-examples : @@ -263,7 +267,8 @@ check-test-suite: \ check-chicken-test-suite \ check-r-test-suite \ check-go-test-suite \ - check-d-test-suite + check-d-test-suite \ + check-javascript-test-suite check-%-test-suite: @if test -z "$(skip-$*)"; then \ @@ -315,7 +320,8 @@ all-test-suite: \ all-chicken-test-suite \ all-r-test-suite \ all-go-test-suite \ - all-d-test-suite + all-d-test-suite \ + all-javascript-test-suite all-%-test-suite: @$(MAKE) -k -s check-$*-test-suite ACTION=all @@ -343,7 +349,8 @@ broken-test-suite: \ broken-chicken-test-suite \ broken-r-test-suite \ broken-go-test-suite \ - broken-d-test-suite + broken-d-test-suite \ + broken-javascript-test-suite broken-%-test-suite: @$(MAKE) -k -s check-$*-test-suite ACTION=broken @@ -456,7 +463,8 @@ install-main: @$(INSTALL_PROGRAM) $(TARGET) $(DESTDIR)$(BIN_DIR)/`echo $(TARGET_NOEXE) | sed '$(transform)'`@EXEEXT@ lib-languages = gcj typemaps tcl perl5 python guile java mzscheme ruby php ocaml octave \ - pike chicken csharp modula3 allegrocl clisp lua cffi uffi r go d + pike chicken csharp modula3 allegrocl clisp lua cffi uffi r go d javascript javascript/jsc \ + javascript/v8 lib-modules = std diff --git a/Source/Makefile.am b/Source/Makefile.am index 984b9c268..9cd55c7dc 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -49,6 +49,7 @@ eswig_SOURCES = CParse/cscanner.c \ Modules/guile.cxx \ Modules/java.cxx \ Modules/lang.cxx \ + Modules/javascript.cxx \ Modules/lua.cxx \ Modules/main.cxx \ Modules/modula3.cxx \ diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx new file mode 100644 index 000000000..239981219 --- /dev/null +++ b/Source/Modules/javascript.cxx @@ -0,0 +1,2442 @@ +#include "swigmod.h" + +/** + * Enables extra debugging information in typemaps. + */ +bool js_template_enable_debug = false; + +// keywords used for state variables +#define NAME "name" +#define NAME_MANGLED "name_mangled" +#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 GETTER "getter" +#define SETTER "setter" +#define PARENT "parent" +#define CTOR "ctor" +#define CTOR_WRAPPERS "ctor_wrappers" +#define CTOR_DISPATCHERS "ctor_dispatchers" +#define DTOR "dtor" +#define ARGCOUNT "wrap:argc" + +/** + * 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 *global(); + + DOH *global(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 *_global; +}; + +/** + * 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(); + + 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 JSEmitterType { + JavascriptCore, + V8 + }; + + JSEmitter(); + + 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 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: + + /** + * 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 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); + + Parm *skipIgnoredArgs(Parm *p); + + virtual int createNamespace(String *scope); + + virtual Hash *createNamespaceEntry(const char *name, const char *parent); + + virtual int emitNamespaces() = 0; + + +protected: + + 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; +}; + +/********************************************************************** + * JAVASCRIPT: swig module implementation + **********************************************************************/ + +/* factory methods for concrete JSEmitters: */ + +JSEmitter *swig_javascript_create_JSCEmitter(); +JSEmitter *swig_javascript_create_V8Emitter(); + +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 void main(int argc, char *argv[]); + virtual int top(Node *n); + + /** + * Registers all %fragments assigned to section "templates". + **/ + virtual int fragmentDirective(Node *n); + +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; +} + +/* --------------------------------------------------------------------- + * 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")) { + emitter->registerTemplate(Getattr(n, "value"), Getattr(n, "code")); + } else { + Swig_fragment_register(n); + } + + return SWIG_OK; +} + +/* --------------------------------------------------------------------- + * 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; +} + +/* --------------------------------------------------------------------- + * 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 mode = -1; + + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp(argv[i], "-v8") == 0) { + Swig_mark_arg(i); + mode = JSEmitter::V8; + SWIG_library_directory("javascript/v8"); + } else if (strcmp(argv[i], "-jsc") == 0) { + Swig_mark_arg(i); + mode = JSEmitter::JavascriptCore; + SWIG_library_directory("javascript/jsc"); + } else if (strcmp(argv[i], "-debug-codetemplates") == 0) { + Swig_mark_arg(i); + js_template_enable_debug = true; + } + } + } + + switch (mode) { + case JSEmitter::V8: + { + emitter = swig_javascript_create_V8Emitter(); + Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0); + break; + } + case JSEmitter::JavascriptCore: + { + emitter = swig_javascript_create_JSCEmitter(); + Preprocessor_define("SWIG_JAVASCRIPT_JSC 1", 0); + break; + } + default: + { + Printf(stderr, "Unknown emitter type."); + SWIG_exit(-1); + break; + } + } + + // Add a symbol to the parser for conditional compilation + Preprocessor_define("SWIGJAVASCRIPT 1", 0); + + // Add typemap definitions + SWIG_typemap_lang("javascript"); + + // 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() +: 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) { + 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); + SWIG_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); + + Setattr(namespaces, "::", global_namespace); + current_namespace = global_namespace; + + f_wrappers = NewString(""); + + return SWIG_OK; +} + +/* --------------------------------------------------------------------- + * skipIgnoredArgs() + * --------------------------------------------------------------------- */ + +Parm *JSEmitter::skipIgnoredArgs(Parm *p) { + while (checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + } + return p; +} + +/* ----------------------------------------------------------------------------- + * 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 to have 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") | GetFlag(n, "feature:extend"); + bool is_static = GetFlag(state.function(), IS_STATIC); + ret = emitFunction(n, is_member, is_static); + } else if (Cmp(kind, "variable") == 0) { + bool is_static = GetFlag(state.variable(), IS_STATIC); + // HACK: smartpointeraccessed static variables are not treated as statics + if (GetFlag(n, "allocate:smartpointeraccess")) { + is_static = false; + } + bool is_setter = GetFlag(n, "wrap:issetter"); + if (is_setter) { + bool is_member = GetFlag(n, "memberset"); + ret = emitSetter(n, is_member, is_static); + } else { + bool is_member = GetFlag(n, "memberget"); + ret = emitGetter(n, is_member, is_static); + } + } else { + Printf(stderr, "Warning: unsupported wrapper function type\n"); + Swig_print_node(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"); + Swig_print_node(n); + ret = SWIG_ERROR; + } + } + + return ret; +} + +int JSEmitter::enterClass(Node *n) { + state.clazz(true); + 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(true); + 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(true); + + // 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_assignable(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; +} + +int JSEmitter::emitCtor(Node *n) { + + Wrapper *wrapper = NewWrapper(); + + bool is_overloaded = GetFlag(n, "sym:overloaded"); + + Template t_ctor(getTemplate("js_ctor")); + + //String *mangled_name = SwigType_manglestr(Getattr(n, "name")); + String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name")); + if(is_overloaded) { + t_ctor = getTemplate("js_overloaded_ctor"); + Append(wrap_name, Getattr(n, "sym:overname")); + } + Setattr(n, "wrap:name", wrap_name); + // note: removing the is_abstract flag, as this emitter + // is supposed to be 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); + // HACK: in test-case `ignore_parameter` emit_attach_parmmaps generated an extra line of applied typemap. + // Deleting wrapper->code here, to reset, and as it seemed to have no side effect elsewhere + Delete(wrapper->code); + wrapper->code = NewString(""); + + 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); + + t_ctor.replace("$jswrapper", wrap_name) + .replace("$jsmangledtype", state.clazz(TYPE_MANGLED)) + .replace("$jslocals", wrapper->locals) + .replace("$jscode", wrapper->code) + .replace("$jsargcount", Getattr(n, ARGCOUNT)) + .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)); + 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("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsdispatchcases", state.clazz(CTOR_DISPATCHERS)) + .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 *free = 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(free, "delete [] (%s)", ctype); + } else { + Printf(free, "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); + if(t) 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} + } + if(t) 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 wierd. + 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", free) + .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", free) + .replace("$jstype", ctype) + .pretty_print(f_wrappers); + } + + Delete(p_classtype); + Delete(ctype); + Delete(free); + + return SWIG_OK; +} + +int JSEmitter::emitGetter(Node *n, bool is_member, bool is_static) { + Wrapper *wrapper = NewWrapper(); + Template t_getter(getTemplate("js_getter")); + + // 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("$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("js_setter")); + + // 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("$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) { + + Wrapper *wrapper = NewWrapper(); + SwigType *type = Getattr(n, "type"); + String *name = Getattr(n, "name"); + String *iname = Getattr(n, "sym:name"); + String *wname = Swig_name_wrapper(name); + String *rawval = Getattr(n, "rawval"); + String *value = rawval ? rawval : Getattr(n, "value"); + + Template t_getter(getTemplate("js_getter")); + + // call the variable methods as a constants are + // registred 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("$jswrapper", wname) + .replace("$jslocals", wrapper->locals) + .replace("$jscode", wrapper->code) + .pretty_print(f_wrappers); + + exitVariable(n); + + DelWrapper(wrapper); + + return SWIG_OK; +} + +int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) { + Wrapper *wrapper = NewWrapper(); + Template t_function(getTemplate("js_function")); + + bool is_overloaded = GetFlag(n, "sym:overloaded"); + + // prepare the function wrapper name + String *iname = Getattr(n, "sym:name"); + String *wrap_name = Swig_name_wrapper(iname); + if (is_overloaded) { + t_function = getTemplate("js_overloaded_function"); + 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); + + // HACK: in test-case `ignore_parameter` emit_attach_parmmaps generates an extra line of applied typemap. + // Deleting wrapper->code here fixes the problem, and seems to have no side effect elsewhere + Delete(wrapper->code); + wrapper->code = NewString(""); + + marshalInputArgs(n, params, wrapper, Function, is_member, is_static); + String *action = emit_action(n); + + marshalOutput(n, params, wrapper, action); + + emitCleanupCode(n, wrapper, params); + + Replaceall(wrapper->code, "$symname", iname); + + t_function.replace("$jswrapper", wrap_name) + .replace("$jslocals", wrapper->locals) + .replace("$jscode", wrapper->code) + .replace("$jsargcount", Getattr(n, ARGCOUNT)) + .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)); + + Append(wrapper->code, t_dispatch_case.str()); + } + + } while ((sibl = Getattr(sibl, "sym:nextSibling"))); + + Template t_function(getTemplate("js_function_dispatcher")); + + // 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 + // substract the extension "sym:overname", + String *wrap_name = NewString(Getattr(n, "wrap:name")); + String *overname = Getattr(n, "sym:overname"); + int l1 = Len(wrap_name); + int l2 = Len(overname); + Delslice(wrap_name, l1-l2, l1); + + Setattr(n, "wrap:name", wrap_name); + state.function(WRAPPER_NAME, wrap_name); + + t_function.replace("$jslocals", wrapper->locals) + .replace("$jscode", wrapper->code); + + // call this here, to replace all variables + t_function.replace("$jswrapper", wrap_name) + .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) { + // Get input typemap for current param + String *tm = Getattr(p, "tmap:in"); + SwigType *type = Getattr(p, "type"); + + 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")); + Printf(wrapper->code, "%s\n", tm); + } 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 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"); + + 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); + } + } + +} + +int JSEmitter::switchNamespace(Node *n) { + // HACK: somehow this gets called when member functions are processed...ignoring + if (GetFlag(n, "ismember")) { + return SWIG_OK; + } + + String *nspace = Getattr(n, "sym:nspace"); + + // if nspace is deactivated, everything goes into the global scope + if (!GetFlag(n, "feature:nspace")) { + current_namespace = Getattr(namespaces, "::"); + return SWIG_OK; + } + + if (nspace == NULL) { + // enums and constants do not have 'sym:nspace' set + // so we try to get the namespace from the qualified name + if(Equal(Getattr(n, "nodeType"), "enumitem")) { + nspace = Swig_scopename_prefix(Getattr(n, "name")); + } + } + + 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"))); + Setattr(namespaces, scope, new_namespace); + + Delete(parent_scope); + return SWIG_OK; +} + +Hash *JSEmitter::createNamespaceEntry(const char *_name, const char *parent) { + Hash *entry = NewHash(); + String *name = NewString(_name); + Setattr(entry, NAME, Swig_scopename_last(name)); + Setattr(entry, NAME_MANGLED, Swig_name_mangle(name)); + Setattr(entry, PARENT, NewString(parent)); + + 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); + + 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; + +}; + +// 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" + +JSCEmitter::JSCEmitter() +: JSEmitter(), + 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; + + // 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); + + // process arguments + int i = 0; + for (p = parms; p; i++) { + 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); + } else { + Printf(arg, "argv[%d]", i - startIdx); + } + break; + case Setter: + if (is_member && !is_static && i == 0) { + Printv(arg, "thisObject", 0); + } else { + Printv(arg, "value", 0); + } + break; + case Ctor: + Printf(arg, "argv[%d]", i); + break; + default: + throw "Illegal state."; + } + tm = emitInputTypemap(n, p, wrapper, arg); + Delete(arg); + if (tm) { + p = Getattr(p, "tmap:in: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); + SWIG_exit(EXIT_FAILURE); + } + + /* Initialization of members */ + f_runtime = NewString(""); + f_init = NewString(""); + f_header = NewString(""); + + state.global(CREATE_NAMESPACES, NewString("")); + state.global(REGISTER_NAMESPACES, NewString("")); + state.global(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); + + return SWIG_OK; +} + +int JSCEmitter::dump(Node *n) { + /* Get the module name */ + String *module = Getattr(n, "name"); + + // write the swig banner + Swig_banner(f_wrap_cpp); + + 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.global(INITIALIZER)) + .replace("$jscreatenamespaces", state.global(CREATE_NAMESPACES)) + .replace("$jsregisternamespaces", state.global(REGISTER_NAMESPACES)) + .pretty_print(f_init); + + Printv(f_wrap_cpp, f_init, 0); + + return SWIG_OK; +} + +int JSCEmitter::close() { + /* strings */ + Delete(f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + + Delete(namespaces); + + /* files */ + Close(f_wrap_cpp); + 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") | GetFlag(n, "feature:extend"); + bool is_overloaded = GetFlag(n, "sym:overloaded"); + + // 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)) { + Append(state.clazz(STATIC_FUNCTIONS), t_function.str()); + } else { + Append(state.clazz(MEMBER_FUNCTIONS), t_function.str()); + } + } else { + Append(Getattr(current_namespace, "functions"), t_function.str()); + } + + 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")) { + Append(state.clazz(STATIC_VARIABLES), t_variable.str()); + } else { + Append(state.clazz(MEMBER_VARIABLES), t_variable.str()); + } + } else { + Append(Getattr(current_namespace, "values"), t_variable.str()); + } + + 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.global(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.global(INITIALIZER)); + + return SWIG_OK; +} + +Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent) { + Hash *entry = JSEmitter::createNamespaceEntry(name, parent); + 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 = Getattr(entry, PARENT); + String *parent_mangled = Swig_name_mangle(parent); + 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) + .pretty_print(f_wrap_cpp); + + Template t_createNamespace(getTemplate("jsc_nspace_definition")); + t_createNamespace.replace("$jsmangledname", name_mangled); + Append(state.global(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.global(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(); + +private: + + /* 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(), + 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); + SWIG_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); + + return SWIG_OK; +} + +int V8Emitter::dump(Node *n) +{ + /* Get the module name */ + String *module = Getattr(n, "name"); + + // write the swig banner + Swig_banner(f_wrap_cpp); + + 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() +{ + // strings + 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); + + // files + Close(f_wrap_cpp); + 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 registeration 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(). + 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() + .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() + .print(f_init_wrappers); + } + + return SWIG_OK; +} + +int V8Emitter::exitFunction(Node* n) +{ + bool is_member = GetFlag(n, "ismember") | GetFlag(n, "feature:extend"); + + // create a dispatcher for overloaded functions + bool is_overloaded = GetFlag(n, "sym:overloaded"); + 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() + .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() + .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)) + .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; + + 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 i = 0; + for (p = parms; p; i++) { + 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); + } else { + Printf(arg, "args[%d]", i - startIdx); + } + break; + case Function: + if (is_member && !is_static && i == 0) { + Printv(arg, "args.Holder()", 0); + } else { + Printf(arg, "args[%d]", i - startIdx); + } + break; + case Setter: + if (is_member && !is_static && i == 0) { + Printv(arg, "info.Holder()", 0); + } else { + Printv(arg, "value", 0); + } + break; + case Ctor: + Printf(arg, "args[%d]", i); + break; + default: + throw "Illegal state."; + } + + tm = emitInputTypemap(n, p, wrapper, arg); + Delete(arg); + + if (tm) { + p = Getattr(p, "tmap:in: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 = Swig_name_mangle(parent); + + 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 + Insert(f_init_register_namespaces, 0, t_register_ns.str()); + } + } + + return SWIG_OK; +} + +JSEmitter *swig_javascript_create_V8Emitter() { + return new V8Emitter(); +} + + +/********************************************************************** + * Helper implementations + **********************************************************************/ + +JSEmitterState::JSEmitterState() + : _global(NewHash()) +{ + // initialize sub-hashes + Setattr(_global, "class", NewHash()); + Setattr(_global, "function", NewHash()); + Setattr(_global, "variable", NewHash()); +} + +JSEmitterState::~JSEmitterState() +{ + Delete(_global); +} + +DOH *JSEmitterState::getState(const char* key, bool _new) +{ + if (_new) { + Hash *hash = NewHash(); + Setattr(_global, key, hash); + } + return Getattr(_global, key); +} + +DOH *JSEmitterState::global() { + return _global; +} + +DOH *JSEmitterState::global(const char* key, DOH *initial) +{ + if(initial != 0) { + Setattr(_global, key, initial); + } + return Getattr(_global, key); +} + +DOH *JSEmitterState::clazz(bool _new) +{ + return getState("class", _new); +} + +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) +{ + return getState("function", _new); +} + +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) +{ + return getState("variable", _new); +} + +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."); + SWIG_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."); + SWIG_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 occurences 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; +} + +void Template::operator=(const Template& t) { + Delete(code); + Delete(templateName); + code = NewString(t.code); + templateName = NewString(t.templateName); +} diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index eb7d49480..f95313053 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1471,7 +1471,9 @@ int Language::membervariableHandler(Node *n) { } if (make_set_wrapper) { Setattr(n, "sym:name", mrename_set); + SetFlag(n, "wrap:issetter"); functionWrapper(n); + Delattr(n, "wrap:issetter"); } else { SetFlag(n, "feature:immutable"); } @@ -2956,7 +2958,9 @@ int Language::variableWrapper(Node *n) { Delete(pname0); } if (make_set_wrapper) { + SetFlag(n, "wrap:issetter"); functionWrapper(n); + Delattr(n, "wrap:issetter"); } /* Restore parameters */ Setattr(n, "sym:name", symname); diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index 7c9cded70..97b21710a 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -51,6 +51,7 @@ extern "C" { Language *swig_r(void); Language *swig_go(void); Language *swig_d(void); + Language *swig_javascript(void); } struct swig_module { @@ -92,6 +93,7 @@ static swig_module modules[] = { {"-tcl8", swig_tcl, 0}, {"-uffi", swig_uffi, "Common Lisp / UFFI"}, {"-xml", swig_xml, "XML"}, + {"-javascript", swig_javascript, "Javascript"}, {NULL, NULL, NULL} }; diff --git a/Tools/javascript/javascript.cxx b/Tools/javascript/javascript.cxx new file mode 100644 index 000000000..ec4ac4e3f --- /dev/null +++ b/Tools/javascript/javascript.cxx @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include + +#include "js_shell.h" + +void print_usage() { + std::cout << "javascript [-i] [-jsc|-v8] [-l module] " << std::endl; +} + +int main(int argc, char* argv[]) { + + std::string scriptPath = ""; + + bool interactive = false; + JSShell* shell = 0; + + for (int idx = 1; idx < argc; ++idx) { + if(strcmp(argv[idx], "-v8") == 0) { + shell = JSShell::Create(JSShell::V8); + } else if(strcmp(argv[idx], "-jsc") == 0) { + shell = JSShell::Create(JSShell::JSC); + } else if(strcmp(argv[idx], "-i") == 0) { + interactive = true; + } else { + scriptPath = argv[idx]; + } + } + + if (shell == 0) { + shell = JSShell::Create(); + } + + bool failed = false; + + if(interactive) { + failed = !(shell->RunShell()); + } else { + failed = !(shell->RunScript(scriptPath)); + } + + if (failed) { + delete shell; + printf("FAIL: Error during execution of script.\n"); + return 1; + } + + delete shell; + + return 0; +} diff --git a/Tools/javascript/js_shell.cxx b/Tools/javascript/js_shell.cxx new file mode 100644 index 000000000..ca5ca7ecd --- /dev/null +++ b/Tools/javascript/js_shell.cxx @@ -0,0 +1,145 @@ +#include "js_shell.h" + +#include +#include +#include +#include + +#ifdef __GNUC__ +#ifdef __APPLE__ +#define LIBRARY_EXT ".dylib" +#else +#define LIBRARY_EXT ".so" +#endif +#include +#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY) +#define CLOSE_LIBRARY(handle) dlclose(handle) +#define LIBRARY_ERROR dlerror +#define LIBRARYFILE(name) std::string("lib").append(name).append(LIBRARY_EXT) +#else +#error "implement dll loading" +#endif + + +JSShell::~JSShell() { + + for(std::vector::iterator it = loaded_modules.begin(); + it != loaded_modules.end(); ++it) { + HANDLE handle = *it; + CLOSE_LIBRARY(handle); + } + +} + +// TODO: this could be done more intelligent... +// - can we achieve source file relative loading? +// - better path resolution +std::string JSShell::LoadModule(const std::string& name, HANDLE* library) { + + // works only for posix like OSs + size_t pathIdx = name.find_last_of("/"); + + std::string lib_name; + std::string module_name; + if (pathIdx == std::string::npos) { + module_name = name; + lib_name = std::string(name).append(LIBRARY_EXT); + } else { + std::string path = name.substr(0, pathIdx+1); + module_name = name.substr(pathIdx+1); + lib_name = path.append(module_name).append(LIBRARY_EXT); + } + + HANDLE handle = LOAD_LIBRARY(lib_name.c_str()); + if(handle == 0) { + std::cout << "Could not load library " << lib_name << ":" + << std::endl << LIBRARY_ERROR() << std::endl; + return 0; + } + + loaded_modules.push_back(handle); + + *library = handle; + + return module_name; +} + +bool JSShell::RunScript(const std::string& scriptPath) { + std::string source = ReadFile(scriptPath); + if(!InitializeEngine()) return false; + + // Node.js compatibility: make `print` available as `console.log()` + ExecuteScript("var console = {}; console.log = print;", ""); + + if(!ExecuteScript(source, scriptPath)) { + return false; + } + + return DisposeEngine(); +} + +bool JSShell::RunShell() { + + if(!InitializeEngine()) return false; + + static const int kBufferSize = 1024; + while (true) { + char buffer[kBufferSize]; + printf("> "); + char* str = fgets(buffer, kBufferSize, stdin); + if (str == NULL) break; + std::string source(str); + ExecuteScript(source, "(shell)"); + } + printf("\n"); + return true; +} + +std::string JSShell::ReadFile(const std::string& fileName) +{ + std::string script; + + std::ifstream file(fileName.c_str()); + if (file.is_open()) { + while ( file.good() ) { + std::string line; + getline(file, line); + script.append(line); + script.append("\n"); + } + file.close(); + } else { + std::cout << "Unable to open file " << fileName << "." << std::endl; + } + + return script; +} + +#ifdef ENABLE_JSC +extern JSShell* JSCShell_Create(); +#endif +#ifdef ENABLE_V8 +extern JSShell* V8Shell_Create(); +#endif + +typedef JSShell*(*ShellFactory)(); + +static ShellFactory js_shell_factories[2] = { +#ifdef ENABLE_JSC +JSCShell_Create, +#else +0, +#endif +#ifdef ENABLE_V8 +V8Shell_Create, +#else +0, +#endif +}; + +JSShell *JSShell::Create(Engine engine) { + if(js_shell_factories[engine] == 0) { + throw "Engine not available."; + } + return js_shell_factories[engine](); +} diff --git a/Tools/javascript/js_shell.h b/Tools/javascript/js_shell.h new file mode 100644 index 000000000..84a8534d6 --- /dev/null +++ b/Tools/javascript/js_shell.h @@ -0,0 +1,48 @@ +#ifndef JS_SHELL_H +#define JS_SHELL_H + +#include +#include + +typedef void* HANDLE; +typedef void* MODULE; + +class JSShell { + +public: + enum Engine { + JSC = 0, + V8 + }; + +public: + + JSShell() {} + + virtual ~JSShell() = 0; + + static JSShell* Create(Engine engine = JSC); + + std::string LoadModule(const std::string& name, HANDLE* library); + + virtual bool RunScript(const std::string& scriptPath); + + virtual bool RunShell(); + +protected: + + virtual bool InitializeEngine() = 0; + + virtual bool ExecuteScript(const std::string& source, const std::string& scriptPath) = 0; + + virtual bool DisposeEngine() = 0; + + static std::string ReadFile(const std::string& fileName); + +protected: + + std::vector loaded_modules; + +}; + +#endif // JS_SHELL_H diff --git a/Tools/javascript/jsc_shell.cxx b/Tools/javascript/jsc_shell.cxx new file mode 100644 index 000000000..e4e8cdd96 --- /dev/null +++ b/Tools/javascript/jsc_shell.cxx @@ -0,0 +1,229 @@ +#include + +#include "js_shell.h" + +#include +#include + +#ifdef __GNUC__ +#include +#define LOAD_SYMBOL(handle, name) dlsym(handle, name) +#else +#error "implement dll loading" +#endif + +class JSCShell: public JSShell { + +typedef int (*JSCIntializer)(JSGlobalContextRef context, JSObjectRef *module); + +public: + + JSCShell() {}; + + virtual ~JSCShell(); + +protected: + + virtual bool InitializeEngine(); + + virtual bool ExecuteScript(const std::string& source, const std::string& scriptPath); + + virtual bool DisposeEngine(); + +private: + + JSObjectRef Import(const std::string &moduleName); + + static JSValueRef Print(JSContextRef context, JSObjectRef object, JSObjectRef globalobj, size_t argc, const JSValueRef args[], JSValueRef* ex); + + static JSValueRef Require(JSContextRef context, JSObjectRef object, JSObjectRef globalobj, size_t argc, const JSValueRef args[], JSValueRef* ex); + + static bool RegisterFunction(JSGlobalContextRef context, JSObjectRef object, const char* functionName, JSObjectCallAsFunctionCallback cbFunction); + + static void PrintError(JSContextRef, JSValueRef); + +private: + + JSGlobalContextRef context; +}; + +JSCShell::~JSCShell() { + if(context != 0) { + JSGlobalContextRelease(context); + context = 0; + } +} + +bool JSCShell::InitializeEngine() { + if(context != 0) { + JSGlobalContextRelease(context); + context = 0; + } + // TODO: check for initialization errors + context = JSGlobalContextCreate(NULL); + if(context == 0) return false; + JSObjectRef globalObject = JSContextGetGlobalObject(context); + + + // store this for later use + JSClassDefinition __shell_classdef__; + JSClassRef __shell_class__ = JSClassCreate(&__shell_classdef__); + JSObjectRef __shell__ = JSObjectMake(context, __shell_class__, 0); + bool success = JSObjectSetPrivate(__shell__, (void*) (long) this); + JSStringRef shellKey = JSStringCreateWithUTF8CString("__shell__"); + JSObjectSetProperty(context, globalObject, shellKey, __shell__, kJSPropertyAttributeReadOnly, NULL); + JSStringRelease(shellKey); + + JSCShell::RegisterFunction(context, globalObject, "print", JSCShell::Print); + JSCShell::RegisterFunction(context, globalObject, "require", JSCShell::Require); + + return true; +} + +bool JSCShell::ExecuteScript(const std::string& source, const std::string& scriptPath) { + JSStringRef jsScript; + JSStringRef sourceURL; + JSValueRef ex; + jsScript = JSStringCreateWithUTF8CString(source.c_str()); + sourceURL = JSStringCreateWithUTF8CString(scriptPath.c_str()); + JSValueRef jsResult = JSEvaluateScript(context, jsScript, 0, sourceURL, 0, &ex); + JSStringRelease(jsScript); + if (jsResult == NULL && ex != NULL) { + JSCShell::PrintError(context, ex); + return false; + } + return true; +} + +bool JSCShell::DisposeEngine() { + JSGlobalContextRelease(context); + context = 0; + return true; +} + +JSValueRef JSCShell::Print(JSContextRef context, JSObjectRef object, + JSObjectRef globalobj, size_t argc, + const JSValueRef args[], JSValueRef* ex) { + if (argc > 0) + { + JSStringRef string = JSValueToStringCopy(context, args[0], NULL); + size_t numChars = JSStringGetMaximumUTF8CStringSize(string); + char *stringUTF8 = new char[numChars]; + JSStringGetUTF8CString(string, stringUTF8, numChars); + printf("%s\n", stringUTF8); + + delete[] stringUTF8; + } + + return JSValueMakeUndefined(context); +} + +// Attention: this feature should not create too high expectations. +// It is only capable of loading things relative to the execution directory +// and not relative to the parent script. +JSValueRef JSCShell::Require(JSContextRef context, JSObjectRef object, + JSObjectRef globalObj, size_t argc, + const JSValueRef args[], JSValueRef* ex) { + JSObjectRef module; + + JSStringRef shellKey = JSStringCreateWithUTF8CString("__shell__"); + JSValueRef shellAsVal = JSObjectGetProperty(context, globalObj, shellKey, NULL); + JSStringRelease(shellKey); + JSObjectRef shell = JSValueToObject(context, shellAsVal, 0); + JSCShell *_this = (JSCShell*) (long) JSObjectGetPrivate(shell); + + if (argc > 0) + { + JSStringRef string = JSValueToStringCopy(context, args[0], NULL); + size_t numChars = JSStringGetMaximumUTF8CStringSize(string); + char *stringUTF8 = new char[numChars]; + JSStringGetUTF8CString(string, stringUTF8, numChars); + + std::string modulePath(stringUTF8); + module = _this->Import(modulePath); + + delete[] stringUTF8; + } + + if (module) { + return module; + } else { + printf("Ooops.\n"); + return JSValueMakeUndefined(context); + } +} + +JSObjectRef JSCShell::Import(const std::string& module_path) { + + HANDLE library; + std::string module_name = LoadModule(module_path, &library); + + if (library == 0) { + printf("Could not load module."); + return 0; + } + + std::string symname = std::string(module_name).append("_initialize"); + + JSCIntializer init_function = reinterpret_cast((long) LOAD_SYMBOL(library, symname.c_str())); + if(init_function == 0) { + printf("Could not find module's initializer function."); + return 0; + } + + JSObjectRef module; + init_function(context, &module); + + return module; +} + +bool JSCShell::RegisterFunction(JSGlobalContextRef context, JSObjectRef object, + const char* functionName, JSObjectCallAsFunctionCallback callback) { + JSStringRef js_functionName = JSStringCreateWithUTF8CString(functionName); + JSObjectSetProperty(context, object, js_functionName, + JSObjectMakeFunctionWithCallback(context, js_functionName, callback), + kJSPropertyAttributeNone, NULL); + JSStringRelease(js_functionName); + return true; +} + +void JSCShell::PrintError(JSContextRef ctx, JSValueRef err) { + char *buffer; + size_t length; + + JSStringRef string = JSValueToStringCopy(ctx, err, 0); + length = JSStringGetLength(string); + buffer = new char[length+1]; + JSStringGetUTF8CString(string, buffer, length+1); + std::string errMsg(buffer); + JSStringRelease(string); + delete[] buffer; + + JSObjectRef errObj = JSValueToObject(ctx, err, 0); + + if(errObj == 0) { + std::cerr << errMsg << std::endl; + return; + } + + JSStringRef sourceURLKey = JSStringCreateWithUTF8CString("sourceURL"); + JSStringRef sourceURLStr = JSValueToStringCopy(ctx, JSObjectGetProperty(ctx, errObj, sourceURLKey, 0), 0); + length = JSStringGetLength(sourceURLStr); + buffer = new char[length+1]; + JSStringGetUTF8CString(sourceURLStr, buffer, length+1); + std::string sourceURL(buffer); + delete[] buffer; + JSStringRelease(sourceURLStr); + JSStringRelease(sourceURLKey); + + JSStringRef lineKey = JSStringCreateWithUTF8CString("line"); + JSValueRef jsLine = JSObjectGetProperty(ctx, errObj, lineKey, 0); + int line = (int) JSValueToNumber(ctx, jsLine, 0); + JSStringRelease(lineKey); + + std::cerr << sourceURL << ":" << line << ":" << errMsg << std::endl; +} + +JSShell* JSCShell_Create() { + return new JSCShell(); +} diff --git a/Tools/javascript/v8_shell.cxx b/Tools/javascript/v8_shell.cxx new file mode 100755 index 000000000..8a571e0f1 --- /dev/null +++ b/Tools/javascript/v8_shell.cxx @@ -0,0 +1,310 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "js_shell.h" + +typedef int (*V8ExtensionInitializer) (v8::Handle module); + +class V8Shell: public JSShell { + +public: + V8Shell(); + + virtual ~V8Shell(); + + virtual bool RunScript(const std::string& scriptPath); + + virtual bool RunShell(); + + +protected: + + virtual bool InitializeEngine(); + + virtual bool ExecuteScript(const std::string& source, const std::string& scriptPath); + + virtual bool DisposeEngine(); + +private: + + v8::Handle Import(const std::string& moduleName); + + v8::Persistent CreateShellContext(); + + void ReportException(v8::TryCatch* handler); + + static v8::Handle Print(const v8::Arguments& args); + + static v8::Handle Require(const v8::Arguments& args); + + static v8::Handle Quit(const v8::Arguments& args); + + static v8::Handle Version(const v8::Arguments& args); + + static const char* ToCString(const v8::String::Utf8Value& value); + +protected: + + v8::Persistent context; +}; + +#ifdef __GNUC__ +#include +#define LOAD_SYMBOL(handle, name) dlsym(handle, name) +#else +#error "implement dll loading" +#endif + +V8Shell::V8Shell() +{ +} + +V8Shell::~V8Shell() { + context.Dispose(); + v8::V8::Dispose(); +} + +bool V8Shell::RunScript(const std::string& scriptPath) { + + if (!context.IsEmpty()) { + context.Dispose(); + } + + std::string source = ReadFile(scriptPath); + + context = CreateShellContext(); + if (context.IsEmpty()) { + printf("Could not create context.\n"); + return false; + } + context->Enter(); + //v8::Context::Scope context_scope(context); + v8::HandleScope scope; + + // Store a pointer to this shell for later use + v8::Handle global = context->Global(); + v8::Local __shell__ = v8::External::New((void*) (long) this); + global->SetHiddenValue(v8::String::New("__shell__"), __shell__); + + // Node.js compatibility: make `print` available as `console.log()` + ExecuteScript("var console = {}; console.log = print;", ""); + + if(!ExecuteScript(source, scriptPath)) { + return false; + } + + context->Exit(); + context.Dispose(); + v8::V8::Dispose(); + + return true; +} + +bool V8Shell::RunShell() { + + if (!context.IsEmpty()) { + context.Dispose(); + } + + context = CreateShellContext(); + if (context.IsEmpty()) { + printf("Could not create context.\n"); + return false; + } + + context->Enter(); + + v8::Context::Scope context_scope(context); + + ExecuteScript("var console = {}; console.log = print;", ""); + + static const int kBufferSize = 1024; + while (true) { + char buffer[kBufferSize]; + printf("> "); + char* str = fgets(buffer, kBufferSize, stdin); + if (str == NULL) break; + std::string source(str); + ExecuteScript(source, "(shell)"); + } + printf("\n"); + + context->Exit(); + context.Dispose(); + v8::V8::Dispose(); + + return true; +} + + +bool V8Shell::InitializeEngine() { + return true; +} + +bool V8Shell::ExecuteScript(const std::string& source, const std::string& name) { + v8::HandleScope handle_scope; + v8::TryCatch try_catch; + v8::Handle script = v8::Script::Compile(v8::String::New(source.c_str()), v8::String::New(name.c_str())); + + // Stop if script is empty + if (script.IsEmpty()) { + // Print errors that happened during compilation. + ReportException(&try_catch); + return false; + } + + v8::Handle result = script->Run(); + + // Print errors that happened during execution. + if (try_catch.HasCaught()) { + ReportException(&try_catch); + return false; + } else { + return true; + } +} + +bool V8Shell::DisposeEngine() { + return true; +} + +v8::Persistent V8Shell::CreateShellContext() { + v8::HandleScope scope; + + // Create a template for the global object. + v8::Handle global = v8::ObjectTemplate::New(); + + // Bind global functions + global->Set(v8::String::New("print"), v8::FunctionTemplate::New(V8Shell::Print)); + global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(V8Shell::Quit)); + global->Set(v8::String::New("require"), v8::FunctionTemplate::New(V8Shell::Require)); + global->Set(v8::String::New("version"), v8::FunctionTemplate::New(V8Shell::Version)); + + v8::Persistent _context = v8::Context::New(NULL, global); + + return _context; +} + +v8::Handle V8Shell::Import(const std::string& module_path) +{ + v8::HandleScope scope; + + HANDLE library; + std::string module_name = LoadModule(module_path, &library); + + std::string symname = std::string(module_name).append("_initialize"); + + V8ExtensionInitializer init_function = reinterpret_cast((long) LOAD_SYMBOL(library, symname.c_str())); + + if(init_function == 0) { + printf("Could not find initializer function."); + return v8::Undefined(); + } + + v8::Local module = v8::Object::New(); + init_function(module); + return scope.Close(module); +} + +v8::Handle V8Shell::Print(const v8::Arguments& args) { + bool first = true; + for (int i = 0; i < args.Length(); i++) { + v8::HandleScope handle_scope; + if (first) { + first = false; + } else { + printf(" "); + } + v8::String::Utf8Value str(args[i]); + const char* cstr = V8Shell::ToCString(str); + printf("%s", cstr); + } + printf("\n"); + fflush(stdout); + return v8::Undefined(); +} + +v8::Handle V8Shell::Require(const v8::Arguments& args) { + v8::HandleScope scope; + + if (args.Length() != 1) { + printf("Illegal arguments for `require`"); + }; + + v8::String::Utf8Value str(args[0]); + const char* cstr = V8Shell::ToCString(str); + std::string moduleName(cstr); + + v8::Local global = v8::Context::GetCurrent()->Global(); + v8::Local hidden = global->GetHiddenValue(v8::String::New("__shell__")); + v8::Local __shell__ = v8::Local::Cast(hidden); + V8Shell* _this = (V8Shell*) (long) __shell__->Value(); + + v8::Handle module = _this->Import(moduleName); + + return scope.Close(module); +} + +v8::Handle V8Shell::Quit(const v8::Arguments& args) { + int exit_code = args[0]->Int32Value(); + fflush(stdout); + fflush(stderr); + exit(exit_code); + return v8::Undefined(); +} + +v8::Handle V8Shell::Version(const v8::Arguments& args) { + return v8::String::New(v8::V8::GetVersion()); +} + +void V8Shell::ReportException(v8::TryCatch* try_catch) { + v8::HandleScope handle_scope; + v8::String::Utf8Value exception(try_catch->Exception()); + const char* exception_string = V8Shell::ToCString(exception); + v8::Handle message = try_catch->Message(); + if (message.IsEmpty()) { + // V8 didn't provide any extra information about this error; just + // print the exception. + printf("%s\n", exception_string); + } else { + // Print (filename):(line number): (message). + v8::String::Utf8Value filename(message->GetScriptResourceName()); + const char* filename_string = V8Shell::ToCString(filename); + int linenum = message->GetLineNumber(); + printf("%s:%i: %s\n", filename_string, linenum, exception_string); + // Print line of source code. + v8::String::Utf8Value sourceline(message->GetSourceLine()); + const char* sourceline_string = V8Shell::ToCString(sourceline); + printf("%s\n", sourceline_string); + // Print wavy underline (GetUnderline is deprecated). + int start = message->GetStartColumn(); + for (int i = 0; i < start; i++) { + printf(" "); + } + int end = message->GetEndColumn(); + for (int i = start; i < end; i++) { + printf("^"); + } + printf("\n"); + v8::String::Utf8Value stack_trace(try_catch->StackTrace()); + if (stack_trace.length() > 0) { + const char* stack_trace_string = V8Shell::ToCString(stack_trace); + printf("%s\n", stack_trace_string); + } + } +} + +// Extracts a C string from a V8 Utf8Value. +const char* V8Shell::ToCString(const v8::String::Utf8Value& value) { + return *value ? *value : ""; +} + +JSShell* V8Shell_Create() { + return new V8Shell(); +} diff --git a/Tools/swigconfig.h.cmake b/Tools/swigconfig.h.cmake new file mode 100644 index 000000000..e4f0b42c4 --- /dev/null +++ b/Tools/swigconfig.h.cmake @@ -0,0 +1,89 @@ +/* Define to 1 if the system has the type `bool'. */ +#cmakedefine HAVE_BOOL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `dl' library (-ldl). */ +#cmakedefine HAVE_LIBDL 1 + +/* Define to 1 if you have the `dld' library (-ldld). */ +#cmakedefine HAVE_LIBDLD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define if popen is available */ +#cmakedefine HAVE_POPEN 1 + +/* Define if rxspencer is available */ +#cmakedefine HAVE_RXSPENCER 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#cmakedefine NO_MINUS_C_MINUS_O 1 + +/* Define to 1 if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS 1 + +/* Name of package */ +#define PACKAGE "swig" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "http://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 @SWIG_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "swig" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@SWIG_VERSION@" + +/* Compiler that built SWIG */ +#define SWIG_CXX "@SWIG_CXX@" + +/* Directory for SWIG system-independent libraries */ +#define SWIG_LIB "/usr/local/share/swig/2.0.0" + +/* Directory for SWIG system-independent libraries (Unix install on native + Windows) */ +#define SWIG_LIB_WIN_UNIX "C:/cygwin/usr/local/share/swig/2.0.0" + +/* Platform that SWIG is built for */ +#define SWIG_PLATFORM "i686-pc-cygwin" + +/* Version number of package */ +#define VERSION "@SWIG_VERSION@" + +/* Default language */ +#define SWIG_LANG "-tcl" + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif diff --git a/Tools/swigprinters.gdb b/Tools/swigprinters.gdb new file mode 100644 index 000000000..661aa3ea1 --- /dev/null +++ b/Tools/swigprinters.gdb @@ -0,0 +1,24 @@ +python +import sys +import os + +try: + global SWIG_PRINTER_DIR + sys.path.insert(0, SWIG_PRINTER_DIR) +except NameError: + raise RuntimeError(""" +--------------------------------------------------------- +Change ~/.gdbinit to be able to use swig pretty printers: +> set python SWIG_PRINTER_DIR = /Tools +> source /Tools/swigprinters.gdb +--------------------------------------------------------- +""") + +from swigprinters import register_swig_printers, enableGdbPrintWorkaround, \ + setChildrenRecursionLevel + +#enableGdbPrintWorkaround() +#setChildrenRecursionLevel(2) +register_swig_printers (None) + +end diff --git a/Tools/swigprinters.py b/Tools/swigprinters.py new file mode 100755 index 000000000..741565997 --- /dev/null +++ b/Tools/swigprinters.py @@ -0,0 +1,574 @@ +import gdb +import gdb.types +import itertools +import re + +log_file = None +GDB_FLATTENED_CHILDREN_WORKAROUND = False +CHILDREN_MAX_RECURSION_LEVEL = 0 + +# workaround: don't cast the following DOHs to it's actual type +# to avoid infinite pretty-print loops +cast_black_list = { + 'Hash': set(['parentNode', 'symtab', 'csymtab', 'sym:symtab', 'inherit', 'nextSibling', 'previousSibling']) +} + +def print_(msg): + global log_file; + + if True: + if log_file == None: + log_file = open('swig_gdb.log', 'w') + log_file.write(msg) + + print(msg) + +class SwigStringPrinter: + """ + Pretty print Swig String* types. + """ + + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + try: + self.t_swigstr_ptr = gdb.lookup_type("struct String").pointer() + self.t_doh_base_ptr = gdb.lookup_type("DohBase").pointer() + except Exception as err: + print_("SwigStringPrinter: Could not retrieve gdb types.\n %s.\n"%(str(err))) + + def display_hint(self): + return 'string' + + def to_string(self): + ret = "" + + # Conversion taken from Swig Internals manual: + # http://peregrine.hpc.uwm.edu/Head-node-docs/swig/2.0.4/Devel/internals.html#7 + # (*(struct String *)(((DohBase *)s)->data)).str + + dohbase = None; + str_data = None; + char_ptr = None; + + try: + dohbase = self.val.reinterpret_cast(self.t_doh_base_ptr).dereference() + except Exception as err: + print_("SwigStringPrinter: Could not dereference DOHBase*\n"); + return ""; + + try: + str_data = dohbase['data'].reinterpret_cast(self.t_swigstr_ptr).dereference() + except Exception as err: + print_("SwigStringPrinter: Could not dereference struct String*\n"); + return ""; + + try: + char_ptr = str_data['str'] + except Exception as err: + print_("SwigStringPrinter: Could not access field (struct String).str\n"); + return ""; + + if char_ptr.is_lazy is True: + char_ptr.fetch_lazy () + + try: + ret = char_ptr.string() + except Exception as err: + print_("SwigStringPrinter: Could not convert const char* to string\n"); + return ""; + + return ret + +class SwigIterator: + + def __init__(self): + + self.t_doh_base_ptr = gdb.lookup_type("DohBase").pointer() + self.t_string_ptr = gdb.lookup_type("String").pointer() + self.t_node_ptr = gdb.lookup_type("Node").pointer() + self.t_hash_ptr = gdb.lookup_type("Hash").pointer() + self.t_file_ptr = gdb.lookup_type("File").pointer() + self.t_void_ptr = gdb.lookup_type("void").pointer() + + def cast_doh(self, doh, name = None): + + if doh == 0: + return doh + + doh = doh.reinterpret_cast(self.t_doh_base_ptr); + + val_base = doh.dereference() + val_type = val_base['type'].dereference() + val_typestr = val_type['objname'].string() + + if not name == None and val_typestr in cast_black_list: + blacklist = cast_black_list[val_typestr] + if name in blacklist: + return doh + + if "String" == val_typestr: + doh = doh.reinterpret_cast(self.t_string_ptr) + elif "File" == val_typestr: + doh = doh.reinterpret_cast(self.t_file_ptr) + # BUG: GDB Pyhton can not handle cyclic references yet + # so these casts are deactivated + elif "Hash" == val_typestr: + doh = doh.reinterpret_cast(self.t_hash_ptr) + elif "Node" == val_typestr: + doh = doh.reinterpret_cast(self.t_node_ptr) + + return doh + +class SwigListIterator(SwigIterator): + + def __init__(self, val): + SwigIterator.__init__(self); + + try: + self.valid = False + + self.val = val.reinterpret_cast(self.t_doh_base_ptr) + val_base = self.val.dereference() + val_type = val_base['type'].dereference() + val_typestr = val_type['objname'].string() + #print_("SwigListIterator: constructing iterator for value of type %s"%val_typestr) + + self.t_struct_list_ptr = gdb.lookup_type("struct List").pointer() + + doh_base = self.val.dereference() + self.l = doh_base['data'].reinterpret_cast(self.t_struct_list_ptr).dereference() + + self.address = 0 + self._index = 0 + self.key = 0 + self.item = 0 + + self.address = self.val.dereference().address + + self.is_first = True + self.valid = True + + except Exception as err: + print_("SwigListIterator: Construction failed.\n %s.\n"%(str(err))) + + def __iter__(self): + return self + + def List_first(self): + + self.object = None; + self._index = 0 + self.key = 0 + self.nitems = int(self.l['nitems']) + self.items = self.l['items'] + + if self.nitems > 0: + self.item = self.items[0] + else: + self.stop() + + def List_next(self): + self._index = self._index + 1 + if self._index >= self.nitems: + self.stop() + else: + self.item = self.items[self._index] + + def next(self): + + if not self.valid: + self.stop() + + if self.is_first: + self.is_first = False + try: + self.List_first() + except StopIteration: + raise StopIteration + except Exception as err: + print_("Error during iteration to first node: \n %s \n" %(str(err))) + self.stop() + else: + try: + self.List_next() + except StopIteration: + raise StopIteration + except Exception as err: + print_("Error during iteration to first node: \n %s \n" %(str(err))) + self.stop() + + key_str = "[%d]"%self._index + item = 0 + + try: + item = self.cast_doh(self.item) + except Exception as err: + print_("SwigListIterator(%s): Exception during casting of value doh:\n %s\n" % (str(self.address), str(err)) ) + self.stop() + + return (key_str, item) + + def stop(self): + self.is_first = True + self.item = 0 + self.key = 0 + raise StopIteration + +class SwigHashIterator(SwigIterator): + + def __init__(self, val): + SwigIterator.__init__(self); + + try: + self.valid = False + + self.val = val.reinterpret_cast(self.t_doh_base_ptr) + + self.t_struct_hash_ptr = gdb.lookup_type("struct Hash").pointer() + self.t_struct_hash_node_ptr = gdb.lookup_type("struct HashNode").pointer() + + doh_base = self.val.dereference() + hash_ = doh_base['data'].reinterpret_cast(self.t_struct_hash_ptr).dereference() + self.hashtable = hash_['hashtable'] + self.hashsize = int(hash_['hashsize']) + self.nitems = int(hash_['nitems']) + + self.next_ = 0 + self.address = 0 + self.pos = 0; + self._current = 0 + self.item = 0 + self.key = 0 + self._index = 0 + + self.address = self.val.dereference().address + + self.is_first = True + self.valid = True + + except Exception as err: + print_("SwigHashIterator: Construction failed.\n %s.\n"%(str(err))) + + def __iter__(self): + return self + + def Hash_firstiter(self): + self._current = 0; + self.item = 0; + self.key = 0; + self._index = 0; + + while (self._index < self.hashsize) and (self.hashtable[self._index] == 0): + self._index = self._index+1; + + if self._index >= self.hashsize: + self.stop(); + + self._current = self.hashtable[self._index] + self._current = self._current.reinterpret_cast(self.t_struct_hash_node_ptr); + self.item = self._current['object']; + self.key = self._current['key']; + + self._current = self._current['next']; + + + def Hash_nextiter(self): + if self._current == 0: + self._index = self._index + 1 + while (self._index < self.hashsize) and (self.hashtable[self._index] == 0): + self._index = self._index + 1 + + if self._index >= self.hashsize: + self.item = 0; + self.key = 0; + self._current = 0; + self.stop() + + self._current = self.hashtable[self._index]; + + self._current = self._current.reinterpret_cast(self.t_struct_hash_node_ptr); + self.key = self._current['key']; + self.item = self._current['object']; + + self._current = self._current['next']; + + + def next(self): + + if not self.valid: + self.stop() + + if self.is_first: + self.is_first = False + try: + self.Hash_firstiter() + except StopIteration: + raise StopIteration + except Exception as err: + print_("Error during iteration to first node: \n %s \n" %(str(err))) + self.stop() + else: + try: + self.Hash_nextiter() + except StopIteration: + raise StopIteration + except Exception as err: + print_("Error during iteration to first node: \n %s \n" %(str(err))) + self.stop() + + key_str = "" + item = 0 + try: + string_printer = SwigStringPrinter("String *", self.key) + key_str = string_printer.to_string() + except Exception as err: + print_("SwigHashIterator(%s): Exception during extracting key string:\n %s\n" % (str(self.address), str(err)) ) + self.stop() + + try: + item = self.cast_doh(self.item, key_str) + + except Exception as err: + print_("SwigHashIterator(%s): Exception during casting of value doh:\n %s\n" % (str(self.address), str(err)) ) + self.stop() + + return (key_str, item) + + def stop(self): + self.is_first = True + raise StopIteration + +class AlternateKeyValueIterator(): + + def __init__(self, iterable): + self.it = iterable.__iter__() + self._next = None + self.count = -1 + + def __iter__(self): + return self + + def next(self): + if self._next == None: + key, value = self.it.next() + self._next = value + self.count = self.count + 1 + return ("[%d]"%self.count, key) + else: + value = self._next + self._next = None + return ("[%d]"%self.count, value) + +class NopIterator: + + def __init__(self): + pass + + def __iter__(self): + return self + + def next(self): + raise StopIteration + +class SwigListPrinter: + """ + Pretty print Swig List* types (also ParmList*). + """ + + def __init__ (self, typename, val): + + self.typename = typename + self.val = val + + it = SwigListIterator(val) + self.valid = it.valid + self.address = it.address + + + def display_hint(self): + return 'array' + + def to_string(self): + return "%s(%s)" % (str(self.typename), str(self.address)) + + def children(self): + + if not self.valid: + print_("SwigListPrinter: Invalid state.\n") + return NopIterator() + + try: + it = SwigListIterator(self.val) + return it + except Exception as err: + print_("SwigListPrinter: Error during creation of children iterator. \n %s \n" %(str(err))) + raise err + +class SwigHashPrinter: + """ + Pretty print Swig Hash* types (also Node*). + """ + + def __init__ (self, typename, val): + + self.typename = typename + self.val = val + it = SwigHashIterator(val) + self.valid = it.valid + self.address = it.address + self.level = 0; + + def display_hint(self): + return 'map' + + def to_string(self): + return "%s(%s)" % (str(self.typename), str(self.address)) + + def children(self): + global GDB_FLATTENED_CHILDREN_WORKAROUND + global CHILDREN_MAX_RECURSION_LEVEL + + if not self.valid: + print_("SwigHashPrinter: Invalid state.\n") + return NopIterator() + + if self.level > CHILDREN_MAX_RECURSION_LEVEL: + return NopIterator() + + try: + it = SwigHashIterator(self.val) + if GDB_FLATTENED_CHILDREN_WORKAROUND: + return AlternateKeyValueIterator(it) + return it + except Exception as err: + print_("SwigHashPrinter: Error during creation of children iterator. \n %s \n" %(str(err))) + raise err + +class SwigSimplePrinter: + def __init__ (self, typename, val): + self.typename = typename + self.val = val + + def display_hint(self): + return "string" + + def to_string(self): + return "%s(%s)"%(self.typename, str(self.val.address)) + +class SwigDelegatingPrinter: + + def __init__ (self, typename, val): + t_doh_base_ptr = gdb.lookup_type("DohBase").pointer() + val_base = val.reinterpret_cast(t_doh_base_ptr).dereference() + val_type = val_base['type'].dereference() + val_typestr = val_type['objname'].string() + self.has_children = False + + if val_typestr == "Hash": + self.delegate = SwigHashPrinter(typename, val) + self.has_children = True + elif val_typestr == "List": + self.delegate = SwigListPrinter(typename, val) + self.has_children = True + elif val_typestr == "String": + self.delegate = SwigStringPrinter(typename, val) + else: + self.delegate = SwigSimplePrinter(typename, val) + + def display_hint(self): + return self.delegate.display_hint() + + def to_string(self): + return self.delegate.to_string() + + def children(self): + if not self.has_children: + return NopIterator() + + return self.delegate.children() + +class RxPrinter(object): + def __init__(self, name, function): + super(RxPrinter, self).__init__() + self.name = name + self.function = function + self.enabled = True + + def invoke(self, value): + if not self.enabled: + return None + return self.function(self.name, value) + +# A pretty-printer that conforms to the "PrettyPrinter" protocol from +# gdb.printing. It can also be used directly as an old-style printer. +class Printer(object): + def __init__(self, name): + super(Printer, self).__init__() + self.name = name + self.subprinters = [] + self.lookup = {} + self.enabled = True + self.compiled_rx = re.compile('^([a-zA-Z0-9_: *]+)$') + + def add(self, name, function): + if not self.compiled_rx.match(name): + raise ValueError, 'error: "%s" does not match' % name + + printer = RxPrinter(name, function) + self.subprinters.append(printer) + self.lookup[name] = printer + print('Added pretty printer for %s. ' % (name)) + + def __call__(self, val): + typename = str(val.type) + if typename in self.lookup: + ret = self.lookup[typename].invoke(val) + return ret + + # Cannot find a pretty printer. Return None. + return None + +swig_printer = None + +def register_swig_printers(obj): + global swig_printer + + if obj is None: + obj = gdb + + obj.pretty_printers.append(swig_printer) + +def build_swig_printer(): + global swig_printer + + swig_printer = Printer("swig") + swig_printer.add('String *', SwigStringPrinter) + swig_printer.add('const String *', SwigStringPrinter) + swig_printer.add('SwigType *', SwigStringPrinter) + swig_printer.add('Hash *', SwigHashPrinter) + swig_printer.add('const Hash *', SwigHashPrinter) + swig_printer.add('Node *', SwigHashPrinter) + swig_printer.add('const Node *', SwigHashPrinter) + swig_printer.add('Parm *', SwigHashPrinter) + swig_printer.add('const Parm *', SwigHashPrinter) + swig_printer.add('List *', SwigListPrinter) + swig_printer.add('const List *', SwigListPrinter) + swig_printer.add('ParmList *', SwigDelegatingPrinter) + swig_printer.add('const ParmList *', SwigDelegatingPrinter) + swig_printer.add('File *', SwigDelegatingPrinter) + #swig_printer.add('DOH *', SwigDelegatingPrinter) + #swig_printer.add('const DOH *', SwigDelegatingPrinter) + + print_("Loaded swig printers\n"); + +def enableGdbPrintWorkaround(): + global GDB_FLATTENED_CHILDREN_WORKAROUND + GDB_FLATTENED_CHILDREN_WORKAROUND = True + +def setChildrenRecursionLevel(level): + global CHILDREN_MAX_RECURSION_LEVEL + CHILDREN_MAX_RECURSION_LEVEL = level + +build_swig_printer() diff --git a/configure.ac b/configure.ac index 5b6441b86..72b507662 100644 --- a/configure.ac +++ b/configure.ac @@ -1107,6 +1107,213 @@ AC_SUBST(JAVALDSHARED) AC_SUBST(JAVACXXSHARED) AC_SUBST(JAVACFLAGS) +#---------------------------------------------------------------- +# Look for JAVASCRIPT +#---------------------------------------------------------------- +AC_ARG_WITH(javascript, AS_HELP_STRING([--without-javascript], [Disable JAVASCRIPT]), [with_javascript="$withval"], [with_javascript=yes]) + +# First, check for "--without-javascript" or "--with-javascript=no". +if test x"${with_javascript}" = xno -o x"${with_alllang}" = xno ; then + AC_MSG_NOTICE([Disabling Javascript]) + JAVASCRIPT= +else + #---------------------------------------------------------------- + # General Javascript settings shared by JSC and V8 + #---------------------------------------------------------------- + + case $host in + *-*-cygwin* | *-*-mingw*) + JSLIBRARYPREFIX="" + ;; + *) + JSLIBRARYPREFIX="lib" + ;; + esac + + case $host in + *-*-darwin*) + JSSO=".dylib" + JSLDSHARED='$(CC) -dynamiclib' + JSCXXSHARED='$(CXX) -dynamiclib' + ;; + *) + JSSO=$SO + JSLDSHARED='$(LDSHARED)' + JSCXXSHARED='$(CXXSHARED)' + ;; + esac + + #---------------------------------------------------------------- + # Look for JavascriptCore (Webkit) settings (JSCOREINCDIR, JSCOREDYNAMICLINKING) + #---------------------------------------------------------------- + + # check for include files + AC_MSG_CHECKING(for include file JavaScriptCore/JavaScript.h) + AC_ARG_WITH(jscoreinc, [ --with-jscinc=path Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=]) + + if test -z "$JSCOREINCDIR"; then + JSCOREINCDIR="/usr/include/ /usr/local/include/" + + # Add in default directory for JavaScriptCore headers for Linux and MacOSX + case $host in + *-*-linux*) + JSCOREINCDIR="/usr/include/webkit-1.0/ /usr/include/webkitgtk-1.0/ /usr/local/include/webkit-1.0/JavaScriptCore/ $JSCOREINCDIR" + ;; + *-*-darwin*) + JSCOREINCDIR="/System/Library/Frameworks/JavaScriptCore.framework/Headers/ $JSCOREINCDIR" + ;; + *) + ;; + esac + fi + + for d in $JSCOREINCDIR ; do + if test -r "$d/JavaScriptCore/JavaScript.h" || test -r "$d/JavaScript.h" ; then + AC_MSG_RESULT($d) + JSCOREINCDIR=$d + JSCOREINC=-I\"$d\" + break + fi + done + + if test "$JSCOREINC" = "" ; then + AC_MSG_RESULT(not found) + fi + + # check for JavaScriptCore/Webkit libraries + AC_ARG_WITH(jscorelib,[ --with-jsclib =path Set location of the JavaScriptCore/Webkit library directory],[JSCORELIB="-L$withval"], [JSCORELIB=]) + AC_MSG_CHECKING(for JavaScriptCore/Webkit library) + + # look for the library when not provided + if test -z "$JSCORELIB"; then + case $host in + *-*-linux*) + dirs="/usr/lib/ /usr/local/lib/" + for i in $dirs ; do + if test -r $i/libwebkit-1.0.la; then + AC_MSG_RESULT($i) + JSCORELIB="-L$i -lwebkit-1.0" + break + fi + + if test -r $i/libjavascriptcoregtk-1.0.so; then + AC_MSG_RESULT($i) + JSCORELIB="-L$i -ljavascriptcoregtk-1.0" + break + fi + + if test -r $i/libwebkitgtk-1.0.so; then + AC_MSG_RESULT($i) + JSCORELIB="-L$i -lwebkitgtk-1.0" + break + fi + done + + if test -z "$JSCORELIB"; then + AC_MSG_RESULT(not found) + JSCENABLED=0 + else + JSCOREDYNAMICLINKING="$JSCORELIB" + JSCENABLED=1 + fi + ;; + *-*-darwin*) + JSCOREDYNAMICLINKING="-framework JavaScriptCore" + ;; + *) + ;; + esac + fi + + #---------------------------------------------------------------- + # Look for V8 settings (JSV8INCDIR, JSV8DYNAMICLINKING) + #---------------------------------------------------------------- + + # check for include files + AC_MSG_CHECKING(for include file v8.h) + AC_ARG_WITH(jsv8inc, [ --with-v8inc=path Set location of Javascript include directory], [JSV8INCDIR="$withval"]) + + # if not include dir is specified we try to find + if test -z "$JSV8INCDIR"; then + # Add in default directory for JavaScriptCore headers for Linux and MacOSX + case $host in + *-*-linux*) + JSV8INCDIR="/usr/include /usr/local/include/ $JSV8INCDIR" + ;; + *-*-darwin*) + JSV8INCDIR="$JSV8INCDIR" + ;; + *) + ;; + esac + fi + + for d in $JSV8INCDIR ; do + if test -r "$d/v8.h" ; then + JSV8INCDIR=$d + JSV8INC=-I\"$d\" + break + fi + done + + if test "$JSV8INC" = "" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($JSV8INCDIR) + fi + + # check for V8 library + AC_MSG_CHECKING(for v8 library) + AC_ARG_WITH(jsv8lib,[ --with-v8lib=path Set location of V8 library directory],[JSV8LIBDIR="$withval"], [JSV8LIB=]) + + v8libdirs="$JSV8LIBDIR /usr/lib/ /usr/local/lib/" + for d in $v8libdirs ; do + if test -r $d/libv8.so; then + JSV8LIBDIR=$d + JSV8LIB="-L$d -lv8" + break + fi + done + + if test "$JSV8LIB" = "" ; then + AC_MSG_RESULT(not found) + JSV8ENABLED=0 + else + AC_MSG_RESULT($JSV8LIBDIR) + JSV8ENABLED=1 + fi + + + # linking options + case $host in + *-*-darwin*) + JSV8DYNAMICLINKING="" # TODO: add osx configuration + ;; + *-*-linux*) + JSV8DYNAMICLINKING="$JSV8LIB" + ;; + *) + JSV8DYNAMICLINKING="" + ;; + esac + +fi + +AC_SUBST(JSCFLAGS) +AC_SUBST(JSCXXFLAGS) +AC_SUBST(JSLIBRARYPREFIX) +AC_SUBST(JSSO) +AC_SUBST(JSLDSHARED) +AC_SUBST(JSCXXSHARED) + +AC_SUBST(JSCOREINC) +AC_SUBST(JSCOREDYNAMICLINKING) +AC_SUBST(JSV8INC) +AC_SUBST(JSV8DYNAMICLINKING) + +AC_SUBST(JSCENABLED) +AC_SUBST(JSV8ENABLED) + #---------------------------------------------------------------- # Look for gcj #---------------------------------------------------------------- @@ -2242,6 +2449,8 @@ if test -z "$JAVA" || test -z "$JAVAC" || test -z "$JAVAINC" ; then fi AC_SUBST(SKIP_JAVA) +SKIP_JAVASCRIPT= +AC_SUBST(SKIP_JAVASCRIPT) SKIP_GUILE= if test -z "$GUILE" || test -z "$GUILE_LIBS" ; then @@ -2440,6 +2649,7 @@ AC_CONFIG_FILES([ \ Examples/test-suite/uffi/Makefile \ Examples/test-suite/r/Makefile \ Examples/test-suite/go/Makefile \ + Examples/test-suite/javascript/Makefile \ Lib/ocaml/swigp4.ml ]) AC_CONFIG_FILES([preinst-swig], [chmod +x preinst-swig])