diff --git a/.gitignore b/.gitignore index c375a7c77..d4d70b010 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 @@ -86,6 +90,7 @@ Source/CParse/parser.c Source/CParse/parser.h Source/eswig swig +Tools/javascript/javascript # Generated documentation Doc/Manual/CCache.html @@ -103,6 +108,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/*/ @@ -115,6 +121,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 7983d0ecd..890382c40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,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 @@ -51,6 +57,9 @@ 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" -a "$ENGINE" = "node"; 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 && sudo npm install -g node-gyp; fi + - if test "$SWIGLANG" = "javascript" -a "$ENGINE" = "jsc"; then sudo apt-get install -qq libwebkitgtk-dev; fi + - if test "$SWIGLANG" = "javascript" -a "$ENGINE" = "v8"; then sudo apt-get install -qq libv8-dev; 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/CCache/Makefile.in b/CCache/Makefile.in index d8f9042fe..abe78c277 100644 --- a/CCache/Makefile.in +++ b/CCache/Makefile.in @@ -69,9 +69,9 @@ distclean: clean maintainer-clean: distclean /bin/rm -f $(PACKAGE_NAME).1 web/ccache-man.html - + # FIXME: To fix this, test.sh needs to be able to take ccache from the # installed prefix, not from the source dir. -installcheck: +installcheck: @echo "WARNING! This is not really \"installcheck\" yet." $(MAKE) check diff --git a/CHANGES.current b/CHANGES.current index 11682c9dd..8b67392b2 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,31 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.1 (in progress) =========================== +2014-05-01: olly + [PHP] The generated __isset() method now returns true for read-only properties. + +2014-04-24: kwwette + [Go] Fix go ./configure parsing of gccgo --version, and + goruntime.swg typo in __GNUC_PATCHLEVEL__ (SF Bug #1298) + +2014-04-24: kwwette + Fix {python|perl5|ruby|tcl}/java examples + + In Lib/gcj/cni.i, for compatibility with newer gcj versions: + + - remove JvAllocObject() which gcj no longer defines, from gcj Changelog: + 2004-04-16 Bryce McKinlay + * gcj/cni.h (JvAllocObject): Remove these obsolete, + undocumented CNI calls. + + - change JvCreateJavaVM() argument from void* to JvVMInitArgs*, from gcj Changelog: + 2005-02-23 Thomas Fitzsimmons + PR libgcj/16923 + ... + (JvCreateJavaVM): Declare vm_args as JvVMInitArgs* rather than void*. + + *** POTENTIAL INCOMPATIBILITY *** + 2014-04-08: wsfulton SF Bug #1366 - Remove duplicate declarations of strtoimax and strtoumax in inttypes.i diff --git a/COPYRIGHT b/COPYRIGHT index 188af4876..6fbf6c0b0 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -16,6 +16,8 @@ Active SWIG Developers: Joseph Wang (joequant@gmail.com) (R) Xavier Delacour (xavier.delacour@gmail.com) (Octave) David Nadlinger (code@klickverbot.at) (D) + 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..e589d9d09 --- /dev/null +++ b/Doc/Manual/Javascript.html @@ -0,0 +1,808 @@ + + + + + + + + +

SWIG and Javascript

+

This chapter describes SWIG's support of Javascript. It does not cover SWIG basics, but only information that is specific to this module.

+ +

Overview

+

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. +Javascript has gone beyond being a browser-based scripting language and with node.js, it is also used as a backend development language.

+

Native Javascript extensions can be used for applications that embed a web-browser view or that embed a Javascript engine (such as node.js). Extending a general purpose web-browser is not possible as this would be a severe security issue.

+

SWIG Javascript currently supports JavascriptCore, the Javascript engine used by Safari/Webkit, and v8, which is used by Chromium and node.js.

+

WebKit is a modern browser implementation available as open-source which can be embedded into an application. +With node-webkit there is a platform which uses Google's Chromium as Web-Browser widget and node.js for javascript extensions. +

+ +

Preliminaries

+ +

Running SWIG

+ +

Suppose that you defined a SWIG module such as the following:

+
+
+%module example
+%{
+#include "example.h"
+%}
+int gcd(int x, int y);
+extern double Foo;
+
+

To build a Javascript module, run SWIG using the -javascript option and a desired target engine -jsc, -v8, or -node. The generator for node is essentially delegating to the v8 generator and adds some necessary preprocessor definitions.

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

If building a C++ extension, add the -c++ option:

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

This creates a C/C++ source file example_wrap.c or example_wrap.cxx. The generated C source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application to create an extension module.

+

The name of the wrapper file is derived from the name of the input file. For example, if the input file is example.i, the name of the wrapper file is example_wrap.c. To change this, you can use the -o option. The wrapped module will export one function which must be called to register the module with the Javascript interpreter. For example, if your module is named example the corresponding initializer for JavascriptCore would be

+
+
+bool example_initialize(JSGlobalContextRef context, JSObjectRef *exports)
+
+

and for v8:

+
+
+void example_initialize(v8::Handle exports)
+
+

+

Note: be aware that v8 has a C++ API, and thus, the generated modules must be compiled as C++.

+

+ +

Running Tests and Examples

+

The configuration for tests and examples currently supports Linux and Mac only and not MinGW (Windows) yet.

+

The default interpreter is node.js as it is available on all platforms and convenient to use.

+

Running the examples with JavascriptCore requires libjavascriptcoregtk-1.0 to be installed, e.g., under Ubuntu with

+
+
+$ sudo apt-get install libjavascriptcoregtk-1.0-dev
+
+

Running with V8 requires libv8:

+
+
+$ sudo apt-get install libv8-dev
+
+

Examples can be run using

+
+
+$ make check-javascript-examples ENGINE=jsc
+
+

ENGINE can be node, jsc, or v8.

+

The test-suite can be run using

+
+
+$ make check-javascript-test-suite ENGINE=jsc
+
+

Tests should run without any problems, i.e., have been tried out, on the following platforms/interpreters:

+
+
+- Ubuntu Precise 12.04 64bit
+    - JavascriptCore (Webkit 1.8.3)
+    - Node.js (0.10.26)
+    - v8 (3.7.12)
+- Ubuntu Saucy 13.10 64bit
+    - JavascriptCore (Webkit 1.10.2)
+    - Node.js
+    - v8 (3.14.5)
+- Mac OSX Mountain Lion 10.8
+    - JavascriptCore (built-in)
+    - Node.js
+- Windows 7 64bit (VS 2010)
+    - Node.js
+
+

+ +

Future work

+

The Javascript module is not yet as mature as other modules and some things are still missing. As it makes use of SWIG's Unified Typemap Library (UTL), many typemaps are inherited. We could work on that if requested:

+ + +

Integration

+

This chapter gives a short introduction how to use a native Javascript extension: as a node.js module, and as an extension for an embedded Webkit.

+ +

Creating node.js Extensions

+

To install node.js you can download an installer from their web-site for OSX and Windows. For Linux you can either build the source yourself and run sudo checkinstall or keep to the (probably stone-age) packaged version. For Ubuntu there is a PPA available.

+
+
+$ sudo add-apt-repository ppa:chris-lea/node.js
+$ sudo apt-get update
+$ sudo apt-get install nodejs
+
+

As v8 is written in C++ and comes as a C++ library it is crucial to compile your module using the same compiler flags as used for building v8. To make things easier, node.js provides a build tool called node-gyp.

+

You have to install it using npm:

+
+
+$ sudo npm install -g node-gyp
+
+

node-gyp expects a configuration file named binding.gyp which is basically in JSON format and conforms to the same format that is used with Google's build-tool gyp.

+

binding.gyp:

+
+
+{
+  "targets": [
+    {
+      "target_name": "example",
+      "sources": [ "example.cxx", "example_wrap.cxx" ]
+    }
+  ]
+}
+
+

First create the wrapper using SWIG:

+
+
+$ swig -javascript -node -c++ example.cxx
+
+

Then run node-gyp

+
+
+$ node-gyp
+
+

This will create a build folder containing the native module. To use the extension you need to 'require' it in your Javascript source file:

+
+
+require("./build/Release/example")
+
+

A more detailed explanation is given in the Examples section.

+ +

Troubleshooting

+ +

This error happens when gyp is installed as a distribution package. It seems to be outdated. Removing it resolves the problem.

+
+
+$ sudo apt-get remove gyp
+
+ +

Embedded Webkit

+

Webkit is pre-installed on OSX and available as a library for GTK.

+ +

OSX

+

There is general information about programming with WebKit on Apple Developer Documentation. Details about Cocoa programming are not covered here.

+

An integration of a native extension 'example' would look like this:

+
+
+#import "appDelegate.h"
+
+extern bool example_initialize(JSGlobalContextRef context);
+
+
+@implementation ExampleAppDelegate
+
+@synthesize webView;
+
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+
+  // Start a webview with the bundled index.html file
+  NSString *path = [[NSBundle mainBundle] bundlePath];
+  NSString *url =  [NSString stringWithFormat: @"file://%@/Contents/Assets/index.html", path];
+
+  WebFrame *webframe = [webView mainFrame];
+  JSGlobalContextRef context = [webframe globalContext];
+
+  example_initialize(context);
+
+  [ [webView mainFrame] loadRequest:
+    [NSURLRequest requestWithURL: [NSURL URLWithString:url] ]
+  ];
+}
+
+@end
+
+ +

GTK

+

There is general information about programming GTK at GTK documentation and in the GTK tutorial, and for Webkit there is a Webkit GTK+ API Reference.

+

An integration of a native extension 'example' would look like this:

+
+
+#include 
+#include 
+
+extern bool example_initialize(JSGlobalContextRef context);
+
+int main(int argc, char* argv[])
+{
+    // Initialize GTK+
+    gtk_init(&argc, &argv);
+
+    ...
+
+    // Create a browser instance
+    WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
+    WebFrame *webframe = webkit_web_view_get_main_frame(webView);
+    JSGlobalContextRef context = webkit_web_frame_get_global_context(webFrame);
+    example_initialize(context);
+
+    ...
+
+    // Load a web page into the browser instance
+    webkit_web_view_load_uri(webView, "http://www.webkitgtk.org/");
+
+    ...
+
+    // Run the main GTK+ event loop
+    gtk_main();
+
+    return 0;
+}
+
+ +

Creating Applications with node-webkit

+

+

To get started with node-webkit there is a very informative set of wiki pages.

+

Similar to node.js, node-webkit is started from command line within a node.js project directory. +Native extensions are created in the very same way as for node.js, except that a customized gyp derivate has to be used: nw-gyp. +

+ +

+A simple example would have the following structure: +

+ +
+
+- package.json
+- app.html
+- app.js
+- node_modules
+  / example
+  ... (as known from node.js)
+
+
+ +

+The configuration file essentially conforms to node.js syntax. +It has some extras to configure node-webkit. See the Manifest specification for more details. +

+ +

+ package.json: +

+
+
+{
+  "name": "example"
+  "main": "app.html"
+  "window": {
+    "show": true,
+    "width": 800,
+    "height": 600
+  }
+}
+
+ +

+The 'main' property of package.json specifies a web-page to be rendered in +the main window.

+ +

+ app.html: +

+ +
+
+<html>
+  <head>
+    <script src="app.js"></script>
+  </head>
+  <body>
+    <div>
+      The greatest common divisor of
+      <span id="x"></span> and
+      <span id="y"></span> is
+      <span id="z"></span>.
+    </div>
+  </body>
+</html>
+
+ +

+As known from node.js one can use require to load javascript modules. +Additionally, node-webkit provides an API that allows to manipulate the window's menu, +open new windows, and many more things. +

+ +

+ app.js: +

+ +
+
window.onload = function() {
+  var example = require("example");
+  var x = 18;
+  var y = 24;
+  var z = example.gcd(x,y);
+  document.querySelector('#x').innerHTML = x;
+  document.querySelector('#y').innerHTML = y;
+  document.querySelector('#z').innerHTML = z;
+};
+
+ +

Examples

+

Some basic examples are shown here in more detail.

+ +

Simple

+

The common example simple looks like this:

+
+
+/* File : example.i */
+%module example
+
+%inline %{
+extern int    gcd(int x, int y);
+extern double Foo;
+%}
+
+

To make this available as a node extension a binding.gyp has to be created:

+
+
+{
+  "targets": [
+    {
+      "target_name": "example",
+      "sources": [ "example.cxx", "example_wrap.cxx" ]
+    }
+  ]
+}
+
+

Then node-gyp is used to build the extension:

+
+
+$ node-gyp configure build
+
+

From a 'nodejs` application the extension would be used like this:

+
+
+// import the extension via require
+var example = require("./build/Release/example");
+
+// calling the global method
+var x = 42;
+var y = 105;
+var g = example.gcd(x,y);
+
+// Accessing the globak variable
+var f = example.Foo;
+example.Foo = 3.1415926;
+
+

First the module example is loaded from the previously built extension. Global methods and variables are available in the scope of the module.

+

+

Note: ECMAScript 5, the currently implemented Javascript standard, does not have modules. node.js and other implementations provide this mechanism defined by the CommonJS group. For browsers this is provided by Browserify, for instance.

+

+ +

Class

+

The common example class defines three classes, Shape, Circle, and Square:

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

Circle and Square inherit from Shape. Shape has a static variable nshapes, a function move that can't be overridden (non-virtual), and two abstract functions area and perimeter (pure virtual) that must be overridden by the sub-classes.

+

A nodejs extension is built the same way as for the simple example.

+

In Javascript it can be used as follows:

+
+
+var example = require("./build/Release/example");
+
+// local aliases for convenience
+var Shape = example.Shape;
+var Circle = example.Circle;
+var Square = example.Square;
+
+// creating new instances using the 'new' operator
+var c = new Circle(10);
+var s = new Square(10);
+
+// accessing a static member
+Shape.nshapes;
+
+// accessing member variables
+c.x = 20;
+c.y = 30;
+s.x = -10;
+s.y = 5;
+
+// calling some methods
+c.area();
+c.perimeter();
+s.area();
+s.perimeter();
+
+// instantiation of Shape is not permitted
+new Shape();
+
+

Running these commands in an interactive node shell results in the following output:

+
+
+$ node -i
+> var example = require("./build/Release/example");
+undefined
+> var Shape = example.Shape;
+undefined
+> var Circle = example.Circle;
+undefined
+> var Square = example.Square;
+undefined
+> var c = new Circle(10);
+undefined
+> var s = new Square(10);
+undefined
+> Shape.nshapes;
+2
+> c.x = 20;
+20
+> c.y = 30;
+30
+> s.x = -10;
+-10
+> s.y = 5;
+5
+> c.area();
+314.1592653589793
+> c.perimeter();
+62.83185307179586
+> s.area();
+100
+> s.perimeter();
+40
+> c.move(40, 40)
+undefined
+> c.x
+60
+> c.y
+70
+> new Shape()
+Error: Class Shape can not be instantiated
+at repl:1:2
+at REPLServer.self.eval (repl.js:110:21)
+at Interface. (repl.js:239:12)
+at Interface.EventEmitter.emit (events.js:95:17)
+at Interface._onLine (readline.js:202:10)
+at Interface._line (readline.js:531:8)
+at Interface._ttyWrite (readline.js:760:14)
+at ReadStream.onkeypress (readline.js:99:10)
+at ReadStream.EventEmitter.emit (events.js:98:17)
+at emitKey (readline.js:1095:12)
+
+

+

Note: In ECMAScript 5 there is no concept for classes. Instead each function can be used as a constructor function which is executed by the 'new' operator. Furthermore, during construction the key property prototype of the constructor function is used to attach a prototype instance to the created object. A prototype is essentially an object itself that is the first-class delegate of a class used whenever the access to a property of an object fails. The very same prototype instance is shared among all instances of one type. Prototypal inheritance is explained in more detail on in Inheritance and the prototype chain, for instance.

+

+ +

Implementation

+

The Javascript Module implementation has taken a very different approach compared to other language modules in order to support different Javascript interpreters.

+ +

Source Code

+

The Javascript module is implemented in Source/Modules/javascript.cxx. It dispatches the code generation to a JSEmitter instance, V8Emitter or JSCEmitter. Additionally there are some helpers: Template, for templated code generation, and JSEmitterState, which is used to manage state information during AST traversal. This rough map shall make it easier to find a way through this huge source file:

+
+
+// module wide defines
+
+#define NAME "name"
+...
+
+// ###############################
+// #  Helper class declarations
+
+class JSEmitterState { ... };
+
+class Template { ... };
+
+// ###############################
+// # JSEmitter declaration
+
+class JSEmitter { ... };
+
+// Emitter factory declarations
+
+JSEmitter *swig_javascript_create_JSCEmitter();
+JSEmitter *swig_javascript_create_V8Emitter();
+
+// ###############################
+// # Javascript module
+
+// Javascript module declaration
+
+class JAVASCRIPT:public Language { ... };
+
+// Javascript module implementation
+
+int JAVASCRIPT::functionWrapper(Node *n) { ... }
+...
+
+// Module factory implementation
+
+static Language *new_swig_javascript() { ... }
+
+extern "C" Language *swig_javascript(void) { ... }
+
+// ###############################
+// # JSEmitter base implementation
+
+JSEmitter::JSEmitter() { ... }
+
+Template JSEmitter::getTemplate(const String *name) { ... }
+...
+
+// ###############################
+// # JSCEmitter
+
+// JSCEmitter declaration
+
+class JSCEmitter: public JSEmitter { ... };
+
+// JSCEmitter implementation
+
+JSCEmitter::JSCEmitter() { ... }
+
+void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { ... }
+...
+
+// JSCEmitter factory
+
+JSEmitter *swig_javascript_create_JSCEmitter() { ... }
+
+
+// ###############################
+// # V8Emitter
+
+// V8Emitter declaration
+
+class V8Emitter: public JSEmitter { ... };
+
+// V8Emitter implementation
+
+V8Emitter::V8Emitter() { ... }
+
+int V8Emitter::initialize(Node *n) { ... }
+
+// V8Emitter factory
+
+JSEmitter *swig_javascript_create_V8Emitter() { ... }
+
+
+// ###############################
+// # Helper implementation (JSEmitterState, Template)
+
+JSEmitterState::JSEmitterState() { ... }
+...
+
+Template::Template(const String *code_) { ... }
+...
+
+ +

Code Templates

+

All generated code is created on the basis of code templates. The templates for JavascriptCore can be found in Lib/javascript/jsc/javascriptcode.swg, for v8 in Lib/javascript/v8/javascriptcode.swg.

+

To track the originating code template for generated code you can run

+
+
+$ swig -javascript -jsc -debug-codetemplates
+
+

which wraps generated code with a descriptive comment

+
+
+/* begin fragment("template_name") */
+
+...generated code ...
+
+/* end fragment("template_name") */
+
+

The Template class is used like this:

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

A code template is registered with the JSEmitter via fragment(name, "template"), e.g.,

+
+
+%fragment ("jsc_variable_declaration", "templates")
+%{
+  {"$jsname", $jsgetter, $jssetter, kJSPropertyAttributeNone},
+%}
+
+

Template creates a copy of that string and Template::replace uses Swig's Replaceall to replace variables in the template. Template::trim can be used to eliminate leading and trailing whitespaces. Template::print is used to write the final template string to a Swig DOH (based on Printv). All methods allow chaining.

+ +

Emitter

+

The Javascript module delegates code generation to a JSEmitter instance. The following extract shows the essential interface:

+
+
+class 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;
+
+  ...
+
+  /**
+   * 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();
+
+  ...
+
+}
+
+

The module calls initialize, dump, and close from within the top method:

+
+
+int JAVASCRIPT::top(Node *n) {
+  emitter->initialize(n);
+
+  Language::top(n);
+
+  emitter->dump(n);
+  emitter->close();
+
+  return SWIG_OK;
+}
+
+

The methods enterClass and exitClass are called from within the classHandler method:

+
+
+int JAVASCRIPT::classHandler(Node *n) {
+
+  emitter->enterClass(n);
+  Language::classHandler(n);
+  emitter->exitClass(n);
+
+  return SWIG_OK;
+}
+
+

In enterClass the emitter stores state information that is necessary when processing class members. In exitClass the wrapper code for the whole class is generated.

+ +

Emitter states

+

For storing information during the AST traversal the emitter provides a JSEmitterState with different slots to store data representing the scopes global, class, function, and variable.

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

When entering a scope, such as in enterClass, the corresponding state is reset and new data is stored:

+
+
+state.clazz(RESET);
+state.clazz(NAME, Getattr(n, "sym:name"));
+
+

State information can be retrieved using state.clazz(NAME) or with Getattr on state.clazz() which actually returns a Hash instance.

+ + diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index c67e08834..269cb2801 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -993,7 +993,7 @@ The current list of operators which can be overloaded (and the alternative funct
  • __unm__ unary minus
  • __call__ operator() (often used in functor classes)
  • __pow__ the exponential fn (no C++ equivalent, Lua uses ^) -
  • __concat__ the concatenation operator (SWIG maps C++'s ~ to Lua's ..) +
  • __concat__ the concatenation operator (Lua's ..)
  • __eq__ operator==
  • __lt__ operator<
  • __le__ operator<= diff --git a/Doc/Manual/Makefile b/Doc/Manual/Makefile index 42149ba3a..5112afa33 100644 --- a/Doc/Manual/Makefile +++ b/Doc/Manual/Makefile @@ -75,4 +75,3 @@ linkchecker: @echo Note linkchecker versions prior to 6.1 do not work properly wrt anchors @echo ----------------------------------------------------------------------- linkchecker --config=./linkchecker.config index.html - diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index d5c41dde7..745570ca4 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -115,6 +115,9 @@ SWIGCLISP Defined when using CLISP SWIGCSHARP Defined when using C# SWIGGUILE Defined when using Guile SWIGJAVA Defined when using Java +SWIGJAVASCRIPT Defined when using Javascript +SWIG_JAVASCRIPT_JSC Defined when using Javascript for JavascriptCore +SWIG_JAVASCRIPT_V8 Defined when using Javascript for v8 or node.js SWIGLUA Defined when using Lua SWIGMODULA3 Defined when using Modula-3 SWIGMZSCHEME Defined when using Mzscheme diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 877ca2fae..99d1dfe0d 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -42,6 +42,7 @@ Last update : SWIG-3.0.1 (in progress)
  • Go support
  • Guile support
  • Java support
  • +
  • Javascript support
  • Common Lisp support
  • Lua support
  • Modula3 support
  • diff --git a/Doc/Manual/chapters b/Doc/Manual/chapters index 9c376b636..32cf0b2dd 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/Examples/Makefile.in b/Examples/Makefile.in index 218d8eca5..326f678c7 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -88,7 +88,7 @@ endif ################################################################## CPP_DLLIBS = #-L/usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.7.2 \ - -L/usr/local/lib -lg++ -lstdc++ -lgcc + -L/usr/local/lib -lg++ -lstdc++ -lgcc # Solaris workshop 5.0 # CPP_DLLIBS = -L/opt/SUNWspro/lib -lCrun @@ -589,6 +589,117 @@ 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@ +JSINCLUDES = @JSCOREINC@ @JSV8INC@ +JSDYNAMICLINKING = @JSCOREDYNAMICLINKING@ @JSV8DYNAMICLINKING@ +JSSO =@JSSO@ +JSLDSHARED = @JSLDSHARED@ +JSCXXSHARED = @JSCXXSHARED@ +NODEJS = @NODEJS@ +NODEGYP = @NODEGYP@ + +# ---------------------------------------------------------------- +# Creating and building Javascript wrappers +# ---------------------------------------------------------------- + +javascript_wrapper: + $(SWIG) -javascript $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.c $(INTERFACEPATH) + +javascript_wrapper_cpp: $(SRCS) + $(SWIG) -javascript -c++ $(SWIGOPT) -o $(INTERFACEDIR)$(TARGET)_wrap.cxx $(INTERFACEPATH) + +javascript_build: $(SRCS) + $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDES) $(JSINCLUDES) + $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +javascript_build_cpp: $(SRCS) +ifeq (node,$(JSENGINE)) + $(NODEGYP) --loglevel=silent configure build 1>>/dev/null +else + $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(JSINCLUDES) + $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + +endif + +# These targets are used by the test-suite: + +javascript: $(SRCS) javascript_custom_interpreter + $(SWIG) -javascript $(SWIGOPT) $(INTERFACEPATH) +ifeq (jsc, $(ENGINE)) + $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDES) $(JSINCLUDES) + $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) +else # (v8 | node) # v8 and node must be compiled as c++ + $(CXX) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(JSINCLUDES) + $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(JSDYNAMICLINKING) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) +endif + +javascript_cpp: $(SRCS) javascript_custom_interpreter + $(SWIG) -javascript -c++ $(SWIGOPT) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CFLAGS) $(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)') + +ifeq (node,$(JSENGINE)) +javascript_run: + $(RUNTOOL) $(NODEJS) $(RUNME).js $(RUNPIPE) +else +javascript_run: javascript_custom_interpreter + $(RUNTOOL) $(ROOT_DIR)/Tools/javascript/javascript -$(JSENGINE) -L $(TARGET) $(RUNME).js $(RUNPIPE) +endif + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +javascript_version: +ifeq (, $(ENGINE)) + @if [ "$(NODEJS)" != "" ]; then \ + echo "Node.js: `($(NODEJS) --version)`"; \ + echo "node-gyp: `($(NODEGYP) --version)`"; \ + else \ + echo "Version depends on the interpreter"; \ + fi +endif +ifeq (node, $(ENGINE)) + echo "Node.js: `($(NODEJS) --version)`" + echo "node-gyp: `($(NODEGYP) --version)`" +endif +ifeq (jsc, $(ENGINE)) + @if [ "@JSCOREVERSION@" != "" ]; then \ + echo "@JSCOREVERSION@"; \ + else \ + echo "Unknown JavascriptCore version."; \ + fi +endif +ifeq (v8, $(ENGINE)) + echo "Unknown v8 version." +endif + +# ----------------------------------------------------------------- +# 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 ###### ################################################################## @@ -1510,7 +1621,7 @@ R_SCRIPT=$(RUNME).R r: $(SRCS) $(SWIG) -r $(SWIGOPT) $(INTERFACEPATH) ifneq ($(SRCS),) - $(CC) -g -c $(CFLAGS) $(R_CFLAGS) $(SRCS) $(INCLUDES) + $(CC) -g -c $(CFLAGS) $(R_CFLAGS) $(SRCS) $(INCLUDES) endif +( PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(ISRCS) $(OBJS) > /dev/null ) @@ -1521,7 +1632,7 @@ endif r_cpp: $(CXXSRCS) $(SWIG) -c++ -r $(SWIGOPT) -o $(RCXXSRCS) $(INTERFACEPATH) ifneq ($(CXXSRCS),) - $(CXX) -g -c $(CXXFLAGS) $(R_CFLAGS) $(CXXSRCS) $(INCLUDES) + $(CXX) -g -c $(CXXFLAGS) $(R_CFLAGS) $(CXXSRCS) $(INCLUDES) endif +( PKG_CPPFLAGS="$(INCLUDES)" $(COMPILETOOL) $(R) CMD SHLIB -o $(LIBPREFIX)$(TARGET)$(SO) $(RCXXSRCS) $(OBJS) > /dev/null ) diff --git a/Examples/chicken/class/example.cxx b/Examples/chicken/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/chicken/class/example.cxx +++ b/Examples/chicken/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/csharp/class/example.cxx b/Examples/csharp/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/csharp/class/example.cxx +++ b/Examples/csharp/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/d/class/example.cxx b/Examples/d/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/d/class/example.cxx +++ b/Examples/d/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/go/class/class.cxx b/Examples/go/class/class.cxx index 1e8e203dd..f87c7ec8f 100644 --- a/Examples/go/class/class.cxx +++ b/Examples/go/class/class.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : class.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/go/class/index.html b/Examples/go/class/index.html index b39119d12..df93b5672 100644 --- a/Examples/go/class/index.html +++ b/Examples/go/class/index.html @@ -33,8 +33,8 @@ public: } virtual ~Shape() { nshapes--; - }; - double x, y; + } + double x, y; void move(double dx, double dy); virtual double area() = 0; virtual double perimeter() = 0; @@ -45,7 +45,7 @@ class Circle : public Shape { private: double radius; public: - Circle(double r) : radius(r) { }; + Circle(double r) : radius(r) { } virtual double area(); virtual double perimeter(); }; @@ -54,7 +54,7 @@ class Square : public Shape { private: double width; public: - Square(double w) : width(w) { }; + Square(double w) : width(w) { } virtual double area(); virtual double perimeter(); }; diff --git a/Examples/guile/class/example.cxx b/Examples/guile/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/guile/class/example.cxx +++ b/Examples/guile/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/guile/matrix/runme.scm b/Examples/guile/matrix/runme.scm old mode 100755 new mode 100644 diff --git a/Examples/javascript/check.list b/Examples/javascript/check.list new file mode 100644 index 000000000..9707e77d4 --- /dev/null +++ b/Examples/javascript/check.list @@ -0,0 +1,13 @@ +class +constant +enum +exception +functor +nspace +operator +overload +pointer +#reference +simple +template +variables diff --git a/Examples/javascript/class/Makefile b/Examples/javascript/class/Makefile new file mode 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/class/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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 100644 index 000000000..046304519 --- /dev/null +++ b/Examples/javascript/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.cxx */ + +#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() { + return M_PI*radius*radius; +} + +double Circle::perimeter() { + return 2*M_PI*radius; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} diff --git a/Examples/javascript/class/example.h b/Examples/javascript/class/example.h new file mode 100644 index 000000000..642130cd0 --- /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() = 0; + virtual double perimeter() = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + virtual double area(); + virtual double perimeter(); +}; diff --git a/Examples/javascript/class/example.i b/Examples/javascript/class/example.i new file mode 100644 index 000000000..fbdf7249f --- /dev/null +++ b/Examples/javascript/class/example.i @@ -0,0 +1,9 @@ +/* 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 100644 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 100644 index 000000000..ea04c7df8 --- /dev/null +++ b/Examples/javascript/constant/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../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 100644 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 100644 index 000000000..f4b55881e --- /dev/null +++ b/Examples/javascript/constant/runme.js @@ -0,0 +1,14 @@ +var example = require("./example"); + +console.log("ICONST = " + example.ICONST + " (should be 42)"); +console.log("FCONST = " + example.FCONST + " (should be 2.1828)"); +console.log("CCONST = " + example.CCONST + " (should be 'x')"); +console.log("CCONST2 = " + example.CCONST2 + " (this should be on a new line)"); +console.log("SCONST = " + example.SCONST + " (should be 'Hello World')"); +console.log("SCONST2 = " + example.SCONST2 + " (should be '\"Hello World\"')"); +console.log("EXPR = " + example.EXPR + " (should be 48.5484)"); +console.log("iconst = " + example.iconst + " (should be 37)"); +console.log("fconst = " + example.fconst + " (should be 3.14)"); + +console.log("EXTERN = " + example.EXTERN + " (should be undefined)"); +console.log("FOO = " + example.FOO + " (should be undefined)"); diff --git a/Examples/javascript/enum/Makefile b/Examples/javascript/enum/Makefile new file mode 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/enum/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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 100644 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 100644 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 100644 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 100644 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/example.mk b/Examples/javascript/example.mk new file mode 100644 index 000000000..274eff1a3 --- /dev/null +++ b/Examples/javascript/example.mk @@ -0,0 +1,27 @@ +# Note: as a convention an example must be in a child directory of this. +# These paths are relative to such an example directory + +ifneq (, $(ENGINE)) + JSENGINE=$(ENGINE) +else + JSENGINE=node +endif + +EXAMPLES_TOP=../.. +SWIG_TOP=../../.. +SWIG = $(SWIG_TOP)/preinst-swig +TARGET = example +INTERFACE = example.i +SWIGOPT=-$(JSENGINE) + +check: build + $(MAKE) -f $(EXAMPLES_TOP)/Makefile JSENGINE='$(JSENGINE)' TARGET='$(TARGET)' javascript_run + +build: + $(MAKE) -f $(EXAMPLES_TOP)/Makefile CXXSRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' javascript_wrapper_cpp + $(MAKE) -f $(EXAMPLES_TOP)/Makefile CXXSRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' JSENGINE='$(JSENGINE)' javascript_build_cpp + +clean: + $(MAKE) -f $(EXAMPLES_TOP)/Makefile javascript_clean diff --git a/Examples/javascript/exception/Makefile b/Examples/javascript/exception/Makefile new file mode 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/exception/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../example.mk diff --git a/Examples/javascript/exception/binding.gyp b/Examples/javascript/exception/binding.gyp new file mode 100644 index 000000000..2be0a17a2 --- /dev/null +++ b/Examples/javascript/exception/binding.gyp @@ -0,0 +1,29 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example.cxx", "example_wrap.cxx" ], + '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_cc': [ "-Wno-unused-variable", "-Wno-unused-but-set-variable", "-Wno-unused-but-set-parameter"], + 'cflags!': [ '-fno-exceptions' ], + 'cflags_cc!': [ '-fno-exceptions', '-fno-rtti' ] + } + ] + ] + } + ] +} 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 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/functor/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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/nspace/Makefile b/Examples/javascript/nspace/Makefile new file mode 100644 index 000000000..ea04c7df8 --- /dev/null +++ b/Examples/javascript/nspace/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../example.mk diff --git a/Examples/javascript/nspace/binding.gyp b/Examples/javascript/nspace/binding.gyp new file mode 100644 index 000000000..69af46b22 --- /dev/null +++ b/Examples/javascript/nspace/binding.gyp @@ -0,0 +1,8 @@ +{ + "targets": [ + { + "target_name": "example", + "sources": [ "example_wrap.cxx" ] + } + ] +} diff --git a/Examples/javascript/nspace/example.h b/Examples/javascript/nspace/example.h new file mode 100644 index 000000000..53066980a --- /dev/null +++ b/Examples/javascript/nspace/example.h @@ -0,0 +1,23 @@ +#ifndef _example_guardian_ +#define _example_guardian_ + +int module_function() { return 7; } +int module_variable = 9; + +namespace MyWorld { + class World { + public: + World() : world_max_count(9) {} + int create_world() { return 17; } + const int world_max_count; // = 9 + }; + namespace Nested { + class Dweller { + public: + enum Gender { MALE = 0, FEMALE = 1 }; + static int count() { return 19; } + }; + } +} + +#endif diff --git a/Examples/javascript/nspace/example.i b/Examples/javascript/nspace/example.i new file mode 100644 index 000000000..c30f87fec --- /dev/null +++ b/Examples/javascript/nspace/example.i @@ -0,0 +1,10 @@ +%module example + +%{ +#include "example.h" +%} + +%nspace MyWorld::Nested::Dweller; +%nspace MyWorld::World; + +%include "example.h" diff --git a/Examples/javascript/nspace/example.js b/Examples/javascript/nspace/example.js new file mode 100644 index 000000000..79cd3913f --- /dev/null +++ b/Examples/javascript/nspace/example.js @@ -0,0 +1 @@ +module.exports = require("./build/Release/example"); diff --git a/Examples/javascript/nspace/runme.js b/Examples/javascript/nspace/runme.js new file mode 100644 index 000000000..d6a49d8d4 --- /dev/null +++ b/Examples/javascript/nspace/runme.js @@ -0,0 +1,50 @@ +// File: runme.js + +// This file illustrates class C++ interface generated +// by SWIG. + +var example = require("./example"); + +// Calling a module function ( aka global function ) +if (example.module_function() !== 7) { + throw new Error("example.module_function() should equal 7"); +} +console.log("example.module_function(): " + example.module_function()); + +// Accessing a module (aka global) variable +if (example.module_variable !== 9) { + throw new Error("example.module_variable should equal 9"); +} +console.log("example.module_variable: " + example.module_variable); + +// Creating an instance of the class +var w1 = new example.MyWorld.World(); +console.log("Creating class instance: w1 = new example.MyWorld.World(): " + w1); + +// Accessing class members +if (w1.create_world() !== 17) { + throw new Error("w1.create_world() should equal 17"); +} +console.log("w1.create_world() = " + w1.create_world()); + +if (w1.world_max_count !== 9) { + throw new Error("w1.world_max_count should equal 9"); +} +console.log("w1.world_max_count = " + w1.world_max_count); + +// Accessing enums from class within namespace +if (example.MyWorld.Nested.Dweller.MALE !== 0) { + throw new Error("example.MyWorld.Nested.Dweller.MALE should equal 0"); +} +console.log("Accessing enums: ex.MyWorld.Nested.Dweller.MALE = " + example.MyWorld.Nested.Dweller.MALE); + +if (example.MyWorld.Nested.Dweller.FEMALE !== 1) { + throw new Error("example.MyWorld.Nested.Dweller.FEMALE should equal 1"); +} +console.log("Accessing enums: ex.MyWorld.Nested.Dweller.FEMALE = " + example.MyWorld.Nested.Dweller.FEMALE); + +// Accessing static member function +if (example.MyWorld.Nested.Dweller.count() !== 19) { + throw new Error("example.MyWorld.Nested.Dweller.count() should equal 19"); +} +console.log("Accessing static member function: ex.MyWorld.Nested.Dweller.count() = " + example.MyWorld.Nested.Dweller.count()); diff --git a/Examples/javascript/operator/Makefile b/Examples/javascript/operator/Makefile new file mode 100644 index 000000000..ea04c7df8 --- /dev/null +++ b/Examples/javascript/operator/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../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 100644 index 000000000..ea04c7df8 --- /dev/null +++ b/Examples/javascript/overload/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../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 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/pointer/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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 100644 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 100644 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 100644 index 000000000..fb8cf0c74 --- /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"); +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)); +console.log(" b = " + example.intp_value(b)); +console.log(" c = " + example.intp_value(c)); + +//// 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); + +// 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 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/reference/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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 100644 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 100644 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 100644 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 100644 index 000000000..88c108314 --- /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:"); +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"); +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"); +va = new example.VectorArray(10); +console.log("va = " + va); + +// ----- 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"); +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."); +for (i = 0; i < 1000000; i++) { + c = va.get(i % 10); +} +//---------TODO--------- +//----- Clean up ----- +//console.log("Cleaning up"); + +//example.delete_VectorArray(va); +//example.delete_Vector(a); +//example.delete_Vector(b); + diff --git a/Examples/javascript/simple/Makefile b/Examples/javascript/simple/Makefile new file mode 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/simple/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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 100644 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 100644 index 000000000..ea04c7df8 --- /dev/null +++ b/Examples/javascript/template/Makefile @@ -0,0 +1,3 @@ +SRCS = + +include ../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 100644 index 000000000..31846faae --- /dev/null +++ b/Examples/javascript/variables/Makefile @@ -0,0 +1,3 @@ +SRCS = example.cxx + +include ../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 100644 index 000000000..f10390a9e --- /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); + 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 100644 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 100644 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 100644 index 000000000..537e17296 --- /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 printed from Javascript)"); +console.log("ivar = " + example.ivar); +console.log("svar = " + example.svar); +console.log("lvar = " + example.lvar); +console.log("uivar = " + example.uivar); +console.log("usvar = " + example.usvar); +console.log("ulvar = " + example.ulvar); +console.log("scvar = " + example.scvar); +console.log("ucvar = " + example.ucvar); +console.log("fvar = " + example.fvar); +console.log("dvar = " + example.dvar); +console.log("cvar = " + example.cvar); +console.log("strvar = " + example.strvar); +console.log("cstrvar = " + example.cstrvar); +console.log("iptrvar = " + example.iptrvar); +console.log("name = " + example.name); +console.log("ptptr = " + example.ptptr + ": " + example.Point_print(example.ptptr)); +console.log("pt = " + example.pt + ": " + example.Point_print(example.pt)); + + +console.log("\nVariables (values printed 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."); +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/lua/class/example.cxx b/Examples/lua/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/lua/class/example.cxx +++ b/Examples/lua/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/lua/class/runme.lua b/Examples/lua/class/runme.lua index 2c3ad8ced..5d140defe 100644 --- a/Examples/lua/class/runme.lua +++ b/Examples/lua/class/runme.lua @@ -53,7 +53,6 @@ print("\nGuess I'll clean up now") -- Note: this invokes the virtual destructor c=nil s=nil -s = 3 -- call gc to make sure they are collected collectgarbage() diff --git a/Examples/modula3/class/example.cxx b/Examples/modula3/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/modula3/class/example.cxx +++ b/Examples/modula3/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/octave/class/example.cxx b/Examples/octave/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/octave/class/example.cxx +++ b/Examples/octave/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/perl5/check.list b/Examples/perl5/check.list index 78d45fc0b..dda849311 100644 --- a/Examples/perl5/check.list +++ b/Examples/perl5/check.list @@ -6,6 +6,7 @@ constants2 extend funcptr import +java multimap multiple_inheritance pointer diff --git a/Examples/perl5/java/Makefile b/Examples/perl5/java/Makefile index ff3aab0e7..3a0bb215d 100644 --- a/Examples/perl5/java/Makefile +++ b/Examples/perl5/java/Makefile @@ -8,15 +8,15 @@ LIBS = -lm check: build $(MAKE) -f $(TOP)/Makefile perl5_run -build: Example.class +build: Example.class Example.h $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' CXX="gcj" \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ CXXSHARED="gcj -fpic -shared Example.class" PERL5_CCFLAGS='' PERL5_EXP='' LIBS="-lstdc++" perl5_cpp clean: $(MAKE) -f $(TOP)/Makefile perl5_clean rm -f *.class Example.h -Example.class: Example.java +Example.class Example.h: Example.java gcj -fPIC -C -c -g Example.java - gcjh Example + gcjh Example.class diff --git a/Examples/python/java/Makefile b/Examples/python/java/Makefile index 12a9b512a..2ce219969 100644 --- a/Examples/python/java/Makefile +++ b/Examples/python/java/Makefile @@ -6,10 +6,11 @@ INTERFACE = example.i LIBS = -lm check: build + $(MAKE) -f $(TOP)/Makefile python_run -build: Example.class +build: Example.class Example.h $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' CXX="gcj" \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ CXXSHARED="gcj -fpic -shared Example.class" DEFS='' LIBS="-lstdc++" python_cpp clean: @@ -17,6 +18,6 @@ clean: rm -f $(TARGET).py rm -f *.class Example.h -Example.class: Example.java +Example.class Example.h: Example.java gcj -fPIC -C -c -g Example.java - gcjh Example + gcjh Example.class diff --git a/Examples/python/java/example.i b/Examples/python/java/example.i index 13d5b5e70..80e08870f 100644 --- a/Examples/python/java/example.i +++ b/Examples/python/java/example.i @@ -7,3 +7,7 @@ %include Example.h + +%extend Example { + ~Example() {} +} diff --git a/Examples/r/class/example.cxx b/Examples/r/class/example.cxx index 1e8e203dd..046304519 100644 --- a/Examples/r/class/example.cxx +++ b/Examples/r/class/example.cxx @@ -1,4 +1,4 @@ -/* File : example.c */ +/* File : example.cxx */ #include "example.h" #define M_PI 3.14159265358979323846 @@ -11,18 +11,18 @@ void Shape::move(double dx, double dy) { int Shape::nshapes = 0; -double Circle::area(void) { +double Circle::area() { return M_PI*radius*radius; } -double Circle::perimeter(void) { +double Circle::perimeter() { return 2*M_PI*radius; } -double Square::area(void) { +double Square::area() { return width*width; } -double Square::perimeter(void) { +double Square::perimeter() { return 4*width; } diff --git a/Examples/ruby/java/Makefile b/Examples/ruby/java/Makefile index 4d2493493..a71635baa 100644 --- a/Examples/ruby/java/Makefile +++ b/Examples/ruby/java/Makefile @@ -8,15 +8,15 @@ LIBS = -lm check: build $(MAKE) -f $(TOP)/Makefile ruby_run -build: Example.class +build: Example.class Example.h $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' CXX="gcj" \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ CXXSHARED="gcj -fpic -shared Example.class" LIBS="-lstdc++" DEFS='' ruby_cpp clean: $(MAKE) -f $(TOP)/Makefile ruby_clean rm -f *.class Example.h -Example.class: Example.java +Example.class Example.h: Example.java gcj -fPIC -C -c -g Example.java - gcjh Example + gcjh Example.class diff --git a/Examples/tcl/java/Makefile b/Examples/tcl/java/Makefile index 3a9212381..a3819ab7c 100644 --- a/Examples/tcl/java/Makefile +++ b/Examples/tcl/java/Makefile @@ -8,18 +8,15 @@ LIBS = -lm check: build $(MAKE) -f $(TOP)/Makefile tcl_run -build: Example.class +build: Example.class Example.h $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ - TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' CXX="gcj" \ - TCL_CXXSHARED="gcj -fpic -shared Example.class " LIBS="-lstdc++" DEFS='' tcl_cpp + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + TCLCXXSHARED="gcj -fpic -shared Example.class " LIBS="-lstdc++" DEFS='' tcl_cpp clean: $(MAKE) -f $(TOP)/Makefile tcl_clean rm -f *.class Example.h -run: - tclsh runme.tcl - -Example.class: Example.java +Example.class Example.h: Example.java gcj -fPIC -C -c -g Example.java - gcjh Example + gcjh Example.class diff --git a/Examples/test-suite/allegrocl/Makefile.in b/Examples/test-suite/allegrocl/Makefile.in index 5f75bfc08..697c15a45 100644 --- a/Examples/test-suite/allegrocl/Makefile.in +++ b/Examples/test-suite/allegrocl/Makefile.in @@ -12,7 +12,7 @@ top_builddir = @top_builddir@ # these cpp tests generate warnings/errors when compiling # the wrapper .cxx file. -CPP_TEST_BROKEN_CXX = +CPP_TEST_BROKEN_CXX = # the error is wrap:action code generated by swig. \ # error: can't convert [std::string] 'b' to 'bool' \ # might just need a bool overload op for std::string. \ @@ -71,7 +71,7 @@ CPP_TEST_CASES_ACL_UNSUPPORTED = \ extern_throws \ throw_exception \ using_pointers \ - + C_TEST_CASES_ACL_BROKEN = \ # 'cdate.i' module support \ li_cdata \ @@ -96,7 +96,7 @@ include $(srcdir)/../common.mk # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -106,7 +106,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -123,4 +123,3 @@ run_testcase = \ clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile allegrocl_clean - diff --git a/Examples/test-suite/c_delete.i b/Examples/test-suite/c_delete.i index 632340629..0c69f9f41 100644 --- a/Examples/test-suite/c_delete.i +++ b/Examples/test-suite/c_delete.i @@ -2,9 +2,9 @@ /* check C++ delete keyword is okay in C wrappers */ -#pragma SWIG nowarn=SWIGWARN_PARSE_KEYWORD +%warnfilter(SWIGWARN_PARSE_KEYWORD) delete; -#if !defined(SWIGOCTAVE) /* Octave compiles wrappers as C++ */ +#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) /* Octave and Javascript/v8 compiles wrappers as C++ */ %inline %{ struct delete { diff --git a/Examples/test-suite/c_delete_function.i b/Examples/test-suite/c_delete_function.i index 3739ceadc..8164d066b 100644 --- a/Examples/test-suite/c_delete_function.i +++ b/Examples/test-suite/c_delete_function.i @@ -2,7 +2,9 @@ /* check C++ delete keyword is okay in C wrappers */ -#if !defined(SWIGOCTAVE) /* Octave compiles wrappers as C++ */ +%warnfilter(SWIGWARN_PARSE_KEYWORD) delete; + +#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) /* Octave and Javascript/v8 compiles wrappers as C++ */ %inline %{ double delete(double d) { return d; } diff --git a/Examples/test-suite/cffi/Makefile.in b/Examples/test-suite/cffi/Makefile.in index aa8b40aec..473d395fd 100644 --- a/Examples/test-suite/cffi/Makefile.in +++ b/Examples/test-suite/cffi/Makefile.in @@ -14,13 +14,13 @@ include $(srcdir)/../common.mk # Overridden variables here # no C++ tests for now CPP_TEST_CASES = -#C_TEST_CASES += +#C_TEST_CASES += # Custom tests - tests with additional commandline options # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -30,7 +30,7 @@ CPP_TEST_CASES = +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -44,8 +44,7 @@ run_testcase = \ # Clean: (does nothing, we dont generate extra cffi code) %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile cffi_clean - diff --git a/Examples/test-suite/chicken/Makefile.in b/Examples/test-suite/chicken/Makefile.in index 3c2f3de54..4ee8cb0fa 100644 --- a/Examples/test-suite/chicken/Makefile.in +++ b/Examples/test-suite/chicken/Makefile.in @@ -3,7 +3,7 @@ ####################################################################### LANGUAGE = chicken -VARIANT = +VARIANT = SCRIPTSUFFIX = _runme.ss PROXYSUFFIX = _runme_proxy.ss srcdir = @srcdir@ @@ -17,7 +17,7 @@ SO = @SO@ # Skip the STD cases for now, except for li_std_string.i SKIP_CPP_STD_CASES = Yes -CPP_TEST_CASES += li_std_string +CPP_TEST_CASES += li_std_string EXTRA_TEST_CASES += chicken_ext_test.externaltest @@ -39,7 +39,7 @@ SWIGOPT += -nounit %.multiproxy: SCRIPTSUFFIX = $(PROXYSUFFIX) # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -55,7 +55,7 @@ SWIGOPT += -nounit $(MAKE) $*.cproxy; \ fi -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -92,7 +92,7 @@ run_testcase = \ # Clean %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile chicken_clean diff --git a/Examples/test-suite/clisp/Makefile.in b/Examples/test-suite/clisp/Makefile.in index 24655a60f..1fe3c23ac 100644 --- a/Examples/test-suite/clisp/Makefile.in +++ b/Examples/test-suite/clisp/Makefile.in @@ -14,13 +14,13 @@ include $(srcdir)/../common.mk # Overridden variables here # no C++ tests for now CPP_TEST_CASES = -#C_TEST_CASES += +#C_TEST_CASES += # Custom tests - tests with additional commandline options # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -30,7 +30,7 @@ CPP_TEST_CASES = +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -44,8 +44,7 @@ run_testcase = \ # Clean: (does nothing, we dont generate extra clisp code) %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile clisp_clean - diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index d0463badd..3614f0467 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -609,6 +609,7 @@ C_TEST_CASES += \ global_functions \ immutable_values \ inctest \ + infinity \ integers \ keyword_rename \ lextype \ @@ -635,6 +636,7 @@ C_TEST_CASES += \ simple_array \ sizeof_pointer \ sneaky1 \ + string_simple \ struct_rename \ struct_initialization \ typedef_struct \ 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/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index 993699bc8..e54edcc35 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -40,7 +40,7 @@ csharp_lib_arrays.cpptest: CSHARPFLAGSSPECIAL = -unsafe csharp_swig2_compatibility.cpptest: SWIGOPT += -DSWIG2_CSHARP # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +(cd $* && $(swig_and_compile_cpp)) +$(run_testcase) @@ -50,7 +50,7 @@ csharp_swig2_compatibility.cpptest: SWIGOPT += -DSWIG2_CSHARP +(cd $* && $(swig_and_compile_c)) +$(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +(cd $* && $(swig_and_compile_multi_cpp)) +$(run_testcase) 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/director_nspace_director_name_collision.i b/Examples/test-suite/director_nspace_director_name_collision.i index 8fd27c968..190bdf4fa 100644 --- a/Examples/test-suite/director_nspace_director_name_collision.i +++ b/Examples/test-suite/director_nspace_director_name_collision.i @@ -34,7 +34,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::A::Foo; %nspace TopLevel::B::Foo; #else diff --git a/Examples/test-suite/enum_forward.i b/Examples/test-suite/enum_forward.i index 1609fa8e9..c82e17be7 100644 --- a/Examples/test-suite/enum_forward.i +++ b/Examples/test-suite/enum_forward.i @@ -1,7 +1,7 @@ %module enum_forward -/* This contains C code that is not valid C++03 and Octave wrappers are always compiled as C++ */ -#if !defined(SWIGOCTAVE) +/* This contains C code that is not valid C++03 and Octave, and Javascript(v8) wrappers are always compiled as C++ */ +#if !defined(SWIGOCTAVE) && !defined(SWIG_JAVASCRIPT_V8) %{ enum ForwardEnum1 { AAA, BBB }; enum ForwardEnum2 { CCC, DDD }; diff --git a/Examples/test-suite/errors/Makefile.in b/Examples/test-suite/errors/Makefile.in index 601dcd303..e4ba7b751 100644 --- a/Examples/test-suite/errors/Makefile.in +++ b/Examples/test-suite/errors/Makefile.in @@ -29,13 +29,13 @@ CPP_ERROR_TEST_CASES := $(filter cpp_%, $(ALL_ERROR_TEST_CASES)) C_ERROR_TEST_CASES := $(filter-out $(CPP_ERROR_TEST_CASES), $(ALL_ERROR_TEST_CASES)) ERROR_TEST_CASES := $(CPP_ERROR_TEST_CASES:=.cpptest) \ - $(C_ERROR_TEST_CASES:=.ctest) + $(C_ERROR_TEST_CASES:=.ctest) include $(srcdir)/../common.mk # Rules for the different types of tests -%.cpptest: +%.cpptest: echo "$(ACTION)ing errors testcase $*" -$(SWIG) -c++ -python -Wall -Fstandard $(SWIGOPT) $*.i 2>&1 | $(TODOS) > $*.$(ERROR_EXT) $(COMPILETOOL) diff -c $*.stderr $*.$(ERROR_EXT) @@ -46,9 +46,8 @@ include $(srcdir)/../common.mk $(COMPILETOOL) diff -c $*.stderr $*.$(ERROR_EXT) %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile $(LANGUAGE)_clean @rm -f *.$(ERROR_EXT) *.py - diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in index 535d05a6e..64a84f820 100644 --- a/Examples/test-suite/go/Makefile.in +++ b/Examples/test-suite/go/Makefile.in @@ -29,7 +29,7 @@ include $(srcdir)/../common.mk .SUFFIXES: .cpptest .ctest .multicpptest # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase_cpp) @@ -39,7 +39,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_multi_testcase) diff --git a/Examples/test-suite/guile/Makefile.in b/Examples/test-suite/guile/Makefile.in index 0c7b3137c..493dde4f5 100644 --- a/Examples/test-suite/guile/Makefile.in +++ b/Examples/test-suite/guile/Makefile.in @@ -14,9 +14,9 @@ GUILE = @GUILE@ GUILE_RUNTIME= C_TEST_CASES = long_long \ - list_vector \ - multivalue \ - pointer_in_out + list_vector \ + multivalue \ + pointer_in_out include $(srcdir)/../common.mk @@ -28,7 +28,7 @@ INCLUDES += -I$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/guile %.multicpptest: SWIGOPT += $(GUILE_RUNTIME) # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -38,7 +38,7 @@ INCLUDES += -I$(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/guile +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) diff --git a/Examples/test-suite/infinity.i b/Examples/test-suite/infinity.i new file mode 100644 index 000000000..726150f02 --- /dev/null +++ b/Examples/test-suite/infinity.i @@ -0,0 +1,47 @@ +%module infinity + +/* 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; + +%{ +#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 +%} + +%inline %{ +/* 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/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 453d29be8..c708c5c09 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -59,7 +59,7 @@ director_nspace.%: JAVA_PACKAGE = $*Package director_nspace_director_name_collision.%: JAVA_PACKAGE = $*Package # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +(cd $(JAVA_PACKAGE) && $(swig_and_compile_cpp)) $(run_testcase) @@ -69,7 +69,7 @@ director_nspace_director_name_collision.%: JAVA_PACKAGE = $*Package +(cd $(JAVA_PACKAGE) && $(swig_and_compile_c)) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +(cd $(JAVA_PACKAGE) && $(swig_and_compile_multi_cpp)) $(run_testcase) diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in new file mode 100644 index 000000000..7368ea9a3 --- /dev/null +++ b/Examples/test-suite/javascript/Makefile.in @@ -0,0 +1,114 @@ +####################################################################### +# Makefile for javascript test-suite +####################################################################### + +LANGUAGE = javascript +NODEGYP = @NODEGYP@ +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 + +include $(srcdir)/../common.mk + +_setup = \ + if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + echo "$(ACTION)ing $(LANGUAGE) ($(JSENGINE)) testcase $* (with run test)" ; \ + else \ + echo "$(ACTION)ing $(LANGUAGE) ($(JSENGINE)) testcase $*" ; \ + 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 $(LANGUAGE) ($(JSENGINE)) testcase typemap_variables" ; + +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\" + + # Note: we need to use swig in C parse mode, but make node-gyp believe it is c++ (via file extension) + swig_and_compile_c = \ + sh ./setup_test.sh $* $(GYP_CFLAGS); \ + $(SWIG) -javascript $(SWIGOPT) -o $*_wrap.cxx ../$*.i; \ + $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null + + swig_and_compile_cpp = \ + sh ./setup_test.sh $* $(GYP_CFLAGS); \ + $(SWIG) -c++ -javascript $(SWIGOPT) ../$*.i; \ + $(NODEGYP) --loglevel=silent --directory $* configure build 1>>/dev/null + + run_testcase = \ + if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \ + node $(srcdir)/$*$(SCRIPTSUFFIX); \ + fi + + + %.ctest: + $(_setup) + $(swig_and_compile_c) + $(run_testcase) + + %.cpptest: + $(_setup) + $(swig_and_compile_cpp) + $(run_testcase) + + %.multicpptest: + $(_setup) + +else + + SWIGOPT += -$(JSENGINE) + + run_testcase = \ + if [ -f $(srcdir)/$*$(SCRIPTSUFFIX) ]; then \ + $(top_srcdir)/Tools/javascript/javascript -$(JSENGINE) $(srcdir)/$*$(SCRIPTSUFFIX); \ + fi + + %.ctest: + $(_setup) + +$(swig_and_compile_c) + $(run_testcase) + + %.cpptest: + $(_setup) + +$(swig_and_compile_cpp) + $(run_testcase) + + %.multicpptest: + $(_setup) + +$(swig_and_compile_multi_cpp) + $(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..7b5182ff6 --- /dev/null +++ b/Examples/test-suite/javascript/infinity_runme.js @@ -0,0 +1,4 @@ +var infinity = require("./infinity"); + +var my_infinity = infinity.INFINITY; +var ret_val = infinity.use_infinity(my_infinity); 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..f1afff428 --- /dev/null +++ b/Examples/test-suite/javascript/nspace_runme.js @@ -0,0 +1,76 @@ +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); + +nspace.Outer.Inner1.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/string_simple_runme.js b/Examples/test-suite/javascript/string_simple_runme.js new file mode 100644 index 000000000..dbdd4136d --- /dev/null +++ b/Examples/test-suite/javascript/string_simple_runme.js @@ -0,0 +1,10 @@ +var string_simple = require("./string_simple"); + +// Test unicode string +var str = "olé"; + +var copy = string_simple.copy_string(str); + +if (str !== copy) { + throw "Error: copy is not equal: original="+str+", copy="+copy; +} 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/lua/Makefile.in b/Examples/test-suite/lua/Makefile.in index 66a0d2da9..0950c9d91 100644 --- a/Examples/test-suite/lua/Makefile.in +++ b/Examples/test-suite/lua/Makefile.in @@ -28,7 +28,7 @@ LIBS = -L. lua_no_module_global.%: SWIGOPT += -nomoduleglobal # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -38,7 +38,7 @@ lua_no_module_global.%: SWIGOPT += -nomoduleglobal +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -52,7 +52,7 @@ run_testcase = \ # Clean: (does nothing, we dont generate extra lua code) %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile lua_clean @@ -60,5 +60,5 @@ clean: cvsignore: @echo '*wrap* *.so *.dll *.exp *.lib' @echo Makefile - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.lua; done - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.lua CVS/Entries ; then echo $${i}_runme.lua; fi; done + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.lua; done + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.lua CVS/Entries ; then echo $${i}_runme.lua; fi; done diff --git a/Examples/test-suite/lua/operator_overload_runme.lua b/Examples/test-suite/lua/operator_overload_runme.lua index f3753749b..5ba06ff08 100644 --- a/Examples/test-suite/lua/operator_overload_runme.lua +++ b/Examples/test-suite/lua/operator_overload_runme.lua @@ -79,7 +79,7 @@ assert(tostring(Op(1))=="Op(1)") assert(tostring(Op(-3))=="Op(-3)") --- check that operator overloads is correctly propogated accross hierarchy +-- check that operator overloads are correctly propogated down inheritance hierarchy a_d=OpDerived() b_d=OpDerived(5) diff --git a/Examples/test-suite/mzscheme/Makefile.in b/Examples/test-suite/mzscheme/Makefile.in index fcaf33a48..67b8bddf2 100644 --- a/Examples/test-suite/mzscheme/Makefile.in +++ b/Examples/test-suite/mzscheme/Makefile.in @@ -18,7 +18,7 @@ include $(srcdir)/../common.mk # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -28,7 +28,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -42,7 +42,7 @@ run_testcase = \ # Clean %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile mzscheme_clean diff --git a/Examples/test-suite/nspace.i b/Examples/test-suite/nspace.i index 1520b3652..25e7104b2 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/Examples/test-suite/ocaml/Makefile.in b/Examples/test-suite/ocaml/Makefile.in index f16c3da95..63edec26a 100644 --- a/Examples/test-suite/ocaml/Makefile.in +++ b/Examples/test-suite/ocaml/Makefile.in @@ -10,7 +10,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -C_TEST_CASES = +C_TEST_CASES = run_testcase = \ if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) -a \ @@ -21,7 +21,7 @@ run_testcase = \ $(COMPILETOOL) $(OCAMLC) -c $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \ $(COMPILETOOL) $(OCAMLC) swig.cmo -custom -g -cc '$(CXX)' -o runme $(srcdir)/$(*).cmo $(srcdir)/$(*)_runme.cmo $(srcdir)/$(*)_wrap.o && \ $(RUNTOOL) ./runme; \ - fi ; + fi ; check_quant: cat /dev/null > testing diff --git a/Examples/test-suite/ocaml/makedebugtop b/Examples/test-suite/ocaml/makedebugtop old mode 100755 new mode 100644 diff --git a/Examples/test-suite/octave/Makefile.in b/Examples/test-suite/octave/Makefile.in index dc309e8c6..e48d36a64 100644 --- a/Examples/test-suite/octave/Makefile.in +++ b/Examples/test-suite/octave/Makefile.in @@ -21,7 +21,7 @@ CPP_TEST_BROKEN += \ li_std_set \ li_std_stream -#C_TEST_CASES += +#C_TEST_CASES += # # This test only works with modern C compilers @@ -39,7 +39,7 @@ CSRCS = $(srcdir)/octave_empty.c # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -49,7 +49,7 @@ CSRCS = $(srcdir)/octave_empty.c +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -72,13 +72,13 @@ clean: cvsignore: @echo '*wrap* *.mc *.so *.dll *.exp *.lib' @echo Makefile - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.m; done - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.m CVS/Entries ; then echo $${i}_runme.m; fi; done - @echo clientdata_prop_a.m - @echo clientdata_prop_b.m - @echo imports_a.m - @echo imports_b.m - @echo mod_a.m mod_b.m + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.m; done + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.m CVS/Entries ; then echo $${i}_runme.m; fi; done + @echo clientdata_prop_a.m + @echo clientdata_prop_b.m + @echo imports_a.m + @echo imports_b.m + @echo mod_a.m mod_b.m @echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.m hugemod_b.m hugemod_runme.m @echo template_typedef_import.m diff --git a/Examples/test-suite/octave/iadd_runme.m b/Examples/test-suite/octave/iadd_runme.m old mode 100755 new mode 100644 diff --git a/Examples/test-suite/octave/overload_complicated_runme.m b/Examples/test-suite/octave/overload_complicated_runme.m old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/Makefile.in b/Examples/test-suite/perl5/Makefile.in index 67eaf5c9a..68f32a54a 100644 --- a/Examples/test-suite/perl5/Makefile.in +++ b/Examples/test-suite/perl5/Makefile.in @@ -31,7 +31,7 @@ include $(srcdir)/../common.mk # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -41,7 +41,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) diff --git a/Examples/test-suite/perl5/char_binary_runme.pl b/Examples/test-suite/perl5/char_binary_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/class_ignore_runme.pl b/Examples/test-suite/perl5/class_ignore_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/contract_runme.pl b/Examples/test-suite/perl5/contract_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/enum_template_runme.pl b/Examples/test-suite/perl5/enum_template_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/grouping_runme.pl b/Examples/test-suite/perl5/grouping_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/ignore_parameter_runme.pl b/Examples/test-suite/perl5/ignore_parameter_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/inherit_missing_runme.pl b/Examples/test-suite/perl5/inherit_missing_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/li_std_except_runme.pl b/Examples/test-suite/perl5/li_std_except_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/minherit_runme.pl b/Examples/test-suite/perl5/minherit_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/naturalvar_runme.pl b/Examples/test-suite/perl5/naturalvar_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/preproc_runme.pl b/Examples/test-suite/perl5/preproc_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/primitive_types_runme.pl b/Examples/test-suite/perl5/primitive_types_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/reference_global_vars_runme.pl b/Examples/test-suite/perl5/reference_global_vars_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/rename_scope_runme.pl b/Examples/test-suite/perl5/rename_scope_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/return_const_value_runme.pl b/Examples/test-suite/perl5/return_const_value_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/run-perl-test.pl b/Examples/test-suite/perl5/run-perl-test.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/sizet_runme.pl b/Examples/test-suite/perl5/sizet_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/sneaky1_runme.pl b/Examples/test-suite/perl5/sneaky1_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/template_typedef_cplx2_runme.pl b/Examples/test-suite/perl5/template_typedef_cplx2_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/typedef_class_runme.pl b/Examples/test-suite/perl5/typedef_class_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/typename_runme.pl b/Examples/test-suite/perl5/typename_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/using1_runme.pl b/Examples/test-suite/perl5/using1_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/using2_runme.pl b/Examples/test-suite/perl5/using2_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/perl5/wrapmacro_runme.pl b/Examples/test-suite/perl5/wrapmacro_runme.pl old mode 100755 new mode 100644 diff --git a/Examples/test-suite/php/Makefile.in b/Examples/test-suite/php/Makefile.in index fcdcac2b9..735a3137e 100644 --- a/Examples/test-suite/php/Makefile.in +++ b/Examples/test-suite/php/Makefile.in @@ -29,7 +29,7 @@ missingctests: missingtests: missingcpptests missingctests # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) +$(run_testcase) @@ -39,7 +39,7 @@ missingtests: missingcpptests missingctests +$(swig_and_compile_c) +$(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) +$(run_testcase) diff --git a/Examples/test-suite/php/arrays_runme.php b/Examples/test-suite/php/arrays_runme.php index 23490e61e..ae17d05e7 100644 --- a/Examples/test-suite/php/arrays_runme.php +++ b/Examples/test-suite/php/arrays_runme.php @@ -12,6 +12,7 @@ check::classname(simplestruct,$ss); $as=new arraystruct(); $as->array_c="abc"; check::equal($as->array_c,"a",'$as->array_c=="a"'); +check::equal(isset($as->array_const_i),TRUE,'isset($as->array_const_i)'); check::done(); ?> diff --git a/Examples/test-suite/pike/Makefile.in b/Examples/test-suite/pike/Makefile.in index 389dc74f8..c1ebb747b 100644 --- a/Examples/test-suite/pike/Makefile.in +++ b/Examples/test-suite/pike/Makefile.in @@ -18,7 +18,7 @@ include $(srcdir)/../common.mk # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -28,7 +28,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -46,4 +46,3 @@ run_testcase = \ clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile pike_clean - diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index e7db32fb7..389aed9ea 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -26,7 +26,7 @@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ -PY2TO3 = 2to3 -x import +PY2TO3 = 2to3 -x import CPP_TEST_CASES += \ @@ -109,7 +109,7 @@ VALGRIND_OPT += --suppressions=pythonswig.supp # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: +$(convert_testcase) $(setup) +$(swig_and_compile_cpp) @@ -121,7 +121,7 @@ VALGRIND_OPT += --suppressions=pythonswig.supp +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: +$(convert_testcase) $(setup) +$(swig_and_compile_multi_cpp) @@ -131,7 +131,7 @@ VALGRIND_OPT += --suppressions=pythonswig.supp # Call 2to3 to generate Python 3.x test from the Python 2.x's *_runme.py file %$(PY3SCRIPTSUFFIX): %$(PY2SCRIPTSUFFIX) cp $< $@ - $(PY2TO3) -w $@ >/dev/null 2>&1 + $(PY2TO3) -w $@ >/dev/null 2>&1 # Runs the testcase. A testcase is only run if @@ -172,12 +172,12 @@ clean: cvsignore: @echo '*wrap* *.pyc *.so *.dll *.exp *.lib' @echo Makefile - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.py; done - @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.py CVS/Entries ; then echo $${i}_runme.py; fi; done - @echo clientdata_prop_a.py - @echo clientdata_prop_b.py - @echo imports_a.py - @echo imports_b.py + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.py; done + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.py CVS/Entries ; then echo $${i}_runme.py; fi; done + @echo clientdata_prop_a.py + @echo clientdata_prop_b.py + @echo imports_a.py + @echo imports_b.py @echo mod_a.py mod_b.py @echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.py hugemod_b.py hugemod_runme.py @echo template_typedef_import.py @@ -185,9 +185,8 @@ cvsignore: hugemod_runme = hugemod$(SCRIPTPREFIX) hugemod: - perl hugemod.pl $(hugemod_runme) + perl hugemod.pl $(hugemod_runme) $(MAKE) hugemod_a.cpptest $(MAKE) hugemod_b.cpptest sh -c "time $(PYTHON) $(hugemod_runme)" sh -c "time $(PYTHON) $(hugemod_runme)" - diff --git a/Examples/test-suite/r/Makefile.in b/Examples/test-suite/r/Makefile.in index 18e2d4b25..32d9b85da 100644 --- a/Examples/test-suite/r/Makefile.in +++ b/Examples/test-suite/r/Makefile.in @@ -28,7 +28,7 @@ include $(srcdir)/../common.mk # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -38,14 +38,14 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_multitestcase) # Runs the testcase. -# -# Run the runme if it exists. If not just load the R wrapper to +# +# Run the runme if it exists. If not just load the R wrapper to # check for syntactic correctness run_testcase = \ if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ @@ -58,7 +58,7 @@ run_multitestcase = \ for f in `cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list` ; do \ if [ -f $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX) ]; then \ env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=.:"$$PATH" \ - $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX); \ + $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(SCRIPTSUFFIX); \ else \ $(RUNTOOL) $(RUNR) $(srcdir)/$(SCRIPTPREFIX)$${f}$(WRAPSUFFIX); \ fi; \ @@ -74,5 +74,3 @@ clean: rm -f $${f}.R $${f}.Rout ; \ done \ fi - - diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index ab366ccd4..40985e532 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -42,7 +42,7 @@ SWIGOPT += -w801 -noautorename -features autodoc=4 ruby_naming.cpptest: SWIGOPT += -autorename # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -52,7 +52,7 @@ ruby_naming.cpptest: SWIGOPT += -autorename +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -66,7 +66,7 @@ run_testcase = \ # Clean %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile ruby_clean diff --git a/Examples/test-suite/ruby/abstract_access_runme.rb b/Examples/test-suite/ruby/abstract_access_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/access_change_runme.rb b/Examples/test-suite/ruby/access_change_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/add_link_runme.rb b/Examples/test-suite/ruby/add_link_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/anonymous_bitfield_runme.rb b/Examples/test-suite/ruby/anonymous_bitfield_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/apply_signed_char_runme.rb b/Examples/test-suite/ruby/apply_signed_char_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/apply_strings_runme.rb b/Examples/test-suite/ruby/apply_strings_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/argout_runme.rb b/Examples/test-suite/ruby/argout_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/arrays_runme.rb b/Examples/test-suite/ruby/arrays_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/cast_operator_runme.rb b/Examples/test-suite/ruby/cast_operator_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/casts_runme.rb b/Examples/test-suite/ruby/casts_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/check_missing_tests.rb b/Examples/test-suite/ruby/check_missing_tests.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/class_ignore_runme.rb b/Examples/test-suite/ruby/class_ignore_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/const_const_runme.rb b/Examples/test-suite/ruby/const_const_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/constover_runme.rb b/Examples/test-suite/ruby/constover_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/cpp_namespace_runme.rb b/Examples/test-suite/ruby/cpp_namespace_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/default_constructor_runme.rb b/Examples/test-suite/ruby/default_constructor_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/dynamic_cast_runme.rb b/Examples/test-suite/ruby/dynamic_cast_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/enum_thorough_runme.rb b/Examples/test-suite/ruby/enum_thorough_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/function_typedef_runme.rb b/Examples/test-suite/ruby/function_typedef_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/imports_runme.rb b/Examples/test-suite/ruby/imports_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/integers_runme.rb b/Examples/test-suite/ruby/integers_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_cstring_runme.rb b/Examples/test-suite/ruby/li_cstring_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_math_runme.rb b/Examples/test-suite/ruby/li_math_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_functors_runme.rb b/Examples/test-suite/ruby/li_std_functors_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_map_runme.rb b/Examples/test-suite/ruby/li_std_map_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_multimap_runme.rb b/Examples/test-suite/ruby/li_std_multimap_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_pair_runme.rb b/Examples/test-suite/ruby/li_std_pair_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_queue_runme.rb b/Examples/test-suite/ruby/li_std_queue_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_set_runme.rb b/Examples/test-suite/ruby/li_std_set_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_speed2_runme.rb b/Examples/test-suite/ruby/li_std_speed2_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_stack_runme.rb b/Examples/test-suite/ruby/li_std_stack_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_stream_runme.rb b/Examples/test-suite/ruby/li_std_stream_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_vector_enum_runme.rb b/Examples/test-suite/ruby/li_std_vector_enum_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/li_std_vector_runme.rb b/Examples/test-suite/ruby/li_std_vector_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/namespace_typemap_runme.rb b/Examples/test-suite/ruby/namespace_typemap_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/overload_bool_runme.rb b/Examples/test-suite/ruby/overload_bool_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/overload_copy_runme.rb b/Examples/test-suite/ruby/overload_copy_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/overload_extend_runme.rb b/Examples/test-suite/ruby/overload_extend_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/overload_extendc_runme.rb b/Examples/test-suite/ruby/overload_extendc_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/overload_simple_runme.rb b/Examples/test-suite/ruby/overload_simple_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/overload_template_runme.rb b/Examples/test-suite/ruby/overload_template_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/primitive_ref_runme.rb b/Examples/test-suite/ruby/primitive_ref_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/ruby_li_std_speed_runme.rb b/Examples/test-suite/ruby/ruby_li_std_speed_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/sneaky1_runme.rb b/Examples/test-suite/ruby/sneaky1_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/std_containers_runme.rb b/Examples/test-suite/ruby/std_containers_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/stl_new_runme.rb b/Examples/test-suite/ruby/stl_new_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/swig_assert.rb b/Examples/test-suite/ruby/swig_assert.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/swig_gc.rb b/Examples/test-suite/ruby/swig_gc.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/template_inherit_runme.rb b/Examples/test-suite/ruby/template_inherit_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/template_ns4_runme.rb b/Examples/test-suite/ruby/template_ns4_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/template_ns_runme.rb b/Examples/test-suite/ruby/template_ns_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/template_rename_runme.rb b/Examples/test-suite/ruby/template_rename_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/typedef_inherit_runme.rb b/Examples/test-suite/ruby/typedef_inherit_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/typedef_scope_runme.rb b/Examples/test-suite/ruby/typedef_scope_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/typemap_namespace_runme.rb b/Examples/test-suite/ruby/typemap_namespace_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/ruby/typename_runme.rb b/Examples/test-suite/ruby/typename_runme.rb old mode 100755 new mode 100644 diff --git a/Examples/test-suite/string_simple.i b/Examples/test-suite/string_simple.i new file mode 100644 index 000000000..c319aa1ef --- /dev/null +++ b/Examples/test-suite/string_simple.i @@ -0,0 +1,13 @@ +%module string_simple + +%newobject copy_string; + +%inline %{ +#include +const char* copy_string(const char* str) { + size_t len = strlen(str); + char* newstring = (char*) malloc(len + 1); + strcpy(newstring, str); + return newstring; +} +%} diff --git a/Examples/test-suite/tcl/Makefile.in b/Examples/test-suite/tcl/Makefile.in index 49d2a7826..6ab293fb9 100644 --- a/Examples/test-suite/tcl/Makefile.in +++ b/Examples/test-suite/tcl/Makefile.in @@ -4,7 +4,7 @@ LANGUAGE = tcl TCLSH = tclsh -SCRIPTSUFFIX = _runme.tcl +SCRIPTSUFFIX = _runme.tcl srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ @@ -27,7 +27,7 @@ include $(srcdir)/../common.mk # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -37,7 +37,7 @@ include $(srcdir)/../common.mk +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -51,7 +51,7 @@ run_testcase = \ # Clean %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile tcl_clean diff --git a/Examples/test-suite/uffi/Makefile.in b/Examples/test-suite/uffi/Makefile.in index 8ad153961..5fd000a96 100644 --- a/Examples/test-suite/uffi/Makefile.in +++ b/Examples/test-suite/uffi/Makefile.in @@ -14,13 +14,13 @@ include $(srcdir)/../common.mk # Overridden variables here # no C++ tests for now CPP_TEST_CASES = -#C_TEST_CASES += +#C_TEST_CASES += # Custom tests - tests with additional commandline options # none! # Rules for the different types of tests -%.cpptest: +%.cpptest: $(setup) +$(swig_and_compile_cpp) $(run_testcase) @@ -30,7 +30,7 @@ CPP_TEST_CASES = +$(swig_and_compile_c) $(run_testcase) -%.multicpptest: +%.multicpptest: $(setup) +$(swig_and_compile_multi_cpp) $(run_testcase) @@ -44,8 +44,7 @@ run_testcase = \ # Clean: (does nothing, we dont generate extra uffi code) %.clean: - + @exit 0 clean: $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile uffi_clean - diff --git a/Lib/gcj/cni.i b/Lib/gcj/cni.i index b12148e91..fcc56687a 100644 --- a/Lib/gcj/cni.i +++ b/Lib/gcj/cni.i @@ -4,10 +4,6 @@ %include -extern jobject JvAllocObject (jclass cls); - -extern jobject JvAllocObject (jclass cls, jsize sz); - extern void JvInitClass (jclass cls); extern jstring JvAllocString (jsize sz); @@ -30,7 +26,7 @@ extern void *JvMalloc (jsize size); extern void JvFree (void *ptr); -extern jint JvCreateJavaVM (void* vm_args); +extern jint JvCreateJavaVM (JvVMInitArgs* vm_args); extern java::lang::Thread* JvAttachCurrentThread (jstring name, java::lang::ThreadGroup* group); diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg index 612f83086..bbc602b0d 100644 --- a/Lib/go/goruntime.swg +++ b/Lib/go/goruntime.swg @@ -116,7 +116,7 @@ extern void _cgo_panic(const char *); file is the same as the version of gccgo. */ #define SWIG_GCC_VERSION \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC__PATH_LEVEL__) + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if SWIG_GCC_VERSION < 40700 #define SwigDoCgocall() diff --git a/Lib/guile/Makefile b/Lib/guile/Makefile index 17f5feced..fba7fd5d3 100644 --- a/Lib/guile/Makefile +++ b/Lib/guile/Makefile @@ -1,4 +1,3 @@ co: co RCS/*.i* RCS/*.swg* - 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..738b54d70 --- /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 construction 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 100644 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 100644 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 100644 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 100644 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 100644 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..67a81146e --- /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 construction 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..ea11b0837 --- /dev/null +++ b/Lib/javascript/v8/javascriptruntime.swg @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------- + * javascriptruntime.swg + * + * ----------------------------------------------------------------------------- */ + +// V8 Version Macro +// ---------------- +// v8 does not (until now) provide a version macro - which is still discussed and may come soon. +// Until then, we set a default version which can be overridden via command line using V8_VERSION: +// swig -javascript -v8 -DV8_VERSION=0x031110 +// Or code in the interface file using SWIG_V8_VERSION: +// %begin %{#define SWIG_V8_VERSION 0x031110%} + +%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 + + +// Node support +// ------------ + +#ifdef BUILDING_NODE_EXTENSION +%insert("runtime") %{ +#include +%} +#endif + + +// V8 runtime +// ---------- + +%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/std_common.i b/Lib/javascript/v8/std_common.i new file mode 100644 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 100644 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 100644 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 100644 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 100644 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/lua/luarun.swg b/Lib/lua/luarun.swg index 42efb9b8f..d038f4af1 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -1274,8 +1274,8 @@ SWIGINTERN void SWIG_Lua_add_class_instance_details(lua_State *L, swig_lua_clas #endif } -/* helpers to add user defined class metamedhods - __add, __sub etc. Necessity for those helpers - arise from the following issue: Lua runtime checks for metamethod existence with rawget function +/* Helpers to add user defined class metamedhods - __add, __sub etc. The helpers are needed + for the following issue: Lua runtime checks for metamethod existence with rawget function ignoring our SWIG-provided __index and __newindex functions. Thus our inheritance-aware method search algorithm doesn't work in such case. (Not to say that Lua runtime queries metamethod directly in metatable and not in object). @@ -1287,7 +1287,7 @@ SWIGINTERN void SWIG_Lua_add_class_instance_details(lua_State *L, swig_lua_clas SWIGRUNTIME int SWIG_Lua_resolve_metamethod(lua_State *L); /*forward declaration*/ -/* The real function that resolveds metamethod. +/* The real function that resolves a metamethod. * Function searches given class and all it's bases(recursively) for first instance of something that is * not equal to SWIG_Lua_resolve_metatmethod. (Almost always this 'something' is actuall metamethod implementation * and it is a SWIG-generated C function.). It returns value on the top of the L and there is no garbage below the @@ -1367,7 +1367,6 @@ SWIGRUNTIME int SWIG_Lua_resolve_metamethod(lua_State *L) */ SWIGINTERN int SWIG_Lua_add_class_user_metamethod(lua_State *L, swig_lua_class *clss, const int metatable_index) { - /* metamethod name - on the top of the stack */ assert(lua_isstring(L,-1)); @@ -1382,7 +1381,6 @@ SWIGINTERN int SWIG_Lua_add_class_user_metamethod(lua_State *L, swig_lua_class * } lua_pop(L,1); - /* Iterating over immediate bases */ int success = 0; int i = 0; @@ -1410,7 +1408,6 @@ SWIGINTERN int SWIG_Lua_add_class_user_metamethod(lua_State *L, swig_lua_class * break; } - return success; } @@ -1430,7 +1427,6 @@ SWIGINTERN void SWIG_Lua_add_class_user_metamethods(lua_State *L, swig_lua_class if(is_inheritable) { /* if metamethod is inheritable */ SWIG_Lua_add_class_user_metamethod(L,clss,metatable_index); } - } lua_pop(L,1); /* remove inheritable metatmethods table */ @@ -1452,7 +1448,6 @@ SWIGINTERN void SWIG_Lua_add_class_user_metamethods(lua_State *L, swig_lua_class * a __getitem/__setitem method should be defined */ lua_pop(L,1); /* pop class metatable */ - } /* Register class static methods,attributes etc as well as constructor proxy */ diff --git a/Lib/mzscheme/Makefile b/Lib/mzscheme/Makefile index 17f5feced..fba7fd5d3 100644 --- a/Lib/mzscheme/Makefile +++ b/Lib/mzscheme/Makefile @@ -1,4 +1,3 @@ co: co RCS/*.i* RCS/*.swg* - diff --git a/Lib/perl5/Makefile.in b/Lib/perl5/Makefile.in index 1fee86ccc..e0b3b74b8 100644 --- a/Lib/perl5/Makefile.in +++ b/Lib/perl5/Makefile.in @@ -1,6 +1,6 @@ # --------------------------------------------------------------- # SWIG Perl5 Makefile -# +# # This file can be used to build various Perl5 extensions with SWIG. # By default this file is set up for dynamic loading, but it can # be easily customized for static extensions by modifying various @@ -17,11 +17,11 @@ # script and should already reflect your machine. #---------------------------------------------------------------- -SRCS = -CXXSRCS = -OBJCSRCS = -OBJS = -INTERFACE = +SRCS = +CXXSRCS = +OBJCSRCS = +OBJS = +INTERFACE = WRAPFILE = $(INTERFACE:.i=_wrap.c) WRAPOBJ = $(INTERFACE:.i=_wrap.o) TARGET = module@SO@ # Use this kind of target for dynamic loading @@ -32,8 +32,8 @@ exec_prefix = @exec_prefix@ CC = @CC@ CXX = @CXX@ -OBJC = @CC@ -Wno-import # -Wno-import needed for gcc -CFLAGS = +OBJC = @CC@ -Wno-import # -Wno-import needed for gcc +CFLAGS = INCLUDES = LIBS = @@ -42,9 +42,9 @@ LIBS = # SWIGOPT = SWIG compiler options # SWIGCC = Compiler used to compile the wrapper file -SWIG = $(exec_prefix)/bin/swig -SWIGOPT = -perl5 -SWIGCC = $(CC) +SWIG = $(exec_prefix)/bin/swig +SWIGOPT = -perl5 +SWIGCC = $(CC) # SWIG Library files. Uncomment this to statically rebuild Perl #SWIGLIBS = -static -lperlmain.i @@ -67,12 +67,12 @@ BUILD = @LDSHARED@ # need to provide additional link libraries (this is not always required). #DLL_LIBS = -L/usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.7.2 \ - -L/usr/local/lib -lg++ -lstdc++ -lgcc + -L/usr/local/lib -lg++ -lstdc++ -lgcc # Perl installation PERL_INCLUDE = -I@PERL5EXT@ -PERL_LIB = -L@PERL5EXT@ -lperl +PERL_LIB = -L@PERL5EXT@ -lperl PERL_FLAGS = -Dbool=char -Dexplicit= # Build libraries (needed for static builds) @@ -118,9 +118,3 @@ $(TARGET): $(WRAPOBJ) $(ALLOBJS) clean: rm -f $(COBJS) $(CXXOBJS) $(OBJCOBJS) $(WRAPOBJ) $(WRAPFILE) $(TARGET) - - - - - - diff --git a/Lib/perl5/Makefile.pl b/Lib/perl5/Makefile.pl index 05240f1e9..cffdc8e79 100644 --- a/Lib/perl5/Makefile.pl +++ b/Lib/perl5/Makefile.pl @@ -7,7 +7,7 @@ # 2. Run perl as 'perl Makefile.pl' # 3. Type 'make' to build your module # 4. Type 'make install' to install your module. -# +# # See "Programming Perl", 2nd. Ed, for more gory details than # you ever wanted to know. @@ -17,5 +17,3 @@ WriteMakefile( 'LIBS' => [''], # Custom libraries (if any) 'OBJECT' => '$module_wrap.o' # Object files ); - - diff --git a/Lib/python/Makefile.in b/Lib/python/Makefile.in index 71effea70..27c384449 100644 --- a/Lib/python/Makefile.in +++ b/Lib/python/Makefile.in @@ -1,6 +1,6 @@ # --------------------------------------------------------------- # SWIG Python Makefile -# +# # This file can be used to build various Python extensions with SWIG. # By default this file is set up for dynamic loading, but it can # be easily customized for static extensions by modifying various @@ -17,11 +17,11 @@ # script and should already reflect your machine. #---------------------------------------------------------------- -SRCS = -CXXSRCS = -OBJCSRCS = -OBJS = -INTERFACE = +SRCS = +CXXSRCS = +OBJCSRCS = +OBJS = +INTERFACE = WRAPFILE = $(INTERFACE:.i=_wrap.c) WRAPOBJ = $(INTERFACE:.i=_wrap.o) TARGET = module@SO@ # Use this kind of target for dynamic loading @@ -32,8 +32,8 @@ exec_prefix = @exec_prefix@ CC = @CC@ CXX = @CXX@ -OBJC = @CC@ -Wno-import # -Wno-import needed for gcc -CFLAGS = +OBJC = @CC@ -Wno-import # -Wno-import needed for gcc +CFLAGS = INCLUDES = LIBS = @@ -42,9 +42,9 @@ LIBS = # SWIGOPT = SWIG compiler options # SWIGCC = Compiler used to compile the wrapper file -SWIG = $(exec_prefix)/bin/swig -SWIGOPT = -python -SWIGCC = $(CC) +SWIG = $(exec_prefix)/bin/swig +SWIGOPT = -python +SWIGCC = $(CC) # SWIG Library files. Uncomment if rebuilding the Python interpreter #SWIGLIBS = -lembed.i @@ -67,11 +67,11 @@ BUILD = @LDSHARED@ # need to provide additional link libraries (this is not always required). #DLL_LIBS = -L/usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.7.2 \ - -L/usr/local/lib -lg++ -lstdc++ -lgcc + -L/usr/local/lib -lg++ -lstdc++ -lgcc # Python installation -PY_INCLUDE = -DHAVE_CONFIG_H @PYINCLUDE@ +PY_INCLUDE = -DHAVE_CONFIG_H @PYINCLUDE@ PY_LIB = @PYLIB@ # Build libraries (needed for static builds) @@ -107,7 +107,7 @@ all: $(TARGET) # Convert the wrapper file into an object file $(WRAPOBJ) : $(WRAPFILE) - $(SWIGCC) -c $(CCSHARED) $(CFLAGS) $(WRAPFILE) $(INCLUDES) $(PY_INCLUDE) + $(SWIGCC) -c $(CCSHARED) $(CFLAGS) $(WRAPFILE) $(INCLUDES) $(PY_INCLUDE) $(WRAPFILE) : $(INTERFACE) $(SWIG) $(SWIGOPT) -o $(WRAPFILE) $(SWIGLIBS) $(INTERFACE) @@ -117,7 +117,3 @@ $(TARGET): $(WRAPOBJ) $(ALLOBJS) clean: rm -f $(COBJS) $(CXXOBJS) $(OBJCOBJS) $(WRAPOBJ) $(WRAPFILE) $(TARGET) - - - - diff --git a/Lib/ruby/Makefile.swig b/Lib/ruby/Makefile.swig index a7f3ae3d2..648b32134 100644 --- a/Lib/ruby/Makefile.swig +++ b/Lib/ruby/Makefile.swig @@ -7,7 +7,7 @@ # 3. Type 'make -f Makefile.swig' to generate wrapper code and Makefile. # 4. Type 'make' to build your extension. # 5. Type 'make install' to install your extension. -# +# MODULE = yourmodule FEATURE = $(MODULE) diff --git a/Lib/tcl/Makefile.in b/Lib/tcl/Makefile.in index 2ab0f7b01..13d7d4653 100644 --- a/Lib/tcl/Makefile.in +++ b/Lib/tcl/Makefile.in @@ -1,10 +1,10 @@ # --------------------------------------------------------------- # SWIG Tcl Makefile -# +# # This file can be used to build various Tcl extensions with SWIG. # By default this file is set up for dynamic loading, but it can # be easily customized for static extensions by modifying various -# portions of the file. +# portions of the file. # # SRCS = C source files # CXXSRCS = C++ source files @@ -19,11 +19,11 @@ # application. #---------------------------------------------------------------- -SRCS = -CXXSRCS = -OBJCSRCS = -OBJS = -INTERFACE = +SRCS = +CXXSRCS = +OBJCSRCS = +OBJS = +INTERFACE = WRAPFILE = $(INTERFACE:.i=_wrap.c) WRAPOBJ = $(INTERFACE:.i=_wrap.o) TARGET = module@SO@ # Use this kind of target for dynamic loading @@ -34,8 +34,8 @@ exec_prefix = @exec_prefix@ CC = @CC@ CXX = @CXX@ -OBJC = @CC@ -Wno-import # -Wno-import needed for gcc -CFLAGS = +OBJC = @CC@ -Wno-import # -Wno-import needed for gcc +CFLAGS = INCLUDES = LIBS = @@ -44,9 +44,9 @@ LIBS = # SWIGOPT = SWIG compiler options # SWIGCC = Compiler used to compile the wrapper file -SWIG = $(exec_prefix)/bin/swig +SWIG = $(exec_prefix)/bin/swig SWIGOPT = -tcl # use -tcl8 for Tcl 8.0 -SWIGCC = $(CC) +SWIGCC = $(CC) # SWIG Library files. Uncomment if rebuilding tclsh #SWIGLIBS = -ltclsh.i @@ -69,7 +69,7 @@ BUILD = @LDSHARED@ # need to provide additional link libraries (this is not always required). #DLL_LIBS = -L/usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.7.2 \ - -L/usr/local/lib -lg++ -lstdc++ -lgcc + -L/usr/local/lib -lg++ -lstdc++ -lgcc # Tcl installation (where is Tcl located) @@ -85,7 +85,7 @@ SYSLIBS = $(LIBM) $(LIBC) @LIBS@ # Build options (uncomment only one of these) BUILD_LIBS = $(LIBS) # Dynamic loading -#BUILD_LIBS = $(TCL_LIB) -ltcl $(LIBS) $(SYSLIBS) # tclsh +#BUILD_LIBS = $(TCL_LIB) -ltcl $(LIBS) $(SYSLIBS) # tclsh # Compilation rules for non-SWIG components @@ -110,7 +110,7 @@ all: $(TARGET) # Convert the wrapper file into an object file $(WRAPOBJ) : $(WRAPFILE) - $(SWIGCC) -c $(CCSHARED) $(CFLAGS) $(WRAPFILE) $(INCLUDES) $(TCL_INCLUDE) + $(SWIGCC) -c $(CCSHARED) $(CFLAGS) $(WRAPFILE) $(INCLUDES) $(TCL_INCLUDE) $(WRAPFILE) : $(INTERFACE) $(SWIG) $(SWIGOPT) -o $(WRAPFILE) $(SWIGLIBS) $(INTERFACE) @@ -120,7 +120,3 @@ $(TARGET): $(WRAPOBJ) $(ALLOBJS) clean: rm -f $(COBJS) $(CXXOBJS) $(OBJCOBJS) $(WRAPOBJ) $(WRAPFILE) $(TARGET) - - - - 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..06e4724c7 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 : @@ -244,10 +249,10 @@ check-%-examples : # gcj individual example java.actionexample: @if $(skip-gcj); then \ - echo "skipping Examples/$(LANGUAGE)/java $(ACTION) (gcj test)"; \ - else \ + echo "skipping Examples/$(LANGUAGE)/java $(ACTION) (gcj test)"; \ + else \ echo $(ACTION)ing Examples/$(LANGUAGE)/java; \ - (cd Examples/$(LANGUAGE)/java && $(MAKE) $(FLAGS) $(chk-set-env) $(ACTION)) \ + (cd Examples/$(LANGUAGE)/java && $(MAKE) $(FLAGS) $(chk-set-env) $(ACTION) RUNPIPE=$(RUNPIPE)) \ fi # Checks testcases in the test-suite excluding those which are known to be broken @@ -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,18 +475,19 @@ 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 -install-lib: +install-lib: @echo "Installing the SWIG library" @$(MKINSTDIRS) $(DESTDIR)$(SWIG_LIB) @for file in $(srcdir)/Lib/*.i $(srcdir)/Lib/*.swg ; do \ i=`basename $$file` ; \ echo "Installing $(DESTDIR)$(SWIG_LIB)/$$i"; \ - $(INSTALL_DATA) $$file $(DESTDIR)$(SWIG_LIB)/$$i; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(SWIG_LIB)/$$i; \ done; @for lang in $(lib-languages) $(lib-modules); \ do \ diff --git a/Source/Makefile.am b/Source/Makefile.am index 3464b511d..824f93ac8 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -48,6 +48,7 @@ eswig_SOURCES = CParse/cscanner.c \ Modules/go.cxx \ Modules/guile.cxx \ Modules/java.cxx \ + Modules/javascript.cxx \ Modules/lang.cxx \ Modules/lua.cxx \ Modules/main.cxx \ @@ -108,7 +109,7 @@ eswig_LDADD = @SWIGLIBS@ CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ # The executable is copied to the root directory for installation and running the test-suite. -# This occurs on each invocation of make and is a step towards providing support for multiple +# This occurs on each invocation of make and is a step towards providing support for multiple # build directories. all-local: eswig@EXEEXT@ cp -f $(top_builddir)/Source/eswig@EXEEXT@ $(top_builddir)/swig@EXEEXT@ @@ -154,4 +155,3 @@ beautify-file: indent -kr --honour-newlines --line-length160 --indent-level2 --braces-on-func-def-line --leave-optional-blank-lines $(SWIGTYPEDEFS) $(INDENTFILE) -o $(INDENTFILE).tmp; cat $(INDENTFILE).tmp | sed -e 's/const const /const /' > $(INDENTFILE); rm $(INDENTFILE).tmp; - diff --git a/Source/Modules/javascript.cxx b/Source/Modules/javascript.cxx new file mode 100644 index 000000000..20af76f9f --- /dev/null +++ b/Source/Modules/javascript.cxx @@ -0,0 +1,2427 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3 + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * javascript.cxx + * + * Javascript language module for SWIG. + * ----------------------------------------------------------------------------- */ + +#include "swigmod.h" +#include "cparse.h" + +/** + * Enables extra debugging information in typemaps. + */ +static bool js_template_enable_debug = false; + +#define ERR_MSG_ONLY_ONE_ENGINE_PLEASE "Only one engine can be specified at a time." + +// keywords used for state variables +#define NAME "name" +#define NAME_MANGLED "name_mangled" +#define 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" +#define HAS_TEMPLATES "has_templates" +#define FORCE_CPP "force_cpp" +#define RESET true + +// keys for global state variables +#define CREATE_NAMESPACES "create_namespaces" +#define REGISTER_NAMESPACES "register_namespaces" +#define INITIALIZER "initializer" + +// keys for class scoped state variables +#define MEMBER_VARIABLES "member_variables" +#define MEMBER_FUNCTIONS "member_functions" +#define STATIC_FUNCTIONS "static_functions" +#define STATIC_VARIABLES "static_variables" + + +/** + * A convenience class to manage state variables for emitters. + * The implementation delegates to SWIG Hash DOHs and provides + * named sub-hashes for class, variable, and function states. + */ +class JSEmitterState { + +public: + JSEmitterState(); + ~JSEmitterState(); + DOH *globals(); + DOH *globals(const char *key, DOH *initial = 0); + DOH *clazz(bool reset = false); + DOH *clazz(const char *key, DOH *initial = 0); + DOH *function(bool reset = false); + DOH *function(const char *key, DOH *initial = 0); + DOH *variable(bool reset = false); + DOH *variable(const char *key, DOH *initial = 0); + static int IsSet(DOH *val); + +private: + DOH *getState(const char *key, bool reset = false); + Hash *globalHash; +}; + +/** + * A convenience class that wraps a code snippet used as template + * for code generation. + */ +class Template { + +public: + Template(const String *code); + Template(const String *code, const String *templateName); + Template(const Template & other); + ~Template(); + String *str(); + Template & replace(const String *pattern, const String *repl); + Template & print(DOH *doh); + Template & pretty_print(DOH *doh); + void operator=(const Template & t); + Template & trim(); + +private: + String *code; + String *templateName; +}; + +/** + * JSEmitter represents an abstraction of javascript code generators + * for different javascript engines. + **/ +class JSEmitter { + +protected: + + typedef JSEmitterState State; + + enum MarshallingMode { + Setter, + Getter, + Ctor, + Function + }; + +public: + + enum JSEngine { + JavascriptCore, + V8, + NodeJS + }; + + JSEmitter(JSEngine engine); + + virtual ~ JSEmitter(); + + /** + * Opens output files and temporary output DOHs. + */ + virtual int initialize(Node *n); + + /** + * Writes all collected code into the output file(s). + */ + virtual int dump(Node *n) = 0; + + /** + * Cleans up all open output DOHs. + */ + virtual int close() = 0; + + /** + * Switches the context for code generation. + * + * Classes, global variables and global functions may need to + * be registered in certain static tables. + * This method should be used to switch output DOHs correspondingly. + */ + virtual int switchNamespace(Node *); + + /** + * Invoked at the beginning of the classHandler. + */ + virtual int enterClass(Node *); + + /** + * Invoked at the end of the classHandler. + */ + virtual int exitClass(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the beginning of the variableHandler. + */ + virtual int enterVariable(Node *); + + /** + * Invoked at the end of the variableHandler. + */ + virtual int exitVariable(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the beginning of the functionHandler. + */ + virtual int enterFunction(Node *); + + /** + * Invoked at the end of the functionHandler. + */ + virtual int exitFunction(Node *) { + return SWIG_OK; + }; + + /** + * Invoked by functionWrapper callback after call to Language::functionWrapper. + */ + virtual int emitWrapperFunction(Node *n); + + /** + * Invoked 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: + + JSEngine engine; + Hash *templates; + State state; + + // contains context specific data (DOHs) + // to allow generation of namespace related code + // which are switched on namespace change + Hash *namespaces; + Hash *current_namespace; + String *defaultResultName; + File *f_wrappers; +}; + +/* factory methods for concrete JSEmitters: */ + +JSEmitter *swig_javascript_create_JSCEmitter(); +JSEmitter *swig_javascript_create_V8Emitter(); +JSEmitter *swig_javascript_create_NodeJSEmitter(); + +/********************************************************************** + * 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 engine = -1; + + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp(argv[i], "-v8") == 0) { + if (engine != -1) { + Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE); + SWIG_exit(-1); + } + Swig_mark_arg(i); + engine = JSEmitter::V8; + } else if (strcmp(argv[i], "-jsc") == 0) { + if (engine != -1) { + Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE); + SWIG_exit(-1); + } + Swig_mark_arg(i); + engine = JSEmitter::JavascriptCore; + } else if (strcmp(argv[i], "-node") == 0) { + if (engine != -1) { + Printf(stderr, ERR_MSG_ONLY_ONE_ENGINE_PLEASE); + SWIG_exit(-1); + } + Swig_mark_arg(i); + engine = JSEmitter::NodeJS; + } else if (strcmp(argv[i], "-debug-codetemplates") == 0) { + Swig_mark_arg(i); + js_template_enable_debug = true; + } else if (strcmp(argv[i], "-help") == 0) { + fputs(usage, stdout); + return; + } + } + } + + switch (engine) { + case JSEmitter::V8: + { + emitter = swig_javascript_create_V8Emitter(); + Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0); + SWIG_library_directory("javascript/v8"); + // V8 API is C++, so output must be C++ compatibile even when wrapping C code + if (!cparse_cplusplus) { + Swig_cparse_cplusplusout(1); + } + break; + } + case JSEmitter::JavascriptCore: + { + emitter = swig_javascript_create_JSCEmitter(); + Preprocessor_define("SWIG_JAVASCRIPT_JSC 1", 0); + SWIG_library_directory("javascript/jsc"); + break; + } + case JSEmitter::NodeJS: + { + emitter = swig_javascript_create_V8Emitter(); + Preprocessor_define("SWIG_JAVASCRIPT_V8 1", 0); + Preprocessor_define("BUILDING_NODE_EXTENSION 1", 0); + SWIG_library_directory("javascript/v8"); + break; + } + default: + { + Printf(stderr, "SWIG Javascript: Unknown engine. Please specify one of '-jsc', '-v8' or '-node'.\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(JSEmitter::JSEngine engine) +: engine(engine), templates(NewHash()), namespaces(NULL), current_namespace(NULL), defaultResultName(NewString("result")), f_wrappers(NULL) { +} + +/* ----------------------------------------------------------------------------- + * ~JSEmitter() + * ----------------------------------------------------------------------------- */ + +JSEmitter::~JSEmitter() { + Delete(templates); +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::RegisterTemplate() : Registers a code template + * + * Note: this is used only by JAVASCRIPT::fragmentDirective(). + * ----------------------------------------------------------------------------- */ + +int JSEmitter::registerTemplate(const String *name, const String *code) { + if (!State::IsSet(state.globals(HAS_TEMPLATES))) { + SetFlag(state.globals(), HAS_TEMPLATES); + } + return Setattr(templates, name, code); +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::getTemplate() : Provides a registered code template + * ----------------------------------------------------------------------------- */ + +Template JSEmitter::getTemplate(const String *name) { + String *templ = Getattr(templates, name); + + if (!templ) { + Printf(stderr, "Could not find template %s\n.", name); + 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 *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: we can remove the is_abstract flag now, as this + // is called for non-abstract classes only. + Setattr(state.clazz(), IS_ABSTRACT, 0); + + ParmList *params = Getattr(n, "parms"); + emit_parameter_variables(params, wrapper); + emit_attach_parmmaps(params, wrapper); + // HACK: in test-case `ignore_parameter` emit_attach_parmmaps generated an extra line of applied typemaps. + // 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.globals(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"); + + // HACK: forcing usage of cppvalue for v8 (which turned out to fix typdef_struct.i, et. al) + if (State::IsSet(state.globals(FORCE_CPP)) && Getattr(n, "cppvalue") != NULL) { + value = Getattr(n, "cppvalue"); + } + + 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 for member functions. + // We can safely ignore them, as members are not associated to a namespace (only their class) + if (GetFlag(n, "ismember")) { + return SWIG_OK; + } + + 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) { + // It seems that only classes have 'sym:nspace' set. + // We try to get the namespace from the qualified name (i.e., everything before the last '::') + nspace = Swig_scopename_prefix(Getattr(n, "name")); + } + + // If there is not even a scopename prefix then it must be global scope + if (nspace == NULL) { + current_namespace = Getattr(namespaces, "::"); + return SWIG_OK; + } + + String *scope = NewString(nspace); + // replace "." with "::" that we can use Swig_scopename_last + Replaceall(scope, ".", "::"); + + // if the scope is not yet registered + // create (parent) namespaces recursively + if (!Getattr(namespaces, scope)) { + createNamespace(scope); + } + current_namespace = Getattr(namespaces, scope); + + return SWIG_OK; +} + +int JSEmitter::createNamespace(String *scope) { + + String *parent_scope = Swig_scopename_prefix(scope); + Hash *parent_namespace; + if (parent_scope == 0) { + parent_namespace = Getattr(namespaces, "::"); + } else if (!Getattr(namespaces, parent_scope)) { + createNamespace(parent_scope); + parent_namespace = Getattr(namespaces, parent_scope); + } else { + parent_namespace = Getattr(namespaces, parent_scope); + } + assert(parent_namespace != 0); + + Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name"))); + 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(JSEmitter::JavascriptCore), NULL_STR(NewString("NULL")), VETO_SET(NewString("JS_veto_set_variable")), f_wrap_cpp(NULL), f_runtime(NULL), f_header(NULL), f_init(NULL) { +} + +JSCEmitter::~JSCEmitter() { + Delete(NULL_STR); + Delete(VETO_SET); +} + + +/* --------------------------------------------------------------------- + * marshalInputArgs() + * + * Process all of the arguments passed into the argv array + * and convert them into C/C++ function arguments using the + * supplied typemaps. + * --------------------------------------------------------------------- */ + +void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { + Parm *p; + String *tm; + + // 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.globals(CREATE_NAMESPACES, NewString("")); + state.globals(REGISTER_NAMESPACES, NewString("")); + state.globals(INITIALIZER, NewString("")); + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("begin", f_wrap_cpp); + Swig_register_filebyname("header", f_header); + Swig_register_filebyname("wrapper", f_wrappers); + Swig_register_filebyname("runtime", f_runtime); + Swig_register_filebyname("init", f_init); + + Swig_banner(f_wrap_cpp); + + return SWIG_OK; +} + +int JSCEmitter::dump(Node *n) { + /* Get the module name */ + String *module = Getattr(n, "name"); + + Template initializer_define(getTemplate("js_initializer_define")); + initializer_define.replace("$jsname", module).pretty_print(f_header); + + SwigType_emit_type_table(f_runtime, f_wrappers); + + Printv(f_wrap_cpp, f_runtime, "\n", 0); + Printv(f_wrap_cpp, f_header, "\n", 0); + Printv(f_wrap_cpp, f_wrappers, "\n", 0); + + emitNamespaces(); + + // compose the initializer function using a template + Template initializer(getTemplate("js_initializer")); + initializer.replace("$jsname", module) + .replace("$jsregisterclasses", state.globals(INITIALIZER)) + .replace("$jscreatenamespaces", state.globals(CREATE_NAMESPACES)) + .replace("$jsregisternamespaces", state.globals(REGISTER_NAMESPACES)) + .pretty_print(f_init); + + Printv(f_wrap_cpp, f_init, 0); + + return SWIG_OK; +} + +int JSCEmitter::close() { + Delete(f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + Delete(namespaces); + Delete(f_wrap_cpp); + return SWIG_OK; +} + +int JSCEmitter::enterFunction(Node *n) { + + JSEmitter::enterFunction(n); + + return SWIG_OK; +} + +int JSCEmitter::exitFunction(Node *n) { + Template t_function = getTemplate("jsc_function_declaration"); + + bool is_member = GetFlag(n, "ismember") | 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)) { + t_function.pretty_print(state.clazz(STATIC_FUNCTIONS)); + } else { + t_function.pretty_print(state.clazz(MEMBER_FUNCTIONS)); + } + } else { + t_function.pretty_print(Getattr(current_namespace, "functions")); + } + + return SWIG_OK; +} + +int JSCEmitter::enterVariable(Node *n) { + JSEmitter::enterVariable(n); + state.variable(GETTER, NULL_STR); + state.variable(SETTER, VETO_SET); + return SWIG_OK; +} + +int JSCEmitter::exitVariable(Node *n) { + Template t_variable(getTemplate("jsc_variable_declaration")); + t_variable.replace("$jsname", state.variable(NAME)) + .replace("$jsgetter", state.variable(GETTER)) + .replace("$jssetter", state.variable(SETTER)); + + if (GetFlag(n, "ismember")) { + if (GetFlag(state.variable(), IS_STATIC) + || Equal(Getattr(n, "nodeType"), "enumitem")) { + t_variable.pretty_print(state.clazz(STATIC_VARIABLES)); + } else { + t_variable.pretty_print(state.clazz(MEMBER_VARIABLES)); + } + } else { + t_variable.pretty_print(Getattr(current_namespace, "values")); + } + + return SWIG_OK; +} + +int JSCEmitter::enterClass(Node *n) { + JSEmitter::enterClass(n); + state.clazz(MEMBER_VARIABLES, NewString("")); + state.clazz(MEMBER_FUNCTIONS, NewString("")); + state.clazz(STATIC_VARIABLES, NewString("")); + state.clazz(STATIC_FUNCTIONS, NewString("")); + + Template t_class_decl = getTemplate("jsc_class_declaration"); + t_class_decl.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .pretty_print(f_wrappers); + + return SWIG_OK; +} + +int JSCEmitter::exitClass(Node *n) { + Template t_class_tables(getTemplate("jsc_class_tables")); + t_class_tables.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsclassvariables", state.clazz(MEMBER_VARIABLES)) + .replace("$jsclassfunctions", state.clazz(MEMBER_FUNCTIONS)) + .replace("$jsstaticclassfunctions", state.clazz(STATIC_FUNCTIONS)) + .replace("$jsstaticclassvariables", state.clazz(STATIC_VARIABLES)) + .pretty_print(f_wrappers); + + /* adds the ctor wrappers at this position */ + // Note: this is necessary to avoid extra forward declarations. + //Append(f_wrappers, state.clazz(CTOR_WRAPPERS)); + + // for abstract classes add a vetoing ctor + if (GetFlag(state.clazz(), IS_ABSTRACT)) { + Template t_veto_ctor(getTemplate("js_veto_ctor")); + t_veto_ctor.replace("$jswrapper", state.clazz(CTOR)) + .replace("$jsname", state.clazz(NAME)) + .pretty_print(f_wrappers); + } + + /* adds a class template statement to initializer function */ + Template t_classtemplate(getTemplate("jsc_class_definition")); + + /* prepare registration of base class */ + String *jsclass_inheritance = NewString(""); + Node *base_class = getBaseClass(n); + if (base_class != NULL) { + Template t_inherit(getTemplate("jsc_class_inherit")); + t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsbaseclassmangled", SwigType_manglestr(Getattr(base_class, "name"))) + .pretty_print(jsclass_inheritance); + } else { + Template t_inherit(getTemplate("jsc_class_noinherit")); + t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .pretty_print(jsclass_inheritance); + } + + t_classtemplate.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsmangledtype", state.clazz(TYPE_MANGLED)) + .replace("$jsclass_inheritance", jsclass_inheritance) + .replace("$jsctor", state.clazz(CTOR)) + .replace("$jsdtor", state.clazz(DTOR)) + .pretty_print(state.globals(INITIALIZER)); + Delete(jsclass_inheritance); + + /* Note: this makes sure that there is a swig_type added for this class */ + SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0")); + + /* adds a class registration statement to initializer function */ + Template t_registerclass(getTemplate("jsc_class_registration")); + t_registerclass.replace("$jsname", state.clazz(NAME)) + .replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsnspace", Getattr(state.clazz("nspace"), NAME_MANGLED)) + .pretty_print(state.globals(INITIALIZER)); + + return SWIG_OK; +} + +Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent) { + 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.globals(CREATE_NAMESPACES), t_createNamespace.str()); + + // Don't register 'exports' as namespace. It is return to the application. + if (!Equal("exports", name)) { + Template t_registerNamespace(getTemplate("jsc_nspace_registration")); + t_registerNamespace.replace("$jsmangledname", name_mangled) + .replace("$jsname", name) + .replace("$jsparent", parent_mangled); + Append(state.globals(REGISTER_NAMESPACES), t_registerNamespace.str()); + } + } + + return SWIG_OK; +} + +JSEmitter *swig_javascript_create_JSCEmitter() { + return new JSCEmitter(); +} + +/********************************************************************** + * V8: JSEmitter implementation for V8 engine + **********************************************************************/ + +class V8Emitter:public JSEmitter { + +public: + V8Emitter(); + + virtual ~ V8Emitter(); + virtual int initialize(Node *n); + virtual int dump(Node *n); + virtual int close(); + virtual int enterClass(Node *n); + virtual int exitClass(Node *n); + virtual int enterVariable(Node *n); + virtual int exitVariable(Node *n); + virtual int exitFunction(Node *n); + +protected: + virtual void marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static); + virtual int emitNamespaces(); + +protected: + /* built-in parts */ + String *f_runtime; + String *f_header; + String *f_init; + String *f_post_init; + + /* part for class templates */ + String *f_class_templates; + + /* parts for initilizer */ + String *f_init_namespaces; + String *f_init_class_templates; + String *f_init_wrappers; + String *f_init_inheritance; + String *f_init_class_instances; + String *f_init_static_wrappers; + String *f_init_register_classes; + String *f_init_register_namespaces; + + // the output cpp file + File *f_wrap_cpp; + + String *NULL_STR; + String *VETO_SET; + String *moduleName; + +}; + +V8Emitter::V8Emitter() +: JSEmitter(JSEmitter::V8), NULL_STR(NewString("0")), VETO_SET(NewString("JS_veto_set_variable")) { +} + +V8Emitter::~V8Emitter() { + Delete(NULL_STR); + Delete(VETO_SET); +} + +int V8Emitter::initialize(Node *n) { + JSEmitter::initialize(n); + + moduleName = Getattr(n, "name"); + + // Get the output file name + String *outfile = Getattr(n, "outfile"); + f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files()); + if (!f_wrap_cpp) { + FileErrorDisplay(outfile); + 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); + + state.globals(FORCE_CPP, NewString("1")); + + Swig_banner(f_wrap_cpp); + + return SWIG_OK; +} + +int V8Emitter::dump(Node *n) { + /* Get the module name */ + String *module = Getattr(n, "name"); + + Template initializer_define(getTemplate("js_initializer_define")); + initializer_define.replace("$jsname", module).pretty_print(f_header); + + SwigType_emit_type_table(f_runtime, f_wrappers); + + Printv(f_wrap_cpp, f_runtime, "\n", 0); + Printv(f_wrap_cpp, f_header, "\n", 0); + Printv(f_wrap_cpp, f_class_templates, "\n", 0); + Printv(f_wrap_cpp, f_wrappers, "\n", 0); + + emitNamespaces(); + + // compose the initializer function using a template + // filled with sub-parts + Template initializer(getTemplate("js_initializer")); + initializer.replace("$jsname", moduleName) + .replace("$jsv8nspaces", f_init_namespaces) + .replace("$jsv8classtemplates", f_init_class_templates) + .replace("$jsv8wrappers", f_init_wrappers) + .replace("$jsv8inheritance", f_init_inheritance) + .replace("$jsv8classinstances", f_init_class_instances) + .replace("$jsv8staticwrappers", f_init_static_wrappers) + .replace("$jsv8registerclasses", f_init_register_classes) + .replace("$jsv8registernspaces", f_init_register_namespaces); + Printv(f_init, initializer.str(), 0); + + Printv(f_wrap_cpp, f_init, 0); + + Printv(f_wrap_cpp, f_post_init, 0); + + return SWIG_OK; +} + +int V8Emitter::close() { + Delete(f_runtime); + Delete(f_header); + Delete(f_class_templates); + Delete(f_init_namespaces); + Delete(f_init_class_templates); + Delete(f_init_wrappers); + Delete(f_init_inheritance); + Delete(f_init_class_instances); + Delete(f_init_static_wrappers); + Delete(f_init_register_classes); + Delete(f_init_register_namespaces); + Delete(f_init); + Delete(f_post_init); + Delete(f_wrap_cpp); + return SWIG_OK; +} + +int V8Emitter::enterClass(Node *n) { + JSEmitter::enterClass(n); + + // emit declaration of a v8 class template + Template t_decl_class(getTemplate("jsv8_declare_class_template")); + t_decl_class.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .trim() + .pretty_print(f_class_templates); + + return SWIG_OK; +} + +int V8Emitter::exitClass(Node *n) { + if (GetFlag(state.clazz(), IS_ABSTRACT)) { + Template t_veto_ctor(getTemplate("js_veto_ctor")); + t_veto_ctor.replace("$jswrapper", state.clazz(CTOR)) + .replace("$jsname", state.clazz(NAME)) + .pretty_print(f_wrappers); + } + + /* Note: this makes sure that there is a swig_type added for this class */ + String *clientData = NewString(""); + Printf(clientData, "&%s_clientData", state.clazz(NAME_MANGLED)); + + /* Note: this makes sure that there is a swig_type added for this class */ + SwigType_remember_clientdata(state.clazz(TYPE_MANGLED), NewString("0")); + + // emit definition of v8 class template + Template t_def_class = getTemplate("jsv8_define_class_template"); + t_def_class.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsname", state.clazz(NAME)) + .replace("$jsmangledtype", state.clazz(TYPE_MANGLED)) + .replace("$jsdtor", state.clazz(DTOR)) + .trim() + .pretty_print(f_init_class_templates); + + Template t_class_instance = getTemplate("jsv8_create_class_instance"); + t_class_instance.replace("$jsname", state.clazz(NAME)) + .replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsctor", state.clazz(CTOR)) + .trim() + .pretty_print(f_init_class_instances); + + // emit inheritance setup + Node *baseClass = getBaseClass(n); + if (baseClass) { + String *base_name = Getattr(baseClass, "name"); + + Template t_inherit = getTemplate("jsv8_inherit"); + + String *base_name_mangled = SwigType_manglestr(base_name); + t_inherit.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsbaseclass", base_name_mangled) + .trim() + .pretty_print(f_init_inheritance); + Delete(base_name_mangled); + } + // emit 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() + .pretty_print(f_init_static_wrappers); + } else { + Template t_register = getTemplate("jsv8_register_member_variable"); + t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsname", state.variable(NAME)) + .replace("$jsgetter", state.variable(GETTER)) + .replace("$jssetter", state.variable(SETTER)) + .trim() + .pretty_print(f_init_wrappers); + } + } else { + // Note: a global variable is treated like a static variable + // with the parent being a nspace object (instead of class object) + Template t_register = getTemplate("jsv8_register_static_variable"); + t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED)) + .replace("$jsname", state.variable(NAME)) + .replace("$jsgetter", state.variable(GETTER)) + .replace("$jssetter", state.variable(SETTER)) + .trim() + .pretty_print(f_init_wrappers); + } + + return SWIG_OK; +} + +int V8Emitter::exitFunction(Node *n) { + bool is_member = GetFlag(n, "ismember") | 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() + .pretty_print(f_init_static_wrappers); + } else { + Template t_register = getTemplate("jsv8_register_member_function"); + t_register.replace("$jsmangledname", state.clazz(NAME_MANGLED)) + .replace("$jsname", state.function(NAME)) + .replace("$jswrapper", state.function(WRAPPER_NAME)) + .trim() + .pretty_print(f_init_wrappers); + } + } else { + // Note: a global function is treated like a static function + // with the parent being a nspace object instead of class object + Template t_register = getTemplate("jsv8_register_static_function"); + t_register.replace("$jsparent", Getattr(current_namespace, NAME_MANGLED)) + .replace("$jsname", state.function(NAME)) + .replace("$jswrapper", state.function(WRAPPER_NAME)) + .trim() + .pretty_print(f_init_static_wrappers); + } + + return SWIG_OK; +} + +void V8Emitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { + Parm *p; + String *tm; + + 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 + String *tmp_register_stmt = NewString(""); + t_register_ns.pretty_print(tmp_register_stmt); + Insert(f_init_register_namespaces, 0, tmp_register_stmt); + Delete(tmp_register_stmt); + } + } + + return SWIG_OK; +} + +JSEmitter *swig_javascript_create_V8Emitter() { + return new V8Emitter(); +} + +/********************************************************************** + * Helper implementations + **********************************************************************/ + +JSEmitterState::JSEmitterState() +: globalHash(NewHash()) { + // initialize sub-hashes + Setattr(globalHash, "class", NewHash()); + Setattr(globalHash, "function", NewHash()); + Setattr(globalHash, "variable", NewHash()); +} + +JSEmitterState::~JSEmitterState() { + Delete(globalHash); +} + +DOH *JSEmitterState::getState(const char *key, bool new_key) { + if (new_key) { + Hash *hash = NewHash(); + Setattr(globalHash, key, hash); + } + return Getattr(globalHash, key); +} + +DOH *JSEmitterState::globals() { + return globalHash; +} + +DOH *JSEmitterState::globals(const char *key, DOH *initial) { + if (initial != 0) { + Setattr(globalHash, key, initial); + } + return Getattr(globalHash, key); +} + +DOH *JSEmitterState::clazz(bool new_key) { + return getState("class", new_key); +} + +DOH *JSEmitterState::clazz(const char *key, DOH *initial) { + DOH *c = clazz(); + if (initial != 0) { + Setattr(c, key, initial); + } + return Getattr(c, key); +} + +DOH *JSEmitterState::function(bool new_key) { + return getState("function", new_key); +} + +DOH *JSEmitterState::function(const char *key, DOH *initial) { + DOH *f = function(); + if (initial != 0) { + Setattr(f, key, initial); + } + return Getattr(f, key); +} + +DOH *JSEmitterState::variable(bool new_key) { + return getState("variable", new_key); +} + +DOH *JSEmitterState::variable(const char *key, DOH *initial) { + DOH *v = variable(); + if (initial != 0) { + Setattr(v, key, initial); + } + return Getattr(v, key); +} + +/*static*/ +int JSEmitterState::IsSet(DOH *val) { + if (!val) { + return 0; + } else { + const char *cval = Char(val); + if (!cval) + return 0; + return (strcmp(cval, "0") != 0) ? 1 : 0; + } +} + +/* ----------------------------------------------------------------------------- + * Template::Template() : creates a Template class for given template code + * ----------------------------------------------------------------------------- */ + +Template::Template(const String *code_) { + + if (!code_) { + Printf(stdout, "Template code was null. Illegal input for template."); + 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/php.cxx b/Source/Modules/php.cxx index 86e1274a8..b07c82d3b 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -2054,7 +2054,6 @@ done: // Write property SET handlers ki = First(shadow_set_vars); - if (ki.key) { // This class has setters. Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n"); @@ -2077,17 +2076,6 @@ done: Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA); } Printf(s_phpclasses, "\t}\n"); - - /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */ - Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); - Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_set')) return true;\n", shadow_classname); - Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); - if (baseclass) { - Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); - } else { - Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); - } - Printf(s_phpclasses, "\t}\n"); } else { Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n"); Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR); @@ -2097,18 +2085,10 @@ done: Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA); } Printf(s_phpclasses, "\t}\n"); - Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); - Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); - if (baseclass) { - Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); - } else { - Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); - } - Printf(s_phpclasses, "\t}\n"); } + // Write property GET handlers ki = First(shadow_get_vars); - if (ki.key) { // This class has getters. Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); @@ -2144,6 +2124,19 @@ done: Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA); } Printf(s_phpclasses, "\t}\n"); + + /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */ + /* __isset() should return true for read-only properties, so check for + * *_get() not *_set(). */ + Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); + Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_get')) return true;\n", shadow_classname); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); + } + Printf(s_phpclasses, "\t}\n"); } else { Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); @@ -2153,6 +2146,14 @@ done: Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA); } Printf(s_phpclasses, "\t}\n"); + Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); + } + Printf(s_phpclasses, "\t}\n"); } if (!class_has_ctor) { diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index 7c9cded70..8a0861d17 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 { @@ -73,6 +74,7 @@ static swig_module modules[] = { {"-go", swig_go, "Go"}, {"-guile", swig_guile, "Guile"}, {"-java", swig_java, "Java"}, + {"-javascript", swig_javascript, "Javascript"}, {"-lua", swig_lua, "Lua"}, {"-modula3", swig_modula3, "Modula 3"}, {"-mzscheme", swig_mzscheme, "Mzscheme"}, diff --git a/Tools/javascript/Makefile.in b/Tools/javascript/Makefile.in new file mode 100644 index 000000000..373c5d952 --- /dev/null +++ b/Tools/javascript/Makefile.in @@ -0,0 +1,56 @@ +# ---------------------------------------------------------------- +# 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@ +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 100644 index 000000000..4c6334f2f --- /dev/null +++ b/Tools/javascript/v8_shell.cxx @@ -0,0 +1,313 @@ +#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); + + virtual bool _ExecuteScript(const std::string& source, const std::string& scriptPath); + +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() {} + +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(); + + bool success = _ExecuteScript(source, scriptPath); + + context->Exit(); + context.Dispose(); + v8::V8::Dispose(); + + return true; +} + +bool V8Shell::_ExecuteScript(const std::string& source, const std::string& scriptPath) { + 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; + } + + 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/configure.ac b/configure.ac index 547ea5b42..d83e0d31b 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 + #---------------------------------------------------------------- + + AC_CHECK_PROGS(NODEJS, node) + + if test -n "$NODEJS"; then + # node-gyp is needed to run the test-suite/examples + AC_CHECK_PROGS(NODEGYP, node-gyp) + if test -z "$NODEGYP"; then + NODEJS= + fi + fi + + #---------------------------------------------------------------- + # Look for JavascriptCore (Webkit) settings (JSCOREINCDIR, JSCOREDYNAMICLINKING) + #---------------------------------------------------------------- + + # check for include files + AC_MSG_CHECKING(for JavaScriptCore/JavaScript.h) + AC_ARG_WITH(jscoreinc, [ --with-jscinc=path Set location of Javascript include directory], [JSCOREINCDIR="$withval"], [JSCOREINCDIR=]) + + JSCOREVERSION= + + 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" + JSCOREVERSION=`pkg-config --modversion javascriptcoregtk-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 V8 Javascript v8.h) + AC_ARG_WITH(jsv8inc, [ --with-v8inc=path Set location of Javascript v8 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 Javascript library) + AC_ARG_WITH(jsv8lib,[ --with-v8lib=path Set location of V8 Javascript 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(JSLIBRARYPREFIX) +AC_SUBST(JSSO) +AC_SUBST(JSLDSHARED) +AC_SUBST(JSCXXSHARED) + +AC_SUBST(JSINTERPRETERCXX) +AC_SUBST(JSINTERPRETERLINKFLAGS) + +AC_SUBST(JSCOREINC) +AC_SUBST(JSCOREDYNAMICLINKING) +AC_SUBST(JSCOREVERSION) +AC_SUBST(JSV8INC) +AC_SUBST(JSV8DYNAMICLINKING) + +AC_SUBST(JSCENABLED) +AC_SUBST(JSV8ENABLED) + +AC_SUBST(NODEJS) +AC_SUBST(NODEGYP) + #---------------------------------------------------------------- # Look for gcj #---------------------------------------------------------------- @@ -2041,9 +2266,13 @@ else GOGCC=true GOVERSIONOPTION=--version AC_MSG_CHECKING([whether gccgo version is too old]) - go_version=`$GO $GOVERSIONOPTION | sed -e 's/[^0-9]* \([0-9.]*\) .*$/\1/' -e 's/[.]//g'` - if test "$go_version" -lt 470; then + go_version=[`$GO $GOVERSIONOPTION | sed -n '1p' | sed -e 's/^.* \([0-9.]*\) *$/\1/' -e 's/[.]//g'`] + if test "x$go_version" = x; then + AC_MSG_RESULT([could not determine gccgo version - disabling Go]) + GO= + elif test "$go_version" -lt 470; then AC_MSG_RESULT([yes - minimum version is 4.7.0]) + GO= else AC_MSG_RESULT([no]) if test "$go_version" -lt 480; then @@ -2238,6 +2467,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" && test -z "$JSCENABLED" && test -z "$JSV8ENABLED" ) ; then + SKIP_JAVASCRIPT="1" +fi +AC_SUBST(SKIP_JAVASCRIPT) SKIP_GUILE= if test -z "$GUILE" || test -z "$GUILE_LIBS" ; then @@ -2412,7 +2646,6 @@ AC_DEFINE_UNQUOTED(SWIG_LIB_WIN_UNIX, ["$SWIG_LIB_WIN_UNIX"], [Directory for SWI AC_CONFIG_FILES([ Makefile swig.spec - Source/Makefile Examples/Makefile Examples/xml/Makefile Examples/test-suite/errors/Makefile @@ -2421,6 +2654,7 @@ AC_CONFIG_FILES([ Examples/test-suite/d/Makefile Examples/test-suite/guile/Makefile Examples/test-suite/java/Makefile + Examples/test-suite/javascript/Makefile Examples/test-suite/mzscheme/Makefile Examples/test-suite/ocaml/Makefile Examples/test-suite/octave/Makefile @@ -2437,6 +2671,8 @@ AC_CONFIG_FILES([ Examples/test-suite/uffi/Makefile Examples/test-suite/r/Makefile Examples/test-suite/go/Makefile + Source/Makefile + Tools/javascript/Makefile ]) AC_CONFIG_FILES([preinst-swig], [chmod +x preinst-swig]) AC_CONFIG_FILES([CCache/ccache_swig_config.h])