diff --git a/.gitignore b/.gitignore index 48826d914..8d72cea5d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ # Editor files and various other junk .*.sw? *.bak +*.log +.DS_Store # Local PCRE pcre @@ -23,6 +25,7 @@ pcre *.so *.so.* *.dylib +*.bundle # C/C++ static libraries, based on: # https://github.com/github/gitignore/blob/master/C.gitignore @@ -71,6 +74,7 @@ Examples/xml/Makefile Source/Include/stamp-h1 Source/Include/swigconfig.h Source/Makefile +Tools/javascript/Makefile .deps config.log config.status @@ -85,6 +89,7 @@ Source/CParse/parser.c Source/CParse/parser.h Source/eswig swig +Tools/javascript/javascript # Generated documentation Doc/Manual/CCache.html @@ -102,6 +107,7 @@ Examples/test-suite/d/*/ Examples/test-suite/go/*/ Examples/test-suite/guile/*/ Examples/test-suite/java/*/ +Examples/test-suite/javascript/*/ Examples/test-suite/lua/*/ Examples/test-suite/mzscheme/*/ Examples/test-suite/ocaml/*/ @@ -114,6 +120,8 @@ Examples/test-suite/r/*/ Examples/test-suite/ruby/*/ Examples/test-suite/tcl/*/ Examples/test-suite/uffi/*/ +*_wrap.c +*_wrap.cxx # Python generated files, based on: # https://github.com/github/gitignore/blob/master/Python.gitignore diff --git a/.travis.yml b/.travis.yml index 5d47074e9..58b3e4ca6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ -language: cpp +language: c compiler: - - clang - gcc env: - SWIGLANG= @@ -14,6 +13,12 @@ matrix: env: SWIGLANG=guile - compiler: gcc env: SWIGLANG=java + - compiler: gcc + env: SWIGLANG=javascript ENGINE=node + - compiler: gcc + env: SWIGLANG=javascript ENGINE=jsc + - compiler: gcc + env: SWIGLANG=javascript ENGINE=v8 - compiler: gcc env: SWIGLANG=lua - compiler: gcc @@ -43,6 +48,7 @@ before_install: - if test -z "$SWIGLANG"; then sudo apt-get -qq install yodl; fi - if test "$SWIGLANG" = "csharp"; then sudo apt-get -qq install mono-devel; fi - if test "$SWIGLANG" = "go"; then go env | sed -e 's/^/export /' > goenvsetup && source goenvsetup && rm -f goenvsetup; fi # Until configure.ac is fixed + - if test "$SWIGLANG" = "javascript"; then sudo apt-get install -qq rlwrap python-software-properties && echo 'yes' | sudo add-apt-repository ppa:chris-lea/node.js && sudo apt-get -qq update && sudo apt-get install -qq nodejs libv8-dev libwebkitgtk-dev && sudo npm install -g node-gyp; fi - if test "$SWIGLANG" = "guile"; then sudo apt-get -qq install guile-2.0-dev; fi - if test "$SWIGLANG" = "lua"; then sudo apt-get -qq install lua5.1 liblua5.1-dev; fi - if test "$SWIGLANG" = "octave"; then sudo apt-get -qq install octave3.2 octave3.2-headers; fi 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/Javascript.html b/Doc/Manual/Javascript.html new file mode 100644 index 000000000..a53e2a7cd --- /dev/null +++ b/Doc/Manual/Javascript.html @@ -0,0 +1,770 @@ + + + + + + + SWIG AND JAVASCRIPT + + + + +
+
+ +
+
+
+

Overview

+

This chapter describes SWIG support for Javascript. The module is designed to support JavascriptCore and V8 as target engine. Currently only JavascriptCore support is implemented. JavaScriptCore is the built-in JavaScript engine for WebKit, whereas V8 is the engine used by Chromium.

+

JavaScript is a prototype-based scripting language that is dynamic, weakly typed and has first-class functions. Its arguably the most popular language for web development. C++, on the other hand, is statically typed, compiled, general purpose programming language. The approach I followed here is "Test driven" where I have written the examples/test-cases to be supported for Javascript one-by-one and implemented the required module files in parallel. The support for Javascript would be added similar to other supported target languages in swig. Swig comes with an "Examples" directory for Javascript like other supported language. The directory contains examples for every supported feature of the target language. There is also a test-suite directory for javascript which contains additional tests.

+

Preliminaries

+

In order to use this module, you will need to have installed javascriptcore and you can install it by installing package libwebkit-dev You can find out some necessary compiler/linker flag by

+
pkg-config javascriptcoregtk-1.0 --cflags --libs
+
+

Using the module

+

To generate an extension for JavascriptCore one would call swig as follows

+

swig -c++ -javascript -jsc example.i +
+

This generates a C++ source file containing the wrapper.

+

How does Javascript talk to C++?

+

JavascriptCore provides a C-API which allows to extend a Javascript interpreter with native methods and structures. Normally, this is used to implement the builtin features of the language. However, by extending the interpreter, it is also possible to add your own commands and variables. A reference manual of this API can be found here.

+

Typically, when you add a new command to the javascript interpreter you need to do two things: first you need to write a special "wrapper" function that serves as the glue between the interpreter and the underlying C function. Then you need to give the interpreter information about the wrapper by providing details about the name of the function, arguments, and so forth. The next few sections illustrate the process.

+

Wrapper functions

+

Suppose you have an ordinary C function like this :

+

int fact(int n) { + if (n <= 1) return 1; + else return n*fact(n-1); +} +
+

In order to access this function from a scripting language, it is necessary to write a special "wrapper" function that serves as the glue between the scripting language and the underlying C function. A wrapper function must do three things :

+ +

As an example, the javascript wrapper function for the fact() function above example might look like the following :

+

JSValueRef wrap_fact(JSContextRef context, JSObjectRef function, JSObjectRef globalobj, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + int arg1 = (int)JSValueToNumber(context, argv[0], NULL); + int arg2 = (int)JSValueToNumber(context, argv[1], NULL); + int result = (int)fact(arg1,arg2); + JSValueRef jsresult = JSValueMakeNumber(context, result); + return jsresult; +} +
+

Once you have created a wrapper function, the final step is to tell the javascript about the new function. This is done by register function called by the javascript when the module is loaded. For example, adding the above function to the javascript interpreter requires code like the following :

+

bool jsc_registerFunction(JSGlobalContextRef context, JSObjectRef object, + const char* functionName, JSObjectCallAsFunctionCallback callback) +{ + JSStringRef js_globalvarsclassname = JSStringCreateWithUTF8CString(globalvarsclassname); + JSObjectSetProperty(context,js_globalvarsclassname,JSObjectMakeFunctionWithCallback(context, + js_globalvarsclassname, callback), kJSPropertyAttributeNone,NULL); + JSStringRelease(jsstring); + return true; +} + +int example_init(JSContextRef context) { + JSObjectRef global; + ... + jsc_registerFunction(context, global, "fact", wrap_fact); + ... +} +
+

When executed, javascript will now have a new command called "fact" that you can use like any other Javascript command. Although the process of adding a new function to javascript has been illustrated, the procedure is almost identical for Perl and Python. Both require special wrappers to be written and both need additional initialization code.

+

Variable Linking

+

Variable linking refers to the problem of mapping a C/C++ global variable to a variable in the scripting language interpreter. For example, suppose you had the following variable:

+

double Foo = 3.5; +
+

To provide such access, variables are commonly manipulated using a pair of get/set functions. For example, whenever the value of a variable is read, a "get" function is invoked. Similarly, whenever the value of a variable is changed, a "set" function is called.

+

bool Foo_set(JSContextRef context, JSObjectRef globalobj, JSStringRef propertyName, JSValueRef value, + JSValueRef* exception) +{ + JSValueRef jsresult; + double arg1 = (double)JSValueToNumber(context, value, NULL); + Foo = arg1; + jscresult = JSValueMakeUndefined(context); + return jsresult; +} + +JSValueRef Foo_get(JSContextRef context, JSObjectRef globalobj, JSStringRef propertyName, JSValueRef* exception) +{ + JSValueRef jsresult; + double result = (double)Foo; + jsresult = JSValueMakeNumber(context, result); + return jsresult; +} +
+

In many languages, calls to the get/set functions can be attached to evaluation and assignment operators. Therefore, evaluating a variable such as Foo might implicitly call the get function. Similarly, typing Foo = 4 would call the underlying set function to change the value.

+

A tour of basic C/C++ wrapping

+

By default, SWIG tries to build a very natural javascript interface to your C/C++ code. Functions are wrapped as functions, classes are wrapped as classes, and so forth. This section briefly covers the essential aspects of this wrapping.

+

Modules

+

The SWIG %module directive specifies the name of the Javascript module. If you specify %module example, then everything is wrapped into a Javascript 'example' module. Underneath the covers, this module consists of a cpp source file example.cpp. When choosing a module name, make sure you don't use the same name as a built-in Javascript command or standard module name.

+

Global variables

+

C/C++ global variables are fully supported by SWIG. However, the underlying mechanism is somewhat different than you might expect due to the way that javascript works.

+

// SWIG interface file with global variables +%module example +... +%inline %{ +extern double Foo; +extern int gcd(int x, int y); +%} +... +
+

Now look at the javascript:

+

print("Global variable Foo=" + example.Foo); +example.Foo = 3.1415926; +print("Variable Foo changed to=" + example.Foo); +print("GCD of x and y is=" + example.gcd(x,y)); +
+

Constants and enums

+

C/C++ constants are installed as javascript objects containing the appropriate value. To create a constant, use #define, enum, or the %constant directive. For example:

+

#define ICONST 42 +#define FCONST 2.1828 +%constant int iconst = 37; +
+

In javascript they are treated as:

+

print("ICONST = " + example.ICONST + " (should be 42)\n"); +print("FCONST = " + example.FCONST + " (should be 2.1828)\n"); +print("iconst = " + example.iconst + " (should be 37)\n"); +
+

For enums, make sure that the definition of the enumeration actually appears in a header file or in the wrapper file somehow---if you just stick an enum in a SWIG interface without also telling the C compiler about it, the wrapper code won't compile. Enums are treated as constants.So if we have enums in c++ as:

+

void enum_test(color c, Foo::speed s); +
+

In javascript they are treated as:

+

example.enum_test(example.RED, example.Foo.IMPULSE); +example.enum_test(example.BLUE, example.Foo.WARP); +example.enum_test(example.GREEN, example.Foo.LUDICROUS); +
+

Inside the class

+

For class enums as below:

+

class Foo { +public: +Foo() { } +enum speed { IMPULSE, WARP, LUDICROUS }; +} +
+

In javascript they are treated as:

+

print(" Foo_IMPULSE =" + example.Foo.IMPULSE); +print(" Foo_WARP =" + example.Foo.WARP); +print(" Foo_LUDICROUS =" + example.Foo.LUDICROUS); +
+

Pointers

+

C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Here is a rather simple interface

+

/* File : example.i */ +%module example +%{ +extern void add(int *, int *, int *); +%} +
+

When wrapped, you will be able to use the functions in a natural way from javascript. For example:

+

// Call the add() function with some pointers +example.add(a, b, c); +
+

// In javascript the code look like as:

+

a = example.new_intp(); +example.intp_assign(a,37); +
+ +

C++ classes

+

C++ classes are wrapped by javascript classes as well. For example, if you have this class,

+

class Circle +{ +public: + Circle(); + Circle(double r); + double area(); + double radius; +}; +
+

you can use it in javascript like this:

+

print("Creating some objects:"); +c = new example.Circle(10); +print("area = " + c.area()); +
+

Class data members are accessed in the same manner as C structures.

+

Static class members and functions are mapped to javascript in a straight-forward manner:

+

class Spam { +public: + static void foo(); + static int bar; +}; +
+

In javascript, the static member can be access in this way:

+

// ----- Access a static member ----- +print("\nA access of static member is" + example.Spam.Foo); // access static member as properties of the class object. +
+

C++ inheritance

+

SWIG is fully aware of issues related to C++ inheritance. Therefore, if you have classes like this

+

class A { +public: + void foo(); + virtual void bar(); +}; +class B: public A { +public: + virtual void bar(); +}; +
+

Those classes are wrapped into a hierarchy of javascript classes that reflect the same inheritance structure. All of the usual javascript utility functions work normally:

+

var a = new example.A(); +a.foo(); +a.bar(); +var b = new example.B(); +b.foo(); +b.bar(); +print("b.cPtr = " + b.getCPtr()); +
+

C++ overloaded functions

+

C++ overloaded functions, methods, and constructors are mostly supported by SWIG. For example, if you have two functions like this:

+

void f(int val) { + std::cout << "Called f(int)." << std::endl; +} +void f(int val1, int val2) { + std::cout << "Called f(int, int)." << std::endl; +} +void f(const char* s) { + std::cout << "Called f(const char*)." << std::endl; +} +
+

You can use them in javascript in a straightforward manner:

+

example.f(1); +example.f(1, 2); +example.f("bla"); +
+

C++ operators

+

Certain C++ overloaded operators can be handled automatically by SWIG. Though, in javascript operator overloading is not possible. Instead one has to make use of the %rename feature.

+

For example, consider a class like this:

+

/* File : example.h */ +#include <math.h> +class Complex { +private: + double rpart, ipart; +public: + Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { } + Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { } + Complex &operator=(const Complex &c) { + rpart = c.rpart; + ipart = c.ipart; + return *this; + } + Complex operator+(const Complex &c) const { + return Complex(rpart+c.rpart, ipart+c.ipart); + } + Complex operator-(const Complex &c) const { + return Complex(rpart-c.rpart, ipart-c.ipart); + } + Complex operator*(const Complex &c) const { + return Complex(rpart*c.rpart - ipart*c.ipart, + rpart*c.ipart + c.rpart*ipart); + } + Complex operator-() const { + return Complex(-rpart, -ipart); + } + + double re() const { return rpart; } + double im() const { return ipart; } +}; +
+

When wrapped, it works like you expect:

+

a = new example.Complex(2,3); +b = new example.Complex(-5,10); + +print ("a =" + a); +print ("b =" + b); + +c = a.plus(b); + +print("c =" + c); +print("a*b =" + a.times(b)); +print("a-c =" + a.minus(c)); + +e = example.Complex.copy(a.minus(c)); +print("e =" + e); + +// Big expression +f = a.plus(b).times(c.plus(b.times(e))).plus(a.uminus()); +print("f =" + f); +
+

One restriction with operator overloading support is that SWIG is not able to fully handle operators that aren't defined as part of the class. For example, if you had code like this

+

class Complex { +... +friend Complex operator+(double, const Complex &c); +... +}; +
+

then SWIG ignores it and issues a warning. You can still wrap the operator, but you may have to encapsulate it in a special function. For example:

+

%rename(Complex_add_dc) operator+(double, const Complex &);

+

There are ways to make this operator appear as part of the class using the %extend directive.

+

C++ namespaces:

+

SWIG is aware of C++ namespaces, but namespace names do not appear in the module nor do namespaces result in a module that is broken up into submodules or packages. For example, if you have a file like this,

+

%module example +namespace nspace { +extern int gcd(int x, int y); +extern double Foo; +class Circle +{ +public: + Circle(); + Circle(double r); + double area(); + double radius; + }; +} +
+

for namespaces, you use the %feature directive in interface file. %feature attaches a new attribute to any parse tree node that matches given prototype.

+

/* File : example.i */ +%module example +%{ +#include "example.h" +%} +%feature("nspace", 1); +%include "example.h" +
+

it works in javascript as follows:

+

print("Global variable Foo=" + example.nspace.Foo); +example.nspace.Foo = 5; +print("Variable Foo changed to " + example.nspace.Foo); +print("GCD of number 6,18 is " + example.nspace.gcd(6,18)); +print("Creating some objects:"); +c = new example.nspace.Circle(10); +print("area = " + c.area()); +
+

If your program has more than one namespace, name conflicts (if any) can be resolved using %rename For example:

+

%rename(Bar_spam) Bar::spam; +namespace Foo { + int spam(); +} +namespace Bar { + int spam(); +} +
+

If you have more than one namespace and your want to keep their symbols separate, consider wrapping them as separate SWIG modules. For example, make the module name the same as the namespace and create extension modules for each namespace separately. If your program utilizes thousands of small deeply nested namespaces each with identical symbol names, well, then you get what you deserve. SWIG resolves overloaded functions and methods using a disambiguation scheme that ranks and sorts declarations according to a set of type-precedence rules. The order in which declarations appear in the input does not matter except in situations where ambiguity arises--in this case, the first declaration takes precedence.

+

C++ templates

+

C++ templates don't present a huge problem for SWIG. However, in order to create wrappers, you have to tell SWIG to create wrappers for a particular template instantiation. To do this, you use the %template directive. For example:

+

/* File : example.i */ +%module example +%{ +#include "example.h" +%} +/* Let's just grab the original header file here */ +%include "example.h" + +/* Now instantiate some specific template declarations */ +%template(maxint) max<int>; +%template(maxdouble) max<double>; +%template(vecint) vector<int>; +%template(vecdouble) vector<double>; +
+

In javascript:

+

//Call some templated functions +print(example.maxint(3,7)); +print(example.maxdouble(3.14,2.18)); + +// Create some class + +iv = new example.vecint(100); +dv = new example.vecdouble(1000); + +for(i=0;i<=100;i++) + iv.setitem(i,2*i); + +for(i=0;i<=1000;i++) + dv.setitem(i, 1.0/(i+1)); + +sum = 0; +for(i=0;i<=100;i++) + sum = sum + iv.getitem(i); + +print(sum); + +sum = 0.0; +for(i=0;i<=1000;i++) + sum = sum + dv.getitem(i); +print(sum); +
+

Exception handling

+

The SWIG %exception directive can be used to create a user-definable exception handler for converting exceptions in your C/C++ program into javascript exceptions. The chapter on customization features contains more details, but suppose you have a C++ class like the following:

+

Since several methods in this class can throw an exception for an out-of-bounds access, you might want to catch this in the javascript extension by writing the following in an interface file:

+

/* File : example.i */ +%module example +%{ +#include "example.h" +%} +%include "std_string.i" + +/* Let's just grab the original header file here */ +%include "example.h" +
+

Actually in JS there is no support for typed exceptions.For now there is support for integer and string exception. Example for integer exception

+

JSValueRef jsc_gcd(JSContextRef context, JSObjectRef function, JSObjectRef globalobj, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ +int arg1 = (int)JSValueToNumber(context, argv[0], NULL); +int arg2 = (int)JSValueToNumber(context, argv[1], NULL); +*exception = JSValueMakeNumber(context, 13); +int result = (int)gcd(arg1,arg2); +JSValueRef jsresult = JSValueMakeNumber(context, result); +
+

and for string exception:

+

JSValueRef wrap_gcd(JSContextRef context, JSObjectRef function, JSObjectRef globalobj, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ +int arg1 = (int)JSValueToNumber(context, argv[0], NULL); +int arg2 = (int)JSValueToNumber(context, argv[1], NULL); +JSStringRef message = JSStringCreateWithUTF8CString("This is a test error."); +*exception = JSValueMakeString(context, message); +JSStringRelease(message); +int result = (int)gcd(arg1,arg2); +JSValueRef jscresult = JSValueMakeNumber(context, result); +return jsresult; +} +
+

How to use generated modules?

+

Basically there is no standard extension mechanism in Javascript. We provided a custom interpreter with extension abilities. If JSC is embedded into a custom application, one has to make use of a generated module initializer function that allows easy extension of interpreter. The basic approach is as follows:

+

Basic Mechanism

+ +

Creating the context

+

JSGlobalContextRef context = JSGlobalContextCreate(NULL); +JSObjectRef globalObject = JSContextGetGlobalObject(context); +... +
+

Calling module initializer

+

extern int example_init(JSGlobalContextRef context); + ... + example_init(context); + ... +
+

Evaluate Javascript

+

// Evaluate the javascript +char* scriptContent = jsccreateStringWithContentsOfFile(scriptPath.c_str()); +JSStringRef jsScript; +if(!scriptContent) { + printf("FAIL: runme script could not be loaded.\n"); + failed = 1; + } + else { + JSValueRef ex; + jsScript = JSStringCreateWithUTF8CString(scriptContent); + JSValueRef jsResult = JSEvaluateScript(context, jsScript, 0, 0, 0, &ex); + if (!jsResult && ex) { + jsc_printError(context, ex, scriptPath); + failed = 1; + } + } + if (scriptContent != NULL) { + free(scriptContent); + } + JSStringRelease(jsScript); + JSGlobalContextRelease(context); + globalObject = 0; + for(std::vector<HANDLE>::iterator it = loaded_modules.begin(); + it != loaded_modules.end(); ++it) { + HANDLE handle = *it; + dlclose(handle); + } + if (failed) { + printf("FAIL: Some tests failed.\n"); + return 1; + } +} +
+

Typemaps

+

A typemap is nothing more than a code generation rule that is attached to a specific C datatype. For example, to convert integers from javascript to C, you might define a typemap like this:

+

%typemap(in) int { + $1 = ($1_ltype)JSValueToNumber(context, $input, NULL); %} + printf("Received an integer : %d\n",$1); +} +
+

Typemaps are always associated with some specific aspect of code generation. In this case, the "in" method refers to the conversion of input arguments to C/C++. The datatype int is the datatype to which the typemap will be applied. The supplied C code is used to convert values. In this code a number of special variable prefaced by a $ are used. The $1 variable is placeholder for a local variable of type int.

+

Javascript typemaps

+

The previous section illustrated an "in" typemap for converting javascript objects to C. A variety of different typemap methods are defined by the javascript module. For example, to convert a C integer back into a javascript object, you might define an "out" typemap like this:

+

%typemap(out) int { + $result = JSValueMakeNumber(context, $1); +} +
+

The Javascript module makes use of Swig's unified template library.

+

Typemap variables

+

Within typemap code, a number of special variables prefaced with a $ may appear. A full list of variables can be found in the "Typemaps" chapter. This is a list of the most common variables:

+

$1: A C local variable corresponding to the actual type specified in the %typemap directive. For input values, this is a C local variable that's supposed to hold an argument value. For output values, this is the raw result that's supposed to be returned to Javascript.

+

$input: A javascript Object * holding a raw javascript object with an argument or variable value.

+

$result: A javascript Object * that holds the result to be returned to javascript.

+

$1_name: The parameter name that was matched.

+

$1_type: The actual C datatype matched by the typemap.

+

$1_ltype: An assignable version of the datatype matched by the typemap (a type that can appear on the left-hand-side of a C assignment operation). This type is stripped of qualifiers and may be an altered version of $1_type. All arguments and local variables in wrapper functions are declared using this type so that their values can be properly assigned.

+

$symname: The javascript name of the wrapper function being created.

+

Javascript: Specification of a Code Generator for JSC

+

The module implementation tries to accomplish a separation of logic and code generation by making use of code templates. In the following, the templates are explained.

+

Top Level structure

+

The generated code consists of the following blocks:

+

<RUNTIME> +<INCLUDES> +<HELPER_FUNCTIONS> +<FUNCTION_WRAPPERS> +<INITIALIZER> +
+ +

INCLUDES

+

#include <JavaScriptCore/JavaScript.h> +<USER_DEFINED_INCLUDES> +
+

USER_DEFINED_INCLUDES: a module property

+

HELPER_FUNCTIONS

+

A lot of boiler-plate code can be shifted into static helper functions:

+

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

FUNCTION_WRAPPERS

+

There are different types of function wrappers: - Member Functions - Getproperty / Setproperty - Global Functions (global/namespace/class) - Constructors / Destructors

+

Member Functions

+

JSValueRef ${functionname}(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + ${LOCALS} + ${CODE} + return jsresult; + + goto fail; + fail: + return NULL; +} +
+ +

Setproperty

+

bool ${setname}(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) +{ + ${LOCALS} + ${CODE} + return jsresult; + + goto fail; + fail: + return NULL; +} +
+ +

Getproperty

+

JSValueRef ${getname}(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) +{ + ${LOCALS} + ${CODE} + return jsresult; + + goto fail; + fail: + return NULL; +} +
+ +

Global Functions

+

JSStaticValue ${namespace}_values[] = { + ${jsglobalvariables} + { 0, 0, 0, 0 } +}; +JSStaticFunction ${namespace}_functions[] = { + ${jsglobalfunctions} + { 0, 0, 0 } +}; +JSClassDefinition ${namespace}_classDefinition; +
+

Variable declaration

+

{"${propertyname}",${getname}, ${setname}, kJSPropertyAttributeNone} +
+

This is used to fill variable definition tables. kJSPropertyAttributeNone is JSC specific and means that the variable has a getter and setter. Even for read-only variables a setter is used which throws an exception.

+

Constructor

+

~~

+

JSObjectRef wrap_createclassnamemangled{overloadext}(JSContextRef context, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) { ${LOCALS} ${CODE} return SWIG_JSC_NewPointerObj(context, result, SWIGTYPE_${type_mangled}, SWIG_POINTER_OWN);

+
goto fail;
+fail:
+return NULL;
+
+

}

+
- `classname_mangled` is the mangled qualified class name,   e.g., `foo::A -> foo_A`
+- `LOCALS`: declarations for input arguments 
+- `CODE`: contains input marshalling, and the action 
+
+## Destructors
+
+

void wrap${classname_mangled}_finalize(JSObjectRef thisObject) { SWIG_PRV_DATA* t = (SWIG_PRV_DATA*)JSObjectGetPrivate(thisObject); if(t && t->swigCMemOwn) delete (${type}*)(t->swigCObject); if(t) delete t; }

+

- `classname_mangled` is the mangled qualified class name, e.g., `foo::A -> foo_A` + +## Initializer +
+

bool ${modulename}_initialize(JSGlobalContextRef context) { SWIG_InitializeModule(0);

+
JSObjectRef global_object = JSContextGetGlobalObject(context);
+
+/* Initialize the base swig type object */
+_SwigObject_objectDefinition.staticFunctions = _SwigObject_functions;
+_SwigObject_objectDefinition.staticValues = _SwigObject_values;
+_SwigObject_classRef = JSClassCreate(&_SwigObject_objectDefinition);
+
+/* Create objects for namespaces */
+${create_namespaces}
+
+/* Create classes */
+${initializercode}
+
+/* Register namespaces */
+${register_namespaces}
+
+return true;
+
+

}

+

## Class template defintions + +A class is specified by a static part (`*_classDefinition`) and a dynamic part (`*_objectDefinition`). +
+

${classname_mangled}_classDefinition.staticFunctions = ${classname_mangled}_staticFunctions; ${classname_mangled}_classDefinition.staticValues = ${classname_mangled}_staticValues; ${classname_mangled}_classDefinition.callAsConstructor = _wrap_create_${classname_mangled}; ${classname_mangled}_objectDefinition.staticValues = ${classname_mangled}_values; ${classname_mangled}_objectDefinition.staticFunctions = ${classname_mangled}_functions; ${classname_mangled}_objectDefinition.parentClass = ${base_classname}_classRef; JSClassRef ${classname_mangled}_classRef = JSClassCreate(&${classname_mangled}objectDefinition); SWIGTYPE${classtype_mangled}->clientdata = ${classname_mangled}_classRef;%}

+

Notes: +- `classname_mangled` is the mangled qualified class name, e.g., `foo::A -> foo_A` + which is retrieved by `Swig_name_mangle(Getattr(n, "name"))` +- ClassDefinitions are built using the staticValues array and the staticFunction array. The staticValues and staticFunctions arrays are the simplest and most efficient means for vending custom properties to the class object. + +## Inheritance +
+

{${classname_mangled}_objectDefinition.parentClass = ${base_classname}_classRef};

+

- `classname_mangled` is the mangled qualified class name, e.g., `foo::A -> foo_A` +- Note: multiple inheritance is not possible; thus we will always take the first parent class + +## Namespaces + +Namespaces are objects without class templates. i.e., instances are created, referenced locally, used as contexts for other registrations, and stored in the according parent contexts. +
+

${namespace}_classDefinition.staticFunctions = ${namespace}_functions; ${namespace}_classDefinition.staticValues = ${namespace}_values; JSObjectRef ${namespace}_object = JSObjectMake(context, JSClassCreate(&${namespace}_classDefinition), NULL);

+

## Registration + +The registration part consists of registering classes at contexts (i.e., global or namespace), methods and properties at classes or contexts, and namespaces as objects at parent contexts. + +* Global functions +
+

JS_registerFunction(${context}, ${context_object}, "${functionname}", ${functionwrapper}

+

* Classes +
+

JS_registerClass(context, ${namespace}_object, "${classname}", &${classname_mangled}_classDefinition)

+

Note: every class template has an associated constructor function wrapper, which is registered here + +* Namespaces +
+

${namespace}_classDefinition.staticFunctions = ${namespace}_functions; ${namespace}_classDefinition.staticValues = ${namespace}_values; JSObjectRef ${namespace}_object = JSObjectMake(context, JSClassCreate(&${namespace}_classDefinition), NULL);

+

Namespaces are registered using: +
+

JS_registerNamespace(context, ${namespace}_object, ${parent_namespace}_object, "${namespace}");

+

~~

+
+ + diff --git a/Doc/Manual/chapters b/Doc/Manual/chapters index 45d35e793..c5f655254 100644 --- a/Doc/Manual/chapters +++ b/Doc/Manual/chapters @@ -23,6 +23,7 @@ D.html Go.html Guile.html Java.html +Javascript.html Lisp.html Lua.html Modula3.html 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 218d8eca5..c06f09f9a 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -589,6 +589,86 @@ java_clean: rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@JAVASO@ +################################################################## +##### JAVASCRIPT ###### +################################################################## + +# Note: These targets are also from within Makefiles in the Example directories. +# There is a common makefile, 'Examples/javascript/js_example.mk' to simplify +# create a configuration for a new example. + + +ROOT_DIR = @ROOT_DIR@ +JSCFLAGS = @JSCFLAGS@ +JSCXXFLAGS = @JSCXXFLAGS@ +JSINCLUDES = @JSCOREINC@ @JSV8INC@ +JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@ +JSLIBRARYPREFIX = @JSLIBRARYPREFIX@ +JSSO =@JSSO@ +JSLDSHARED = @JSLDSHARED@ +JSCXXSHARED = @JSCXXSHARED@ + +SWIGJS = $(SWIG) -javascript + +# ---------------------------------------------------------------- +# Creating and building Javascript wrappers +# ---------------------------------------------------------------- + +javascript_wrapper: + $(SWIGJS) $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.c $(INTERFACEPATH) + +javascript_wrapper_cpp: $(SRCS) + $(SWIGJS) -c++ $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.cxx $(INTERFACEPATH) + +javascript_build: $(SRCS) + $(CC) -c $(CCSHARED) $(CFLAGS) $(JSCFLAGS) $(ISRCS) $(SRCS) $(INCLUDES) $(JSINCLUDES) + $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +javascript_build_cpp:: $(SRCS) + $(CXX) -c $(CCSHARED) $(CFLAGS) $(JSCFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(JSINCLUDES) + $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +# TODO: make node-gyp configurable and detected via ./configure +javascript_build_node: $(SRCS) + node-gyp --loglevel=silent configure build 1>>/dev/null + +# These targets are used by the test-suite: + +javascript: $(SRCS) javascript_custom_interpreter + $(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) javascript_custom_interpreter + $(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) + +# ----------------------------------------------------------------- +# Running a javascript example +# ----------------------------------------------------------------- + +javascript_custom_interpreter: + (cd $(ROOT_DIR)/Tools/javascript && $(MAKE) JSENGINE='$(JSENGINE)') + +javascript_run: javascript_custom_interpreter + $(ROOT_DIR)/Tools/javascript/javascript -$(JSENGINE) -L $(TARGET) runme.js + +# TODO: make node configurable and detected via ./configure +javascript_run_node: + node runme.js + +# ----------------------------------------------------------------- +# Cleaning the javascript examples +# ----------------------------------------------------------------- + +javascript_clean: + rm -rf build + rm -f *_wrap* runme + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@JSSO@ *.$(SO) + (cd $(ROOT_DIR)/Tools/javascript && $(MAKE) -s clean) + ################################################################## ##### ANDROID ###### ################################################################## diff --git a/Examples/javascript/check.list b/Examples/javascript/check.list new file mode 100644 index 000000000..040267812 --- /dev/null +++ b/Examples/javascript/check.list @@ -0,0 +1,13 @@ +class +constant +enum +#exception +functor +#namespace +operator +overload +pointer +#reference +simple +template +variables diff --git a/Examples/javascript/class/Makefile b/Examples/javascript/class/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/class/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/class/binding.gyp b/Examples/javascript/class/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/class/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/class/example.cxx b/Examples/javascript/class/example.cxx new file mode 100755 index 000000000..e23fa6f73 --- /dev/null +++ b/Examples/javascript/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ +#include +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} diff --git a/Examples/javascript/class/example.h b/Examples/javascript/class/example.h new file mode 100755 index 000000000..64b7684fa --- /dev/null +++ b/Examples/javascript/class/example.h @@ -0,0 +1,34 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void); + virtual double perimeter(void); +}; diff --git a/Examples/javascript/class/example.i b/Examples/javascript/class/example.i new file mode 100755 index 000000000..75700b305 --- /dev/null +++ b/Examples/javascript/class/example.i @@ -0,0 +1,10 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/javascript/class/example.js b/Examples/javascript/class/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/class/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/class/runme.js b/Examples/javascript/class/runme.js new file mode 100755 index 000000000..e1d5d9797 --- /dev/null +++ b/Examples/javascript/class/runme.js @@ -0,0 +1,46 @@ +var example = require("./example"); + +// ----- Object creation ----- + +console.log("Creating some objects:"); +c = new example.Circle(10); +console.log("Created circle " + c); +s = new example.Square(10); +console.log("Created square " + s); + +// ----- Access a static member ----- +console.log("\nA total of " + example.Shape.nshapes + " shapes were created"); // access static member as properties of the class object + +// ----- Member data access ----- +// Set the location of the object. +// Note: methods in the base class Shape are used since +// x and y are defined there. + +c.x = 20; +c.y = 30; +s.x = -10; +s.y = 5; + +console.log("\nHere is their new position:"); +console.log("Circle = (" + c.x + "," + c.y + ")"); +console.log("Square = (" + s.x + "," + s.y + ")"); + +// ----- Call some methods ----- +console.log("\nHere are some properties of the shapes:"); +console.log("Circle:"); +console.log("area = " + c.area() + ""); +console.log("perimeter = " + c.perimeter() + ""); +console.log("\n"); +console.log("Square:"); +console.log("area = " + s.area() + ""); +console.log("perimeter = " + s.perimeter() + ""); + +// ----- Delete everything ----- +console.log("\nGuess I'll clean up now"); +// Note: this invokes the virtual destructor +delete c; +delete s; + +console.log(example.Shape.nshapes + " shapes remain"); + +console.log("Goodbye"); diff --git a/Examples/javascript/constant/Makefile b/Examples/javascript/constant/Makefile new file mode 100755 index 000000000..a2570636e --- /dev/null +++ b/Examples/javascript/constant/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../js_example.mk diff --git a/Examples/javascript/constant/binding.gyp b/Examples/javascript/constant/binding.gyp new file mode 100644 index 000000000..69af46b22 --- /dev/null +++ b/Examples/javascript/constant/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/constant/example.h b/Examples/javascript/constant/example.h new file mode 100644 index 000000000..2c88ebd1e --- /dev/null +++ b/Examples/javascript/constant/example.h @@ -0,0 +1,8 @@ +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" +#define EXTERN extern +#define FOO (ICONST + BAR) diff --git a/Examples/javascript/constant/example.i b/Examples/javascript/constant/example.i new file mode 100755 index 000000000..a6d28e7c9 --- /dev/null +++ b/Examples/javascript/constant/example.i @@ -0,0 +1,24 @@ +/* File : example.i */ +%module example + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + +/* The following directives also produce constants */ +%constant int iconst = 37; +%constant double fconst = 3.14; diff --git a/Examples/javascript/constant/example.js b/Examples/javascript/constant/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/constant/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/constant/runme.js b/Examples/javascript/constant/runme.js new file mode 100755 index 000000000..2188bf099 --- /dev/null +++ b/Examples/javascript/constant/runme.js @@ -0,0 +1,14 @@ +var example = require("./example"); + +console.log("ICONST = " + example.ICONST + " (should be 42)\n"); +console.log("FCONST = " + example.FCONST + " (should be 2.1828)\n"); +console.log("CCONST = " + example.CCONST + " (should be 'x')\n"); +console.log("CCONST2 = " + example.CCONST2 + " (this should be on a new line)\n"); +console.log("SCONST = " + example.SCONST + " (should be 'Hello World')\n"); +console.log("SCONST2 = " + example.SCONST2 + " (should be '\"Hello World\"')\n"); +console.log("EXPR = " + example.EXPR + " (should be 48.5484)\n"); +console.log("iconst = " + example.iconst + " (should be 37)\n"); +console.log("fconst = " + example.fconst + " (should be 3.14)\n"); + +console.log("EXTERN = " + example.EXTERN + " (should be undefined)\n"); +console.log("FOO = " + example.FOO + " (should be undefined)\n"); diff --git a/Examples/javascript/enum/Makefile b/Examples/javascript/enum/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/enum/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/enum/binding.gyp b/Examples/javascript/enum/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/enum/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/enum/example.cxx b/Examples/javascript/enum/example.cxx new file mode 100755 index 000000000..6785e57ac --- /dev/null +++ b/Examples/javascript/enum/example.cxx @@ -0,0 +1,37 @@ +/* File : example.c */ + +#include "example.h" +#include + +void Foo::enum_test(speed s) { + if (s == IMPULSE) { + printf("IMPULSE speed\n"); + } else if (s == WARP) { + printf("WARP speed\n"); + } else if (s == LUDICROUS) { + printf("LUDICROUS speed\n"); + } else { + printf("Unknown speed\n"); + } +} + +void enum_test(color c, Foo::speed s) { + if (c == RED) { + printf("color = RED, "); + } else if (c == BLUE) { + printf("color = BLUE, "); + } else if (c == GREEN) { + printf("color = GREEN, "); + } else { + printf("color = Unknown color!, "); + } + if (s == Foo::IMPULSE) { + printf("speed = IMPULSE speed\n"); + } else if (s == Foo::WARP) { + printf("speed = WARP speed\n"); + } else if (s == Foo::LUDICROUS) { + printf("speed = LUDICROUS speed\n"); + } else { + printf("speed = Unknown speed!\n"); + } +} diff --git a/Examples/javascript/enum/example.h b/Examples/javascript/enum/example.h new file mode 100755 index 000000000..9119cd9fc --- /dev/null +++ b/Examples/javascript/enum/example.h @@ -0,0 +1,13 @@ +/* File : example.h */ + +enum color { RED, BLUE, GREEN }; + +class Foo { + public: + Foo() { } + enum speed { IMPULSE=10, WARP=20, LUDICROUS=30 }; + void enum_test(speed s); +}; + +void enum_test(color c, Foo::speed s); + diff --git a/Examples/javascript/enum/example.i b/Examples/javascript/enum/example.i new file mode 100755 index 000000000..23ee8a822 --- /dev/null +++ b/Examples/javascript/enum/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/javascript/enum/example.js b/Examples/javascript/enum/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/enum/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/enum/runme.js b/Examples/javascript/enum/runme.js new file mode 100755 index 000000000..d4e89e8c8 --- /dev/null +++ b/Examples/javascript/enum/runme.js @@ -0,0 +1,34 @@ +var example = require("./example"); + +// ----- Object creation ----- + +// Print out the value of some enums +console.log("*** color ***"); +console.log(" RED =" + example.RED); +console.log(" BLUE =" + example.BLUE); +console.log(" GREEN =" + example.GREEN); + +console.log("\n*** Foo::speed ***"); +console.log(" Foo_IMPULSE =" + example.Foo.IMPULSE); +console.log(" Foo_WARP =" + example.Foo.WARP); +console.log(" Foo_LUDICROUS =" + example.Foo.LUDICROUS); + +console.log("\nTesting use of enums with functions\n"); + +example.enum_test(example.RED, example.Foo.IMPULSE); +example.enum_test(example.BLUE, example.Foo.WARP); +example.enum_test(example.GREEN, example.Foo.LUDICROUS); +example.enum_test(1234,5678); + +console.log("\nTesting use of enum with class method"); +f = new example.Foo(); + +f.enum_test(example.Foo.IMPULSE); +f.enum_test(example.Foo.WARP); +f.enum_test(example.Foo.LUDICROUS); + +// enum value BLUE of enum color is accessed as property of cconst +console.log("example.BLUE= " + example.BLUE); + +// enum value LUDICROUS of enum Foo::speed is accessed as as property of cconst +console.log("example.speed.LUDICROUS= " + example.Foo.LUDICROUS); diff --git a/Examples/javascript/exception/Makefile b/Examples/javascript/exception/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/exception/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/exception/binding.gyp b/Examples/javascript/exception/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/exception/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/exception/example.cxx b/Examples/javascript/exception/example.cxx new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Examples/javascript/exception/example.cxx @@ -0,0 +1 @@ + diff --git a/Examples/javascript/exception/example.h b/Examples/javascript/exception/example.h new file mode 100644 index 000000000..7cf917d01 --- /dev/null +++ b/Examples/javascript/exception/example.h @@ -0,0 +1,53 @@ +/* File : example.h */ + +#include +#ifndef SWIG +struct A { +}; +#endif + +class Exc { +public: + Exc(int c, const char *m) { + code = c; + strncpy(msg,m,256); + } + int code; + char msg[256]; +}; + +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif + +class Test { +public: + int simple() throw(int) { + throw(37); + return 1; + } + int message() throw(const char *) { + throw("I died."); + return 1; + } + int hosed() throw(Exc) { + throw(Exc(42,"Hosed")); + return 1; + } + int unknown() throw(A*) { + static A a; + throw &a; + return 1; + } + int multi(int x) throw(int, const char *, Exc) { + if (x == 1) throw(37); + if (x == 2) throw("Bleah!"); + if (x == 3) throw(Exc(42,"No-go-diggy-die")); + return 1; + } +}; + +#if defined(_MSC_VER) + #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif + diff --git a/Examples/javascript/exception/example.i b/Examples/javascript/exception/example.i new file mode 100644 index 000000000..08672c3a8 --- /dev/null +++ b/Examples/javascript/exception/example.i @@ -0,0 +1,12 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%include "std_string.i" + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/javascript/exception/example.js b/Examples/javascript/exception/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/exception/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/exception/runme.js b/Examples/javascript/exception/runme.js new file mode 100644 index 000000000..977f51ebc --- /dev/null +++ b/Examples/javascript/exception/runme.js @@ -0,0 +1,64 @@ +var example = require("./example"); + +console.log("Trying to catch some exceptions."); +t = new example.Test(); +try{ + t.unknown(); + throw -1; +} catch(error) +{ + if(error == -1) { + console.log("t.unknown() didn't throw"); + } else { + console.log("successfully catched throw in Test::unknown()."); + } +} + +try{ + t.simple(); + throw -1; +} +catch(error){ + if(error == -1) { + console.log("t.simple() did not throw"); + } else { + console.log("successfully catched throw in Test::simple()."); + } +} + +try{ + t.message(); + throw -1; +} catch(error){ + if(error == -1) { + console.log("t.message() did not throw"); + } else { + console.log("successfully catched throw in Test::message()."); + } +} + +try{ + t.hosed(); + throw -1; +} +catch(error){ + if(error == -1) { + console.log("t.hosed() did not throw"); + } else { + console.log("successfully catched throw in Test::hosed()."); + } +} + +for (var i=1; i<4; i++) { + try{ + t.multi(i); + throw -1; + } + catch(error){ + if(error == -1) { + console.log("t.multi(" + i + ") did not throw"); + } else { + console.log("successfully catched throw in Test::multi()."); + } + } +} diff --git a/Examples/javascript/functor/Makefile b/Examples/javascript/functor/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/functor/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/functor/binding.gyp b/Examples/javascript/functor/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/functor/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/functor/example.cxx b/Examples/javascript/functor/example.cxx new file mode 100644 index 000000000..e69de29bb diff --git a/Examples/javascript/functor/example.i b/Examples/javascript/functor/example.i new file mode 100644 index 000000000..0450c2124 --- /dev/null +++ b/Examples/javascript/functor/example.i @@ -0,0 +1,25 @@ +/* File : example.i */ +%module example + + +%inline %{ +// From B. Strousjoup, "The C++ Programming Language, Third Edition", p. 514 +template class Sum { + T res; +public: + Sum(T i = 0) : res(i) { } + void operator() (T x) { res += x; } + T result() const { return res; } +}; + +%} + +%rename(call) *::operator(); // the fn call operator + +// Instantiate a few versions +%template(intSum) Sum; +%template(doubleSum) Sum; + + + + diff --git a/Examples/javascript/functor/example.js b/Examples/javascript/functor/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/functor/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/functor/runme.js b/Examples/javascript/functor/runme.js new file mode 100644 index 000000000..dc12470f4 --- /dev/null +++ b/Examples/javascript/functor/runme.js @@ -0,0 +1,15 @@ +var example = require("./example"); + +a = new example.intSum(0); +b = new example.doubleSum(100.0); + +// Use the objects. They should be callable just like a normal +// javascript function. + +for (i=1;i<=100;i++) + a.call(i); // Note: function call + b.call(Math.sqrt(i)); // Note: function call + +console.log(a.result()); +console.log(b.result()); + diff --git a/Examples/javascript/js_example.mk b/Examples/javascript/js_example.mk new file mode 100644 index 000000000..6cb6eb113 --- /dev/null +++ b/Examples/javascript/js_example.mk @@ -0,0 +1,52 @@ +# Note: as a convention an example must be in a child directory of this. +# These paths are relative to such an example directory +EXAMPLES_TOP=../.. +SWIG_TOP=../../.. + +SWIG = $(SWIG_TOP)/preinst-swig + +# TODO: we could only set these only if not yet set... +JS_SCRIPT = runme.js +TARGET = example +INTERFACE = example.i + +ifneq (, $(ENGINE)) + JSENGINE=$(ENGINE) +else + JSENGINE=node +endif + +SWIGOPT=-$(JSENGINE) + +ifeq (node,$(JSENGINE)) + +build: wrapper + $(MAKE) -f $(EXAMPLES_TOP)/Makefile CXXSRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' JSENGINE='$(JSENGINE)' javascript_build_node + +else + +build: wrapper + $(MAKE) -f $(EXAMPLES_TOP)/Makefile CXXSRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' JSENGINE='$(JSENGINE)' javascript_build_cpp + +endif + +wrapper: + $(MAKE) -f $(EXAMPLES_TOP)/Makefile CXXSRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' javascript_wrapper_cpp + +ifeq (node,$(JSENGINE)) + +check: build + $(MAKE) -f $(EXAMPLES_TOP)/Makefile JSENGINE='$(JSENGINE)' javascript_run_node + +else + +check: build + $(MAKE) -f $(EXAMPLES_TOP)/Makefile JSENGINE='$(JSENGINE)' TARGET='$(TARGET)' javascript_run + +endif + +clean: + $(MAKE) -f $(EXAMPLES_TOP)/Makefile javascript_clean diff --git a/Examples/javascript/namespace/Makefile b/Examples/javascript/namespace/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/namespace/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/namespace/binding.gyp b/Examples/javascript/namespace/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/namespace/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/namespace/example.cxx b/Examples/javascript/namespace/example.cxx new file mode 100644 index 000000000..5beeb09fe --- /dev/null +++ b/Examples/javascript/namespace/example.cxx @@ -0,0 +1,36 @@ +/* File : example.c */ + +#include +#include "example.h" + +#define M_PI 3.14159 + + +/* A global variable */ +namespace nspace +{ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + +Circle::Circle(): radius(1.0) {} + +Circle::Circle(double r): radius(r) { + std::cout << "created Circle with r=" << radius << std::endl; +} + +double Circle::area() { + std::cout << "Circle::area called, r=" << radius << std::endl; + return M_PI*radius*radius; +} +} diff --git a/Examples/javascript/namespace/example.h b/Examples/javascript/namespace/example.h new file mode 100644 index 000000000..7f76c2f07 --- /dev/null +++ b/Examples/javascript/namespace/example.h @@ -0,0 +1,20 @@ + +namespace nspace { + +extern int gcd(int x, int y); +extern double Foo; + +class Circle +{ +public: + Circle(); + + Circle(double r); + + double area(); + + double radius; + +}; + +} diff --git a/Examples/javascript/namespace/example.i b/Examples/javascript/namespace/example.i new file mode 100644 index 000000000..e14b10b44 --- /dev/null +++ b/Examples/javascript/namespace/example.i @@ -0,0 +1,10 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%feature("nspace", 1); + +%include "example.h" diff --git a/Examples/javascript/namespace/example.js b/Examples/javascript/namespace/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/namespace/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/namespace/runme.js b/Examples/javascript/namespace/runme.js new file mode 100644 index 000000000..08e0d3769 --- /dev/null +++ b/Examples/javascript/namespace/runme.js @@ -0,0 +1,10 @@ +var example = require("./example"); + +console.log("Global variable Foo=" + example.nspace.Foo); +example.nspace.Foo = 5; +console.log("Variable Foo changed to " + example.nspace.Foo); +console.log("GCD of number 6,18 is " + example.nspace.gcd(6,18)); + +console.log("Creating some objects:"); +c = new example.nspace.Circle(10); +console.log("area = " + c.area()); diff --git a/Examples/javascript/operator/Makefile b/Examples/javascript/operator/Makefile new file mode 100755 index 000000000..a2570636e --- /dev/null +++ b/Examples/javascript/operator/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../js_example.mk diff --git a/Examples/javascript/operator/binding.gyp b/Examples/javascript/operator/binding.gyp new file mode 100644 index 000000000..69af46b22 --- /dev/null +++ b/Examples/javascript/operator/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/operator/example.h b/Examples/javascript/operator/example.h new file mode 100644 index 000000000..4da6a2307 --- /dev/null +++ b/Examples/javascript/operator/example.h @@ -0,0 +1,36 @@ +/* File : example.h */ +#include + +class Complex { +private: + double rpart, ipart; +public: + Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { } + Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { } + Complex &operator=(const Complex &c) { + rpart = c.rpart; + ipart = c.ipart; + return *this; + } + Complex operator+(const Complex &c) const { + return Complex(rpart+c.rpart, ipart+c.ipart); + } + Complex operator-(const Complex &c) const { + return Complex(rpart-c.rpart, ipart-c.ipart); + } + Complex operator*(const Complex &c) const { + return Complex(rpart*c.rpart - ipart*c.ipart, + rpart*c.ipart + c.rpart*ipart); + } + Complex operator-() const { + return Complex(-rpart, -ipart); + } + + double re() const { return rpart; } + double im() const { return ipart; } +}; + + + + + diff --git a/Examples/javascript/operator/example.i b/Examples/javascript/operator/example.i new file mode 100644 index 000000000..7a1bd45e1 --- /dev/null +++ b/Examples/javascript/operator/example.i @@ -0,0 +1,34 @@ +/* File : example.i */ +%module example +#pragma SWIG nowarn=SWIGWARN_IGNORE_OPERATOR_EQ +%{ +#include "example.h" +%} + +/* This header file is a little tough to handle because it has overloaded + operators and constructors. We're going to try and deal with that here */ + +/* This turns the copy constructor in a function ComplexCopy() that can + be called */ + +%rename(assign) Complex::operator=; +%rename(plus) Complex::operator+; +%rename(minus) Complex::operator-(const Complex &) const; +%rename(uminus) Complex::operator-() const; +%rename(times) Complex::operator*; + +/* Now grab the original header file */ +%include "example.h" + +/* An output method that turns a complex into a short string */ +%extend Complex { + char *toString() { + static char temp[512]; + sprintf(temp,"(%g,%g)", $self->re(), $self->im()); + return temp; + } + static Complex* copy(const Complex& c) { + return new Complex(c); + } +}; + diff --git a/Examples/javascript/operator/example.js b/Examples/javascript/operator/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/operator/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/operator/runme.js b/Examples/javascript/operator/runme.js new file mode 100644 index 000000000..a700918d6 --- /dev/null +++ b/Examples/javascript/operator/runme.js @@ -0,0 +1,25 @@ +var example = require("./example"); + +a = new example.Complex(2,3); +b = new example.Complex(-5,10); + +console.log ("a =" + a); +console.log ("b =" + b); + +c = a.plus(b); + +console.log("c =" + c); +console.log("a*b =" + a.times(b)); +console.log("a-c =" + a.minus(c)); + +e = example.Complex.copy(a.minus(c)); +console.log("e =" + e); + +// Big expression +f = a.plus(b).times(c.plus(b.times(e))).plus(a.uminus()); +console.log("f =" + f); + + + + + diff --git a/Examples/javascript/overload/Makefile b/Examples/javascript/overload/Makefile new file mode 100755 index 000000000..a2570636e --- /dev/null +++ b/Examples/javascript/overload/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../js_example.mk diff --git a/Examples/javascript/overload/binding.gyp b/Examples/javascript/overload/binding.gyp new file mode 100644 index 000000000..69af46b22 --- /dev/null +++ b/Examples/javascript/overload/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/overload/example.h b/Examples/javascript/overload/example.h new file mode 100644 index 000000000..2f112f1e1 --- /dev/null +++ b/Examples/javascript/overload/example.h @@ -0,0 +1,28 @@ +#include + +void f() { + std::cout << "Called f()." << std::endl; +} + +void f(int val) { + std::cout << "Called f(int)." << std::endl; +} +void f(int val1, int val2) { + std::cout << "Called f(int, int)." << std::endl; +} + +void f(const char* s) { + std::cout << "Called f(const char*)." << std::endl; +} + +void f(bool val) { + std::cout << "Called f(bool)." << std::endl; +} + +void f(long val) { + std::cout << "Called f(long)." << std::endl; +} + +void f(double val) { + std::cout << "Called f(double)." << std::endl; +} diff --git a/Examples/javascript/overload/example.i b/Examples/javascript/overload/example.i new file mode 100644 index 000000000..b86689f8a --- /dev/null +++ b/Examples/javascript/overload/example.i @@ -0,0 +1,16 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* + Note: overloading is implemented in a sloppy way currently + i.e., only the number of arguments is taken into conideration + for dispatching. + To solve the problem one has to rename such conflicting methods. +*/ +%rename(f_double) f(double val); + +%include "example.h" diff --git a/Examples/javascript/overload/example.js b/Examples/javascript/overload/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/overload/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/overload/runme.js b/Examples/javascript/overload/runme.js new file mode 100644 index 000000000..1e6c861a6 --- /dev/null +++ b/Examples/javascript/overload/runme.js @@ -0,0 +1,9 @@ +var example = require("./example"); + +example.f(); +example.f(1); +example.f(1, 2); +example.f("bla"); +example.f(false); +example.f(11111111111); +example.f_double(1.0); diff --git a/Examples/javascript/pointer/Makefile b/Examples/javascript/pointer/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/pointer/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/pointer/binding.gyp b/Examples/javascript/pointer/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/pointer/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/pointer/example.cxx b/Examples/javascript/pointer/example.cxx new file mode 100755 index 000000000..8762329fe --- /dev/null +++ b/Examples/javascript/pointer/example.cxx @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void subtract(int *x, int *y, int *result) { + *result = *x - *y; +} + +int divide(int n, int d, int *r) { + int q; + q = n/d; + *r = n - q*d; + return q; +} diff --git a/Examples/javascript/pointer/example.i b/Examples/javascript/pointer/example.i new file mode 100755 index 000000000..38c67d7d2 --- /dev/null +++ b/Examples/javascript/pointer/example.i @@ -0,0 +1,30 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void subtract(int *, int *, int *); +extern int divide(int, int, int *); +%} + +/* This example illustrates a couple of different techniques + for manipulating C pointers */ + +/* First we'll use the pointer library */ +extern void add(int *x, int *y, int *result); +%include cpointer.i +%pointer_functions(int, intp); + +/* Next we'll use some typemaps */ + +%include typemaps.i +extern void subtract(int *INPUT, int *INPUT, int *OUTPUT); + +/* Next we'll use typemaps and the %apply directive */ + +%apply int *OUTPUT { int *r }; +extern int divide(int n, int d, int *r); + + + + diff --git a/Examples/javascript/pointer/example.js b/Examples/javascript/pointer/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/pointer/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/pointer/runme.js b/Examples/javascript/pointer/runme.js new file mode 100755 index 000000000..7f1e51c9e --- /dev/null +++ b/Examples/javascript/pointer/runme.js @@ -0,0 +1,35 @@ +var example = require("./example"); + +// First create some objects using the pointer library. +console.log("Testing the pointer library\n"); +a = example.new_intp(); +b = example.new_intp(); +c = example.new_intp(); + +example.intp_assign(a,37); +example.intp_assign(b,42); + +console.log(" a = " + example.intp_value(a) + "\n"); +console.log(" b = " + example.intp_value(b) + "\n"); +console.log(" c = " + example.intp_value(c) + "\n"); + +//// Call the add() function with some pointers +example.add(a, b, c); + +// +//// Now get the result +r = example.intp_value(c); +console.log(" 37 + 42 = " + r + "\n"); + +// Clean up the pointers +example.delete_intp(a); +example.delete_intp(b); +example.delete_intp(c); + +//// Now try the typemap library +//// This should be much easier. Now how it is no longer +//// necessary to manufacture pointers. +//"OUTPUT" Mapping is not supported +//console.log("Trying the typemap library"); +//r = example.subtract(37,42); +//console.log("37 - 42 =" + r); diff --git a/Examples/javascript/pointer/typemaps.i b/Examples/javascript/pointer/typemaps.i new file mode 100644 index 000000000..e69de29bb diff --git a/Examples/javascript/reference/Makefile b/Examples/javascript/reference/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/reference/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/reference/binding.gyp b/Examples/javascript/reference/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/reference/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/reference/example.cxx b/Examples/javascript/reference/example.cxx new file mode 100755 index 000000000..8a513bf49 --- /dev/null +++ b/Examples/javascript/reference/example.cxx @@ -0,0 +1,46 @@ +/* File : example.cxx */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "example.h" +#include +#include + +Vector operator+(const Vector &a, const Vector &b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} + +char *Vector::print() { + static char temp[512]; + sprintf(temp,"Vector %p (%g,%g,%g)", this, x,y,z); + return temp; +} + +VectorArray::VectorArray(int size) { + items = new Vector[size]; + maxsize = size; +} + +VectorArray::~VectorArray() { + delete [] items; +} + +Vector &VectorArray::operator[](int index) { + if ((index < 0) || (index >= maxsize)) { + printf("Panic! Array index out of bounds.\n"); + exit(1); + } + return items[index]; +} + +int VectorArray::size() { + return maxsize; +} + diff --git a/Examples/javascript/reference/example.h b/Examples/javascript/reference/example.h new file mode 100755 index 000000000..4915adb1b --- /dev/null +++ b/Examples/javascript/reference/example.h @@ -0,0 +1,26 @@ +/* File : example.h */ + +class Vector { +private: + double x,y,z; +public: + Vector() : x(0), y(0), z(0) { }; + Vector(double x, double y, double z) : x(x), y(y), z(z) { }; + friend Vector operator+(const Vector &a, const Vector &b); + char *print(); +}; + +class VectorArray { +private: + Vector *items; + int maxsize; +public: + VectorArray(int maxsize); + ~VectorArray(); + Vector &operator[](int); + int size(); +}; + + + + diff --git a/Examples/javascript/reference/example.i b/Examples/javascript/reference/example.i new file mode 100755 index 000000000..1cf19c82c --- /dev/null +++ b/Examples/javascript/reference/example.i @@ -0,0 +1,42 @@ +/* File : example.i */ + +/* This file has a few "typical" uses of C++ references. */ + +%module example + +%{ +#include "example.h" +%} + +class Vector { +public: + Vector(double x, double y, double z); + ~Vector(); + char *print(); +}; + +/* This helper function calls an overloaded operator */ +%inline %{ +Vector addv(Vector &a, Vector &b) { + return a+b; +} +%} + +/* Wrapper around an array of vectors class */ + +class VectorArray { +public: + VectorArray(int maxsize); + ~VectorArray(); + int size(); + + /* This wrapper provides an alternative to the [] operator */ + %extend { + Vector &get(int index) { + return (*$self)[index]; + } + void set(int index, Vector &a) { + (*$self)[index] = a; + } + } +}; diff --git a/Examples/javascript/reference/example.js b/Examples/javascript/reference/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/reference/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/reference/runme.js b/Examples/javascript/reference/runme.js new file mode 100755 index 000000000..935d2b948 --- /dev/null +++ b/Examples/javascript/reference/runme.js @@ -0,0 +1,67 @@ +// This file illustrates the manipulation of C++ references in Javascript. +var example = require("./example"); + +// ----- Object creation ----- + +console.log("Creating some objects:\n"); +a = new example.Vector(3,4,5); +b = new example.Vector(10,11,12); + +console.log(" created" + a.print()); +console.log(" created" + b.print()); + +// ----- Call an overloaded operator ----- + +// This calls the wrapper we placed around operator+(const Vector &a, const Vector &) +// It returns a new allocated object. + +console.log("Adding a+b\n"); +c = example.addv(a, b); +console.log("a+b = " + c.print()); + + +// TODO: Note: Unless we free the result, a memory leak will occur +//delete_Vector(c); + +// ----- Create a vector array ----- + +// Note: Using the high-level interface here +console.log("Creating an array of vectors\n"); +va = new example.VectorArray(10); +console.log("va = " + va + "\n"); + +// ----- Set some values in the array ----- + +// These operators copy the value of a and b to the vector array +va.set(0,a); +va.set(1,b); + +// This will work, but it will cause a memory leak! +va.set(2,example.addv(a,b)); + +// The non-leaky way to do it +//c = addv(a,b); +//va.set(3,c); +//delete_Vector(c); + +// Get some values from the array + +console.log("Getting some array values\n"); +for (i = 0; i < 5; i++) { + temp = va.get(i); + console.log(i,temp.print()); +} + +// Watch under resource meter to check on this +console.log("Making sure we don't leak memory.\n"); +for (i = 0; i < 1000000; i++) { + c = va.get(i % 10); +} +//---------TODO--------- +//----- Clean up ----- +//console.log("Cleaning up\n"); + +//example.delete_VectorArray(va); +//example.delete_Vector(a); +//example.delete_Vector(b); + diff --git a/Examples/javascript/reference/swig_gdb.log b/Examples/javascript/reference/swig_gdb.log new file mode 100644 index 000000000..57bca0306 --- /dev/null +++ b/Examples/javascript/reference/swig_gdb.log @@ -0,0 +1,22 @@ +Loaded swig printers +SwigStringPrinter: Could not convert const char* to string +SwigListIterator: Construction failed. + Cannot access memory at address 0x7d894828ec834853. +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigListIterator: Construction failed. + Cannot access memory at address 0x7d894828ec834853. +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not dereference struct String* +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not dereference struct String* +SwigStringPrinter: Could not dereference struct String* +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not dereference struct String* +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not dereference struct String* +SwigStringPrinter: Could not dereference struct String* diff --git a/Examples/javascript/simple/Makefile b/Examples/javascript/simple/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/simple/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/simple/binding.gyp b/Examples/javascript/simple/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/simple/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/simple/example.cxx b/Examples/javascript/simple/example.cxx new file mode 100644 index 000000000..1c2af789c --- /dev/null +++ b/Examples/javascript/simple/example.cxx @@ -0,0 +1,18 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + + diff --git a/Examples/javascript/simple/example.i b/Examples/javascript/simple/example.i new file mode 100644 index 000000000..24093b9bf --- /dev/null +++ b/Examples/javascript/simple/example.i @@ -0,0 +1,7 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +%} diff --git a/Examples/javascript/simple/example.js b/Examples/javascript/simple/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/simple/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/simple/runme.js b/Examples/javascript/simple/runme.js new file mode 100755 index 000000000..be2c18669 --- /dev/null +++ b/Examples/javascript/simple/runme.js @@ -0,0 +1,26 @@ +var example = require("./example"); + +/* Call our gcd() function */ + +x = 42; +y = 105; +g = example.gcd(x,y); +console.log("GCD of x and y is=" + g); + +/* Manipulate the Foo global variable */ + +/* Output its current value */ +console.log("Global variable Foo=" + example.Foo); + +/* Change its value */ +example.Foo = 3.1415926; + +/* See if the change took effect */ +console.log("Variable Foo changed to=" + example.Foo); + + + + + + + diff --git a/Examples/javascript/template/Makefile b/Examples/javascript/template/Makefile new file mode 100755 index 000000000..a2570636e --- /dev/null +++ b/Examples/javascript/template/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../js_example.mk diff --git a/Examples/javascript/template/binding.gyp b/Examples/javascript/template/binding.gyp new file mode 100644 index 000000000..69af46b22 --- /dev/null +++ b/Examples/javascript/template/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/template/example.h b/Examples/javascript/template/example.h new file mode 100644 index 000000000..7401df650 --- /dev/null +++ b/Examples/javascript/template/example.h @@ -0,0 +1,32 @@ +/* File : example.h */ + +// Some template definitions + +template T max(T a, T b) { return a>b ? a : b; } + +template class vector { + T *v; + int sz; + public: + vector(int _sz) { + v = new T[_sz]; + sz = _sz; + } + T &get(int index) { + return v[index]; + } + void set(int index, T &val) { + v[index] = val; + } +#ifdef SWIG + %extend { + T getitem(int index) { + return $self->get(index); + } + void setitem(int index, T val) { + $self->set(index,val); + } + } +#endif +}; + diff --git a/Examples/javascript/template/example.i b/Examples/javascript/template/example.i new file mode 100644 index 000000000..8f94c4da1 --- /dev/null +++ b/Examples/javascript/template/example.i @@ -0,0 +1,17 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + +/* Now instantiate some specific template declarations */ + +%template(maxint) max; +%template(maxdouble) max; +%template(vecint) vector; +%template(vecdouble) vector; + diff --git a/Examples/javascript/template/example.js b/Examples/javascript/template/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/template/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/template/runme.js b/Examples/javascript/template/runme.js new file mode 100644 index 000000000..55894dfd5 --- /dev/null +++ b/Examples/javascript/template/runme.js @@ -0,0 +1,30 @@ +var example = require("./example"); + +//Call some templated functions +console.log(example.maxint(3,7)); +console.log(example.maxdouble(3.14,2.18)); + +// Create some class + +iv = new example.vecint(100); +dv = new example.vecdouble(1000); + +for(i=0;i<=100;i++) + iv.setitem(i,2*i); + +for(i=0;i<=1000;i++) + dv.setitem(i, 1.0/(i+1)); + +sum = 0; +for(i=0;i<=100;i++) + sum = sum + iv.getitem(i); + +console.log(sum); + +sum = 0.0; +for(i=0;i<=1000;i++) + sum = sum + dv.getitem(i); +console.log(sum); + +delete iv; +delete dv; diff --git a/Examples/javascript/variables/Makefile b/Examples/javascript/variables/Makefile new file mode 100755 index 000000000..b0934786a --- /dev/null +++ b/Examples/javascript/variables/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../js_example.mk diff --git a/Examples/javascript/variables/binding.gyp b/Examples/javascript/variables/binding.gyp new file mode 100644 index 000000000..54eebfaa0 --- /dev/null +++ b/Examples/javascript/variables/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/variables/example.cxx b/Examples/javascript/variables/example.cxx new file mode 100755 index 000000000..3ad4c2323 --- /dev/null +++ b/Examples/javascript/variables/example.cxx @@ -0,0 +1,96 @@ +/* File : example.c */ + +/* I'm a file containing some C global variables */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include "example.h" + +int ivar = 0; +short svar = 0; +long lvar = 0; +unsigned int uivar = 0; +unsigned short usvar = 0; +unsigned long ulvar = 0; +signed char scvar = 0; +unsigned char ucvar = 0; +char cvar = 0; +float fvar = 0; +double dvar = 0; +char *strvar = 0; +#ifdef __cplusplus // Note: for v8 this must be linkable with g++, without extern cstrvar is mangled +extern const char cstrvar[] = "Goodbye"; +#else +const char cstrvar[] = "Goodbye"; +#endif +const +int *iptrvar = 0; +char name[256] = "Dave"; +char path[256] = "/home/beazley"; + + +/* Global variables involving a structure */ +Point *ptptr = 0; +Point pt = { 10, 20 }; + +/* A variable that we will make read-only in the interface */ +int status = 1; + +/* A debugging function to print out their values */ + +void print_vars() { + printf("ivar = %d\n", ivar); + printf("svar = %d\n", svar); + printf("lvar = %ld\n", lvar); + printf("uivar = %u\n", uivar); + printf("usvar = %u\n", usvar); + printf("ulvar = %lu\n", ulvar); + printf("scvar = %d\n", scvar); + printf("ucvar = %u\n", ucvar); + printf("fvar = %g\n", fvar); + printf("dvar = %g\n", dvar); + printf("cvar = %c\n", cvar); + printf("strvar = %s\n", strvar ? strvar : "(null)"); + printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)"); + printf("iptrvar = %p\n", iptrvar); + printf("name = %s\n", name); + printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0); + printf("pt = (%d, %d)\n", pt.x, pt.y); + printf("status = %d\n", status); +} + +/* A function to create an integer (to test iptrvar) */ + +int *new_int(int value) { + int *ip = (int *) malloc(sizeof(int)); + *ip = value; + return ip; +} + +/* A function to create a point */ + +Point *new_Point(int x, int y) { + Point *p = (Point *) malloc(sizeof(Point)); + p->x = x; + p->y = y; + return p; +} + +char * Point_print(Point *p) { + static char buffer[256]; + if (p) { + sprintf(buffer,"(%d,%d)", p->x,p->y); + } else { + sprintf(buffer,"null"); + } + return buffer; +} + +void pt_print() { + printf("(%d, %d)\n", pt.x, pt.y); +} diff --git a/Examples/javascript/variables/example.h b/Examples/javascript/variables/example.h new file mode 100755 index 000000000..0f7e89594 --- /dev/null +++ b/Examples/javascript/variables/example.h @@ -0,0 +1,6 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + diff --git a/Examples/javascript/variables/example.i b/Examples/javascript/variables/example.i new file mode 100755 index 000000000..591b871ed --- /dev/null +++ b/Examples/javascript/variables/example.i @@ -0,0 +1,49 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Some global variable declarations */ +%inline %{ +extern int ivar; +extern short svar; +extern long lvar; +extern unsigned int uivar; +extern unsigned short usvar; +extern unsigned long ulvar; +extern signed char scvar; +extern unsigned char ucvar; +extern char cvar; +extern float fvar; +extern double dvar; +extern char *strvar; +extern const char cstrvar[]; +extern int *iptrvar; +extern char name[256]; + +extern Point *ptptr; +extern Point pt; +%} + + +/* Some read-only variables */ + +%immutable; + +%inline %{ +extern int status; +extern char path[256]; +%} + +%mutable; + +/* Some helper functions to make it easier to test */ +%inline %{ +extern void print_vars(); +extern int *new_int(int value); +extern Point *new_Point(int x, int y); +extern char *Point_print(Point *p); +extern void pt_print(); +%} + diff --git a/Examples/javascript/variables/example.js b/Examples/javascript/variables/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/variables/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/variables/runme.js b/Examples/javascript/variables/runme.js new file mode 100755 index 000000000..d07861713 --- /dev/null +++ b/Examples/javascript/variables/runme.js @@ -0,0 +1,68 @@ +var example = require("./example"); + +// Try to set the values of some global variables +example.ivar = 42; +example.svar = -31000; +example.lvar = 65537; +example.uivar = 123456; +example.usvar = 61000; +example.ulvar = 654321; +example.scvar = -13; +example.ucvar = 251; +example.cvar = "S"; +example.fvar = 3.14159; +example.dvar = 2.1828; +example.strvar = "Hello World"; +example.iptrvar= example.new_int(37); +example.ptptr = example.new_Point(37,42); +example.name = "Bill"; + +// Now console.log out the values of the variables +console.log("Variables (values console.loged from Python)" + "\n"); +console.log("ivar = " + example.ivar + "\n"); +console.log("svar = " + example.svar + "\n"); +console.log("lvar = " + example.lvar + "\n"); +console.log("uivar = " + example.uivar + "\n"); +console.log("usvar = " + example.usvar + "\n"); +console.log("ulvar = " + example.ulvar + "\n"); +console.log("scvar = " + example.scvar + "\n"); +console.log("ucvar = " + example.ucvar + "\n"); +console.log("fvar = " + example.fvar + "\n"); +console.log("dvar = " + example.dvar + "\n"); +console.log("cvar = " + example.cvar + "\n"); +console.log("strvar = " + example.strvar+ "\n"); +console.log("cstrvar = " + example.cstrvar+ "\n"); +console.log("iptrvar = " + example.iptrvar+ "\n"); +console.log("name = " + example.name + "\n"); +console.log("ptptr = " + example.ptptr + ": " + example.Point_print(example.ptptr) + "\n"); +console.log("pt = " + example.pt + ": " + example.Point_print(example.pt) + "\n"); + + +console.log("\nVariables (values console.loged from C)"); + +example.print_vars(); + +console.log("\nNow I'm going to try and modify some read only variables"); + +console.log("Tring to set 'path'"); +try{ + example.path = "Whoa!"; + console.log("Hey, what's going on?!?! This shouldn't work"); +} +catch(e){ + console.log("Good."); +} + +console.log("Trying to set 'status'"); +try{ + example.status = 0; + console.log("Hey, what's going on?!?! This shouldn't work"); +} catch(e){ + console.log("Good."); +} + +console.log("\nI'm going to try and update a structure variable.\n"); +example.pt = example.ptptr; +console.log("The new value is: "); +example.pt_print(); +console.log("You should see the value: " + example.Point_print(example.ptptr)); diff --git a/Examples/javascript/variables/swig_gdb.log b/Examples/javascript/variables/swig_gdb.log new file mode 100644 index 000000000..2fe437110 --- /dev/null +++ b/Examples/javascript/variables/swig_gdb.log @@ -0,0 +1,9 @@ +Loaded swig printers +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string +SwigStringPrinter: Could not convert const char* to string diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index b9239315a..14f13bed8 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -98,6 +98,7 @@ C_TEST_BROKEN += \ tag_no_clash_with_variable # C++ test cases. (Can be run individually using: make testcase.cpptest) +ifndef SKIP_CPP_CASES CPP_TEST_CASES += \ abstract_access \ abstract_inherit \ @@ -489,6 +490,7 @@ CPP_TEST_CASES += \ voidtest \ wallkw \ wrapmacro +endif # C++11 test cases. CPP11_TEST_CASES = \ @@ -562,6 +564,7 @@ CPP_TEST_CASES += $(CPP11_TEST_CASES) endif # C test cases. (Can be run individually using: make testcase.ctest) +ifndef SKIP_C_CASES C_TEST_CASES += \ arrays \ bom_utf8 \ @@ -612,9 +615,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 \ @@ -623,6 +627,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 bfbd706f4..8e92e7840 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 fdea75e2f..f24227c68 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) || defined(SWIGLUA) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGLUA) || 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 58c560412..3e4b3c214 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) || defined(SWIGLUA) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGLUA) || 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 e92ff8c1d..2f7c6fbe1 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) || defined(SWIGLUA) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD) || defined(SWIGLUA) || 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..0581c1920 --- /dev/null +++ b/Lib/javascript/jsc/javascriptstrings.swg @@ -0,0 +1,184 @@ +/* ------------------------------------------------------------ + * 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 e31e5037f..6bac0b98a 100644 --- a/Lib/typemaps/strings.swg +++ b/Lib/typemaps/strings.swg @@ -499,7 +499,7 @@ * --- String fragment methods --- * ------------------------------------------------------------ */ - +#ifndef %_typemap2_string %define %_typemap2_string(StringCode, CharCode, Char, CharName, SWIG_AsCharPtrAndSize, @@ -602,7 +602,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 4407d1316..f4d0be077 100644 --- a/Makefile.in +++ b/Makefile.in @@ -84,6 +84,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@" @@ -129,6 +130,7 @@ check-aliveness: @$(skip-r) || ./$(TARGET) -r -help @$(skip-go) || ./$(TARGET) -go -help @$(skip-d) || ./$(TARGET) -d -help + @$(skip-javascript) || ./$(TARGET) -javascript -help check-ccache: test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) check) @@ -139,6 +141,7 @@ check-versions: \ check-perl5-version \ check-python-version \ check-java-version \ + check-javascript-version \ check-android-version \ check-guile-version \ check-mzscheme-version \ @@ -196,7 +199,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) @@ -221,6 +225,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 : @@ -274,7 +279,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 \ @@ -326,7 +332,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) $(FLAGS) check-$*-test-suite ACTION=all @@ -354,7 +361,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) $(FLAGS) check-$*-test-suite ACTION=broken @@ -467,7 +475,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 49d571236..4dbede635 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..eae594727 --- /dev/null +++ b/Source/Modules/javascript.cxx @@ -0,0 +1,2428 @@ +#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" + +// 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" +#define HAS_TEMPLATES "has_templates" + +#define RESET true + +/** + * 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(const Template & other); + + ~Template(); + + String *str(); + + Template & replace(const String *pattern, const String *repl); + + Template & print(DOH *doh); + + Template & pretty_print(DOH *doh); + + void operator=(const Template & t); + + Template & trim(); + +private: + + String *code; + String *templateName; + +}; + +/** + * JSEmitter represents an abstraction of javascript code generators + * for different javascript engines. + **/ +class JSEmitter { + +protected: + + typedef JSEmitterState State; + + enum MarshallingMode { + Setter, + Getter, + Ctor, + Function + }; + +public: + + enum 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; +}; + +/* factory methods for concrete JSEmitters: */ + +JSEmitter *swig_javascript_create_JSCEmitter(); +JSEmitter *swig_javascript_create_V8Emitter(); + +/********************************************************************** + * JAVASCRIPT: swig module implementation + **********************************************************************/ + +class JAVASCRIPT:public Language { + +public: + + JAVASCRIPT():emitter(NULL) { + } ~JAVASCRIPT() { + delete emitter; + } + + virtual int functionHandler(Node *n); + virtual int globalfunctionHandler(Node *n); + virtual int variableHandler(Node *n); + virtual int globalvariableHandler(Node *n); + virtual int staticmemberfunctionHandler(Node *n); + virtual int classHandler(Node *n); + virtual int functionWrapper(Node *n); + virtual int constantWrapper(Node *n); + virtual 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; +} + +static const char *usage = (char *) "\ +Javascript Options (available with -javascript)\n\ + -jsc - creates a JavascriptCore extension \n\ + -v8 - creates a v8 extension \n\ + -node - creates a node.js extension \n\ + -debug-codetemplates - generates information about the origin of code templates.\n"; + + +/* --------------------------------------------------------------------- + * main() + * + * Entry point for the JAVASCRIPT module + * --------------------------------------------------------------------- */ + +void JAVASCRIPT::main(int argc, char *argv[]) { + // Set javascript subdirectory in SWIG library + SWIG_library_directory("javascript"); + + int 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], "-node") == 0) { + Swig_mark_arg(i); + mode = JSEmitter::V8; + SWIG_library_directory("javascript/v8"); + Preprocessor_define("BUILDING_NODE_EXTENSION 1", 0); + } else if (strcmp(argv[i], "-debug-codetemplates") == 0) { + Swig_mark_arg(i); + js_template_enable_debug = true; + } else if (strcmp(argv[i], "-help") == 0) { + fputs(usage, stdout); + return; + } + } + } + + switch (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, "SWIG Javascript: Unknown emitter type.\n"); + 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) { + if (!State::IsSet(state.global (HAS_TEMPLATES))) { + SetFlag(state.global (), HAS_TEMPLATES); + } + return Setattr(templates, name, code); +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::getTemplate() : Provides a registered code template + * ----------------------------------------------------------------------------- */ + +Template JSEmitter::getTemplate(const String *name) { + String *templ = Getattr(templates, name); + + if (!templ) { + Printf(stderr, "Could not find template %s\n.", name); + 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_member = GetFlag(n, "ismember"); + bool is_setter = GetFlag(n, "memberset") || GetFlag(n, "varset"); + bool is_getter = GetFlag(n, "memberget") || GetFlag(n, "varget"); + if (is_setter) { + ret = emitSetter(n, is_member, is_static); + } else if (is_getter) { + ret = emitGetter(n, is_member, is_static); + } else { + Swig_print_node(n); + } + + } 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(RESET); + state.clazz(NAME, Getattr(n, "sym:name")); + state.clazz("nspace", current_namespace); + + // Creating a mangled name using the current namespace and the symbol name + String *mangled_name = NewString(""); + Printf(mangled_name, "%s_%s", Getattr(current_namespace, NAME_MANGLED), Getattr(n, "sym:name")); + state.clazz(NAME_MANGLED, SwigType_manglestr(mangled_name)); + Delete(mangled_name); + + state.clazz(TYPE, NewString(Getattr(n, "classtype"))); + + String *type = SwigType_manglestr(Getattr(n, "classtypeobj")); + String *classtype_mangled = NewString(""); + Printf(classtype_mangled, "p%s", type); + state.clazz(TYPE_MANGLED, classtype_mangled); + Delete(type); + + String *ctor_wrapper = NewString("_wrap_new_veto_"); + Append(ctor_wrapper, state.clazz(NAME)); + state.clazz(CTOR, ctor_wrapper); + state.clazz(CTOR_DISPATCHERS, NewString("")); + state.clazz(DTOR, NewString("0")); + + // HACK: assume that a class is abstract + // this is resolved by emitCtor (which is only called for non abstract classes) + SetFlag(state.clazz(), IS_ABSTRACT); + + return SWIG_OK; +} + +int JSEmitter::enterFunction(Node *n) { + state.function(RESET); + state.function(NAME, Getattr(n, "sym:name")); + if (Equal(Getattr(n, "storage"), "static")) { + SetFlag(state.function(), IS_STATIC); + } + return SWIG_OK; +} + +int JSEmitter::enterVariable(Node *n) { + // reset the state information for variables. + state.variable(RESET); + + // Retrieve a pure symbol name. Using 'sym:name' as a basis, as it considers %renamings. + if (Equal(Getattr(n, "view"), "memberconstantHandler")) { + // Note: this is kind of hacky/experimental + // For constants/enums 'sym:name' contains e.g., 'Foo_Hello' instead of 'Hello' + state.variable(NAME, Getattr(n, "memberconstantHandler:sym:name")); + } else { + state.variable(NAME, Swig_scopename_last(Getattr(n, "sym:name"))); + } + + if (Equal(Getattr(n, "storage"), "static")) { + SetFlag(state.variable(), IS_STATIC); + } + + if (!Language::instance()->is_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) { + // HACK: somehow it happened under OSX that before everything started + // a lot of SWIG internal constants were emitted + // This didn't happen on other platforms yet... + // we ignore those premature definitions + if (!State::IsSet(state.global (HAS_TEMPLATES))) { + return SWIG_ERROR; + } + + 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; + +}; + +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() { + Delete(f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Delete(namespaces); + Delete(f_wrap_cpp); + return SWIG_OK; +} + +int JSCEmitter::enterFunction(Node *n) { + + JSEmitter::enterFunction(n); + + return SWIG_OK; +} + +int JSCEmitter::exitFunction(Node *n) { + Template t_function = getTemplate("jsc_function_declaration"); + + bool is_member = GetFlag(n, "ismember") | 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() { + Delete(f_runtime); + Delete(f_header); + Delete(f_class_templates); + Delete(f_init_namespaces); + Delete(f_init_class_templates); + Delete(f_init_wrappers); + Delete(f_init_inheritance); + Delete(f_init_class_instances); + Delete(f_init_static_wrappers); + Delete(f_init_register_classes); + Delete(f_init_register_namespaces); + Delete(f_init); + Delete(f_post_init); + Delete(f_wrap_cpp); + return SWIG_OK; +} + +int V8Emitter::enterClass(Node *n) { + JSEmitter::enterClass(n); + + // emit declaration of a v8 class template + Template t_decl_class(getTemplate("jsv8_declare_class_template")); + t_decl_class.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .trim() + .pretty_print(f_class_templates); + + return SWIG_OK; +} + +int V8Emitter::exitClass(Node *n) { + if (GetFlag(state.clazz(), IS_ABSTRACT)) { + Template t_veto_ctor(getTemplate("js_veto_ctor")); + t_veto_ctor.replace("$jswrapper", state.clazz(CTOR)) + .replace("$jsname", state.clazz(NAME)) + .pretty_print(f_wrappers); + } + + /* Note: this makes sure that there is a swig_type added for this class */ + String *clientData = NewString(""); + Printf(clientData, "&%s_clientData", state.clazz(NAME_MANGLED)); + + /* Note: this makes sure that there is a swig_type added for this class */ + SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0")); + + // emit definition of v8 class template + Template t_def_class = getTemplate("jsv8_define_class_template"); + t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsname", state.clazz(NAME)) + .replace("$jsmangledtype", state.clazz(TYPE_MANGLED)) + .replace("$jsdtor", state.clazz(DTOR)) + .trim() + .pretty_print(f_init_class_templates); + + Template t_class_instance = getTemplate("jsv8_create_class_instance"); + t_class_instance.replace("$jsname", state.clazz(NAME)) + .replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsctor", state.clazz(CTOR)) + .trim() + .pretty_print(f_init_class_instances); + + // emit inheritance setup + Node *baseClass = getBaseClass(n); + if (baseClass) { + String *base_name = Getattr(baseClass, "name"); + + Template t_inherit = getTemplate("jsv8_inherit"); + + String *base_name_mangled = SwigType_manglestr(base_name); + t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsbaseclass", base_name_mangled) + .trim() + .pretty_print(f_init_inheritance); + Delete(base_name_mangled); + } + // emit 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; +} + +Template::Template(const Template & t) { + code = NewString(t.code); + templateName = NewString(t.templateName); +} + +void Template::operator=(const Template & t) { + Delete(code); + Delete(templateName); + code = NewString(t.code); + templateName = NewString(t.templateName); +} diff --git a/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/Makefile.in b/Tools/javascript/Makefile.in new file mode 100644 index 000000000..d58412b50 --- /dev/null +++ b/Tools/javascript/Makefile.in @@ -0,0 +1,58 @@ +# ---------------------------------------------------------------- +# 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'). +# +# ---------------------------------------------------------------- +CC = @CC@ +# HACK: under OSX a g++ compiled interpreter is seg-faulting when loading module libraries +# with 'c++' it works... probably some missing flags? +JSCXX = @JSINTERPRETERCXX@ +CFLAGS = @PLATCFLAGS@ +CXXFLAGS = @BOOST_CPPFLAGS@ @PLATCXXFLAGS@ +LINKFLAGS = @JSINTERPRETERLINKFLAGS@ + +ROOT_DIR = @ROOT_DIR@ +JSCFLAGS = @JSCFLAGS@ +JSCXXFLAGS = @JSCXXFLAGS@ +JSINCLUDES = @JSCOREINC@ @JSV8INC@ +JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@ +JSLIBRARYPREFIX = @JSLIBRARYPREFIX@ +JSSO =@JSSO@ +JSLDSHARED = @JSLDSHARED@ +JSCXXSHARED = @JSCXXSHARED@ +JSV8ENABLED = @JSV8ENABLED@ +JSCENABLED = @JSCENABLED@ + +# These settings are provided by 'configure' (see '/configure.in') +ifeq (1, $(JSV8ENABLED)) + JS_INTERPRETER_SRC_V8 = v8_shell.cxx + JS_INTERPRETER_ENABLE_V8 = -DENABLE_V8 +endif + +ifeq (1, $(JSCENABLED)) + JS_INTERPRETER_SRC_JSC = jsc_shell.cxx + JS_INTERPRETER_ENABLE_JSC = -DENABLE_JSC +endif + +JS_INTERPRETER_DEFINES = $(JS_INTERPRETER_ENABLE_JSC) $(JS_INTERPRETER_ENABLE_V8) +JS_INTERPRETER_SRC = javascript.cxx js_shell.cxx $(JS_INTERPRETER_SRC_JSC) $(JS_INTERPRETER_SRC_V8) + +JS_INTERPRETER_OBJS = $(JS_INTERPRETER_SRC:.cxx=.o) + +%.o: %.cxx + $(JSCXX) $(JS_INTERPRETER_DEFINES) $(CXXFLAGS) $(JSINCLUDES) -o $@ -c $< + +javascript: $(JS_INTERPRETER_OBJS) + $(JSCXX) $^ $(CXXFLAGS) -o javascript $(JSDYNAMICLINKING) $(LINKFLAGS) + +clean: + rm -f *.o + rm -f javascript diff --git a/Tools/javascript/javascript.cxx b/Tools/javascript/javascript.cxx new file mode 100644 index 000000000..5e7cc0b20 --- /dev/null +++ b/Tools/javascript/javascript.cxx @@ -0,0 +1,66 @@ +#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[]) { + +#if defined(JAVASCRIPT_INTERPRETER_STOP) + std::cout << "Attach your Debugger and press any key to continue" << std::endl; + std::cin.get(); +#endif + + std::string scriptPath = ""; + + bool interactive = false; + JSShell* shell = 0; + + std::vector modulePath; + modulePath.push_back("."); + + 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 if(strcmp(argv[idx], "-L") == 0) { + modulePath.push_back(argv[++idx]); + } else { + scriptPath = argv[idx]; + } + } + + if (shell == 0) { + shell = JSShell::Create(); + } + + shell->setModulePath(modulePath); + + 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..539b83d65 --- /dev/null +++ b/Tools/javascript/js_shell.cxx @@ -0,0 +1,156 @@ +#include "js_shell.h" + +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#ifdef __APPLE__ +#define LIBRARY_EXT ".bundle" +#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); + } + + std::string lib_path; + HANDLE handle = 0; + + for (int i = 0; i < module_path.size(); ++i) { + lib_path = module_path[i] + "/" + lib_name; + if (access( lib_path.c_str(), F_OK ) != -1) { + handle = LOAD_LIBRARY(lib_path.c_str()); + } + } + + if(handle == 0) { + std::cerr << "Could not find module " << lib_path << ":" + << 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..1e2466b96 --- /dev/null +++ b/Tools/javascript/js_shell.h @@ -0,0 +1,53 @@ +#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(); + + void setModulePath(const std::vector& modulePath) { + module_path = modulePath; + } + +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; + std::vector module_path; + +}; + +#endif // JS_SHELL_H diff --git a/Tools/javascript/jsc_shell.cxx b/Tools/javascript/jsc_shell.cxx new file mode 100644 index 000000000..292c4042b --- /dev/null +++ b/Tools/javascript/jsc_shell.cxx @@ -0,0 +1,233 @@ +#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__ = JSClassDefinition(); + + JSClassRef __shell_class__ = JSClassCreate(&__shell_classdef__); + JSObjectRef __shell__ = JSObjectMake(context, __shell_class__, 0); + bool success = JSObjectSetPrivate(__shell__, (void*) (long) this); + if (!success) { + std::cerr << "Could not register the shell in the Javascript context" << std::endl; + return false; + } + 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 f3414969e..1d5d9ace7 100644 --- a/configure.ac +++ b/configure.ac @@ -1087,6 +1087,231 @@ 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 + JAVASCRIPT=1 + + #---------------------------------------------------------------- + # 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' + # HACK: didn't manage to get dynamic module loading working with a g++ compiled interpreter + JSINTERPRETERCXX='c++' + JSINTERPRETERLINKFLAGS='-g -Wl,-search_paths_first -Wl,-headerpad_max_install_names' + ;; + *) + JSSO=$SO + JSLDSHARED='$(LDSHARED)' + JSCXXSHARED='$(CXXSHARED)' + JSINTERPRETERCXX='$(CXX)' + JSINTERPRETERLINKFLAGS='-ldl' + ;; + esac + + #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Look for Node.js which is the default javascript engine + # without it, the javascript test-suite will be skipped + #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + AC_CHECK_PROGS(NODEJS, node) + + #---------------------------------------------------------------- + # 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/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 + + if test -r $i/libwebkit-1.0.la; then + AC_MSG_RESULT($i) + JSCORELIB="-L$i -lwebkit-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" + JSCENABLED=1 + ;; + *) + ;; + 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(JSINTERPRETERCXX) +AC_SUBST(JSINTERPRETERLINKFLAGS) + +AC_SUBST(JSCOREINC) +AC_SUBST(JSCOREDYNAMICLINKING) +AC_SUBST(JSV8INC) +AC_SUBST(JSV8DYNAMICLINKING) + +AC_SUBST(JSCENABLED) +AC_SUBST(JSV8ENABLED) + #---------------------------------------------------------------- # Look for gcj #---------------------------------------------------------------- @@ -2238,6 +2463,11 @@ if test -z "$JAVA" || test -z "$JAVAC" || test -z "$JAVAINC" ; then fi AC_SUBST(SKIP_JAVA) +SKIP_JAVASCRIPT= +if test -z "$JAVASCRIPT" || test -z "$NODEJS"; then + SKIP_JAVASCRIPT="1" +fi +AC_SUBST(SKIP_JAVASCRIPT) SKIP_GUILE= if test -z "$GUILE" || test -z "$GUILE_LIBS" ; then @@ -2421,6 +2651,8 @@ AC_CONFIG_FILES([ Examples/test-suite/d/Makefile Examples/test-suite/guile/Makefile Examples/test-suite/java/Makefile + Examples/test-suite/javascript/Makefile + Tools/javascript/Makefile Examples/test-suite/mzscheme/Makefile Examples/test-suite/ocaml/Makefile Examples/test-suite/octave/Makefile diff --git a/swig-v8/swig-v8.xcodeproj/project.pbxproj b/swig-v8/swig-v8.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d6fcad63b --- /dev/null +++ b/swig-v8/swig-v8.xcodeproj/project.pbxproj @@ -0,0 +1,153 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXGroup section */ + A7E4F27918BDF64900ED77C7 = { + isa = PBXGroup; + children = ( + ); + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + A7E4F28018BDF64900ED77C7 /* swig-v8 */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = A7E4F28318BDF64900ED77C7 /* Build configuration list for PBXLegacyTarget "swig-v8" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + dependencies = ( + ); + name = "swig-v8"; + passBuildSettingsInEnvironment = 1; + productName = "swig-v8"; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXProject section */ + A7E4F27B18BDF64900ED77C7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0450; + ORGANIZATIONNAME = "Oliver Buchtala"; + }; + buildConfigurationList = A7E4F27E18BDF64900ED77C7 /* Build configuration list for PBXProject "swig-v8" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = A7E4F27918BDF64900ED77C7; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A7E4F28018BDF64900ED77C7 /* swig-v8 */, + ); + }; +/* End PBXProject section */ + +/* Begin XCBuildConfiguration section */ + A7E4F28118BDF64900ED77C7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + A7E4F28218BDF64900ED77C7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + SDKROOT = macosx; + }; + name = Release; + }; + A7E4F28418BDF64900ED77C7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEBUGGING_SYMBOLS = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + A7E4F28518BDF64900ED77C7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A7E4F27E18BDF64900ED77C7 /* Build configuration list for PBXProject "swig-v8" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A7E4F28118BDF64900ED77C7 /* Debug */, + A7E4F28218BDF64900ED77C7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A7E4F28318BDF64900ED77C7 /* Build configuration list for PBXLegacyTarget "swig-v8" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A7E4F28418BDF64900ED77C7 /* Debug */, + A7E4F28518BDF64900ED77C7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = A7E4F27B18BDF64900ED77C7 /* Project object */; +}